You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #766 ("verify spend ownership in Unspend") added a mandatory server-side ownership check to the UDF unspend path: the caller must pass spend.SpendingData.Bytes() and the server compares it against the stored spending data before reversing the spend. Without the match, unspend is rejected.
PR #828 (feat/teranode-native-ops) migrates unspend to the native operate-path via subOpUnspend = 3. After the merge of #766 into the pr-828 branch, the client now forwards spend.SpendingData.Bytes() as the 3rd arg through both paths:
Native path (useNativeTeranodeOps = true): client packs the arg into the msgpack payload and the BSV-forked aerospike-server-private receives it on the wire. However, the subOpUnspend = 3 dispatcher in mod_teranode_native_op.c does not yet validate it — the arg arrives at the server but is ignored, so the ownership check is silently skipped. This is a security regression versus the UDF path.
What needs to change
Server-side (bsv-blockchain/aerospike-server-private, branch feat/teranode-native-op): update the subOpUnspend = 3 dispatcher in mod_teranode_native_op.c to accept the additional SpendingData []byte arg and apply the same ownership comparison the Lua unspend does. The client side is already forwarding the arg.
After the server-side update lands, no client-side change is required — the existing call passes the arg.
A unit/integration test against a BSV-forked aerospike-server should be added to cover ownership-mismatch rejection on the native path, mirroring the UDF-side tests in unspend_ownership_test.go.
Workaround until fixed
Keep aerospike_use_native_teranode_ops = false (the default) on any cluster where the ownership check matters. The UDF path still has the #766 fix end-to-end.
Context
PR #766 ("verify spend ownership in Unspend") added a mandatory server-side ownership check to the UDF
unspendpath: the caller must passspend.SpendingData.Bytes()and the server compares it against the stored spending data before reversing the spend. Without the match, unspend is rejected.PR #828 (
feat/teranode-native-ops) migratesunspendto the native operate-path viasubOpUnspend = 3. After the merge of #766 into the pr-828 branch, the client now forwardsspend.SpendingData.Bytes()as the 3rd arg through both paths:useNativeTeranodeOps = false, the default): server receives the arg, the Lua UDF validates ownership — the fix(utxo): verify spend ownership in Unspend #766 protection is preserved.useNativeTeranodeOps = true): client packs the arg into the msgpack payload and the BSV-forkedaerospike-server-privatereceives it on the wire. However, thesubOpUnspend = 3dispatcher inmod_teranode_native_op.cdoes not yet validate it — the arg arrives at the server but is ignored, so the ownership check is silently skipped. This is a security regression versus the UDF path.What needs to change
Server-side (
bsv-blockchain/aerospike-server-private, branchfeat/teranode-native-op): update thesubOpUnspend = 3dispatcher inmod_teranode_native_op.cto accept the additionalSpendingData []bytearg and apply the same ownership comparison the Lua unspend does. The client side is already forwarding the arg.After the server-side update lands, no client-side change is required — the existing call passes the arg.
A unit/integration test against a BSV-forked aerospike-server should be added to cover ownership-mismatch rejection on the native path, mirroring the UDF-side tests in
unspend_ownership_test.go.Workaround until fixed
Keep
aerospike_use_native_teranode_ops = false(the default) on any cluster where the ownership check matters. The UDF path still has the #766 fix end-to-end.References