This example demonstrates how to use the spv and transaction packages to perform a comprehensive verification of a transaction, including its scripts and Merkle proof (from BEEF data).
The verify_transaction example showcases:
- Starting with a hexadecimal string representing BEEF data (which includes the transaction and its Merkle path).
- Creating a
transaction.Transactionobject from this hex string usingtransaction.NewTransactionFromBEEFHex. - Calling the
spv.Verifyfunction to perform a series of checks. - Using
spv.GullibleHeadersClientas a placeholder for actual block header validation.
The spv.Verify function typically checks:
- The internal consistency and validity of the BEEF structure.
- The syntactic validity of the transaction's input and output scripts.
- The correctness of the Merkle path against the transaction ID (i.e., the transaction is correctly placed in its purported Merkle tree).
- (Optionally) Fee verification if a
FeeVerifieris provided. - Confirmation of the Merkle root against a block header obtained via the
spv.Headersclient.
// BEEF data as a hex string (truncated for brevity)
const BEEFHex = "0100beef01fe636d0c0007021400fe507c0c7aa754cef1f7889d5fd395cf1f785dd7de98eed895dbedfe4e5bc70d1502ac4e164f5bc16746bb0868404292ac8318bbac3800e4aad13a014da427adce3e010b00bc4ff395efd11719b277694cface5aa50d085a0bb81f613f70313acd28cf4557010400574b2d9142b8d28b61d88e3b2c3f44d858411356b49a28a4643b6d1a6a092a5201030051a05fc84d531b5d250c23f4f886f6812f9fe3f402d61607f977b4ecd2701c19010000fd781529d58fc2523cf396a7f25440b409857e7e221766c57214b1d38c7b481f01010062f542f45ea3660f86c013ced80534cb5fd4c19d66c56e7e8c5d4bf2d40acc5e010100b121e91836fd7cd5102b654e9f72f3cf6fdbfd0b161c53a9c54b12c841126331020100000001cd4e4cac3c7b56920d1e7655e7e260d31f29d9a388d04910f1bbd72304a79029010000006b483045022100e75279a205a547c445719420aa3138bf14743e3f42618e5f86a19bde14bb95f7022064777d34776b05d816daf1699493fcdf2ef5a5ab1ad710d9c97bfb5b8f7cef3641210263e2dee22b1ddc5e11f6fab8bcd2378bdd19580d640501ea956ec0e786f93e76ffffffff013e660000000000001976a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac0000000001000100000001ac4e164f5bc16746bb0868404292ac8318bbac3800e4aad13a014da427adce3e000000006a47304402203a61a2e931612b4bda08d541cfb980885173b8dcf64a3471238ae7abcd368d6402204cbf24f04b9aa2256d8901f0ed97866603d2be8324c2bfb7a37bf8fc90edd5b441210263e2dee22b1ddc5e11f6fab8bcd2378bdd19580d640501ea956ec0e786f93e76ffffffff013c660000000000001976a9146bfd5c7fbe21529d45803dbcf0c87dd3c71efbc288ac0000000000"
// Create transaction from BEEF hex
tx, err := transaction.NewTransactionFromBEEFHex(BEEFHex)
if err != nil {
panic(err)
}
// Perform SPV verification
// This checks BEEF structure, script validity, Merkle path,
// and (conceptually) block header confirmation.
// GullibleHeadersClient trusts any header. No FeeVerifier is provided.
verified, _ := spv.Verify(tx, &spv.GullibleHeadersClient{}, nil)
println(verified)This section shows loading a transaction from BEEF hex. The spv.Verify function is then called. It uses the MerklePath embedded within the tx object (which comes from the BEEF data) and the provided spv.Headers client.
Because spv.GullibleHeadersClient is used, the block header check will always pass. Thus, verified will be true if the BEEF structure is valid, the transaction scripts are syntactically correct, and the Merkle path correctly proves the transaction's inclusion in some Merkle tree. It does not, with this client, confirm that the transaction is in a block on the actual main chain.
To run this example:
go run verify_transaction.goThe output will be true if the transaction passes all checks relative to the GullibleHeadersClient (i.e., scripts are valid, Merkle proof is internally consistent).
Note:
- The example uses a hardcoded BEEF hex string.
spv.GullibleHeadersClientis used for simplicity. For true SPV, aheaders_client.Clientconnected to a real headers service should be used.- A
FeeVerifier(the third argument tospv.Verify) can be provided to check if the transaction pays adequate fees, but it'snilin this example.
To integrate transaction verification into your application:
- Obtain the transaction data, preferably in BEEF format (hex or binary) to include the Merkle proof.
- Create a
transaction.Transactionobject (e.g., usingtransaction.NewTransactionFromBEEFHex()). - Initialize a proper
spv.Headersclient, likeheaders_client.Client, configured for your network and a trusted headers source. - (Optional) Create and configure a
FeeVerifierif you need to check transaction fees. - Call
spv.Verify(yourTransaction, yourHeadersClient, yourFeeVerifier).- A
trueresult indicates the transaction is valid, confirmed, and (if applicable) meets fee requirements according to your provided clients. - A
falseresult or an error indicates a failure in one of the verification steps.
- A
For more information, see: