// Copyright (c) 2013 Conformal Systems LLC. // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package btcwire_test import ( "bytes" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" "reflect" "testing" "time" ) // TestBlock tests the MsgBlock API. func TestBlock(t *testing.T) { pver := uint32(60002) // Block 1 header. prevHash := &blockOne.Header.PrevBlock merkleHash := &blockOne.Header.MerkleRoot bits := blockOne.Header.Bits nonce := blockOne.Header.Nonce bh := btcwire.NewBlockHeader(prevHash, merkleHash, bits, nonce) // Ensure the command is expected value. wantCmd := "block" msg := btcwire.NewMsgBlock(bh) if cmd := msg.Command(); cmd != wantCmd { t.Errorf("NewMsgBlock: wrong command - got %v want %v", cmd, wantCmd) } // Ensure max payload is expected value for latest protocol version. // Num addresses (varInt) + max allowed addresses. wantPayload := uint32(1024 * 1024 * 32) maxPayload := msg.MaxPayloadLength(pver) if maxPayload != wantPayload { t.Errorf("MaxPayloadLength: wrong max payload length for "+ "protocol version %d - got %v, want %v", pver, maxPayload, wantPayload) } // Ensure we get the same block header data back out. if !reflect.DeepEqual(&msg.Header, bh) { t.Errorf("NewMsgBlock: wrong block header - got %v, want %v", spew.Sdump(&msg.Header), spew.Sdump(bh)) } // Ensure transactions are added properly. tx := blockOne.Transactions[0].Copy() msg.AddTransaction(tx) if !reflect.DeepEqual(msg.Transactions, blockOne.Transactions) { t.Errorf("AddTransaction: wrong transactions - got %v, want %v", spew.Sdump(msg.Transactions), spew.Sdump(blockOne.Transactions)) } // Ensure transactions are properly cleared. msg.ClearTransactions() if len(msg.Transactions) != 0 { t.Errorf("ClearTransactions: wrong transactions - got %v, want %v", len(msg.Transactions), 0) } return } func TestBlockTxShas(t *testing.T) { pver := btcwire.ProtocolVersion // Block 1, transaction 1 hash. hashStr := "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098" wantHash, err := btcwire.NewShaHashFromStr(hashStr) if err != nil { t.Errorf("NewShaHashFromStr: %v", err) return } wantShas := []btcwire.ShaHash{*wantHash} shas, err := blockOne.TxShas(pver) if err != nil { t.Errorf("TxShas: %v", err) } if !reflect.DeepEqual(shas, wantShas) { t.Errorf("TxShas: wrong transaction hashes - got %v, want %v", spew.Sdump(shas), spew.Sdump(wantShas)) } } func TestBlockSha(t *testing.T) { pver := btcwire.ProtocolVersion // Block 1 hash. hashStr := "839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048" wantHash, err := btcwire.NewShaHashFromStr(hashStr) if err != nil { t.Errorf("NewShaHashFromStr: %v", err) } // Ensure the hash produced is expected. blockHash, err := blockOne.BlockSha(pver) if err != nil { t.Errorf("BlockSha: %v", err) } if !blockHash.IsEqual(wantHash) { t.Errorf("BlockSha: wrong hash - got %v, want %v", spew.Sprint(blockHash), spew.Sprint(wantHash)) } } // TestBlockWire tests the MsgBlock wire encode and decode for various numbers // of transaction inputs and outputs and protocol versions. func TestBlockWire(t *testing.T) { tests := []struct { in *btcwire.MsgBlock // Message to encode out *btcwire.MsgBlock // Expected decoded message buf []byte // Wire encoding pver uint32 // Protocol version for wire encoding }{ // Latest protocol version. { &blockOne, &blockOne, blockOneBytes, btcwire.ProtocolVersion, }, // Protocol version BIP0035Version. { &blockOne, &blockOne, blockOneBytes, btcwire.BIP0035Version, }, // Protocol version BIP0031Version. { &blockOne, &blockOne, blockOneBytes, btcwire.BIP0031Version, }, // Protocol version NetAddressTimeVersion. { &blockOne, &blockOne, blockOneBytes, btcwire.NetAddressTimeVersion, }, // Protocol version MultipleAddressVersion. { &blockOne, &blockOne, blockOneBytes, btcwire.MultipleAddressVersion, }, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { // Encode the message to wire format. var buf bytes.Buffer err := test.in.BtcEncode(&buf, test.pver) if err != nil { t.Errorf("BtcEncode #%d error %v", i, err) continue } if !bytes.Equal(buf.Bytes(), test.buf) { t.Errorf("BtcEncode #%d\n got: %s want: %s", i, spew.Sdump(buf.Bytes()), spew.Sdump(test.buf)) continue } // Decode the message from wire format. var msg btcwire.MsgBlock rbuf := bytes.NewBuffer(test.buf) err = msg.BtcDecode(rbuf, test.pver) if err != nil { t.Errorf("BtcDecode #%d error %v", i, err) continue } if !reflect.DeepEqual(&msg, test.out) { t.Errorf("BtcDecode #%d\n got: %s want: %s", i, spew.Sdump(&msg), spew.Sdump(test.out)) continue } } } var blockOne btcwire.MsgBlock = btcwire.MsgBlock{ Header: btcwire.BlockHeader{ Version: 1, PrevBlock: btcwire.ShaHash{ 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, }, MerkleRoot: btcwire.ShaHash{ 0x98, 0x20, 0x51, 0xfd, 0x1e, 0x4b, 0xa7, 0x44, 0xbb, 0xbe, 0x68, 0x0e, 0x1f, 0xee, 0x14, 0x67, 0x7b, 0xa1, 0xa3, 0xc3, 0x54, 0x0b, 0xf7, 0xb1, 0xcd, 0xb6, 0x06, 0xe8, 0x57, 0x23, 0x3e, 0x0e, }, Timestamp: time.Unix(0x4966bc61, 0), // 2009-01-08 20:54:25 -0600 CST Bits: 0x1d00ffff, // 486604799 Nonce: 0x9962e301, // 2573394689 TxnCount: 1, }, Transactions: []*btcwire.MsgTx{ &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ &btcwire.TxIn{ PreviousOutpoint: btcwire.OutPoint{ Hash: btcwire.ShaHash{}, Index: 0xffffffff, }, SignatureScript: []byte{ 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, }, Sequence: 0xffffffff, }, }, TxOut: []*btcwire.TxOut{ &btcwire.TxOut{ Value: 0x12a05f200, PkScript: []byte{ 0x41, // OP_DATA_65 0x04, 0x96, 0xb5, 0x38, 0xe8, 0x53, 0x51, 0x9c, 0x72, 0x6a, 0x2c, 0x91, 0xe6, 0x1e, 0xc1, 0x16, 0x00, 0xae, 0x13, 0x90, 0x81, 0x3a, 0x62, 0x7c, 0x66, 0xfb, 0x8b, 0xe7, 0x94, 0x7b, 0xe6, 0x3c, 0x52, 0xda, 0x75, 0x89, 0x37, 0x95, 0x15, 0xd4, 0xe0, 0xa6, 0x04, 0xf8, 0x14, 0x17, 0x81, 0xe6, 0x22, 0x94, 0x72, 0x11, 0x66, 0xbf, 0x62, 0x1e, 0x73, 0xa8, 0x2c, 0xbf, 0x23, 0x42, 0xc8, 0x58, 0xee, // 65-byte signature 0xac, // OP_CHECKSIG }, }, }, LockTime: 0, }, }, } var blockOneBytes = []byte{ 0x01, 0x00, 0x00, 0x00, // Version 1 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, // PrevBlock 0x98, 0x20, 0x51, 0xfd, 0x1e, 0x4b, 0xa7, 0x44, 0xbb, 0xbe, 0x68, 0x0e, 0x1f, 0xee, 0x14, 0x67, 0x7b, 0xa1, 0xa3, 0xc3, 0x54, 0x0b, 0xf7, 0xb1, 0xcd, 0xb6, 0x06, 0xe8, 0x57, 0x23, 0x3e, 0x0e, // MerkleRoot 0x61, 0xbc, 0x66, 0x49, // Timestamp 0xff, 0xff, 0x00, 0x1d, // Bits 0x01, 0xe3, 0x62, 0x99, // Nonce 0x01, // TxnCount 0x01, 0x00, 0x00, 0x00, // Version 0x01, // Varint for number of input transactions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // // Previous output hash 0xff, 0xff, 0xff, 0xff, // Prevous output index 0x07, // Varint for length of signature script 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, // Signature script 0xff, 0xff, 0xff, 0xff, // Sequence 0x01, // Varint for number of output transactions 0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, // Transaction amount 0x43, // Varint for length of pk script 0x41, // OP_DATA_65 0x04, 0x96, 0xb5, 0x38, 0xe8, 0x53, 0x51, 0x9c, 0x72, 0x6a, 0x2c, 0x91, 0xe6, 0x1e, 0xc1, 0x16, 0x00, 0xae, 0x13, 0x90, 0x81, 0x3a, 0x62, 0x7c, 0x66, 0xfb, 0x8b, 0xe7, 0x94, 0x7b, 0xe6, 0x3c, 0x52, 0xda, 0x75, 0x89, 0x37, 0x95, 0x15, 0xd4, 0xe0, 0xa6, 0x04, 0xf8, 0x14, 0x17, 0x81, 0xe6, 0x22, 0x94, 0x72, 0x11, 0x66, 0xbf, 0x62, 0x1e, 0x73, 0xa8, 0x2c, 0xbf, 0x23, 0x42, 0xc8, 0x58, 0xee, // 65-byte signature 0xac, // OP_CHECKSIG 0x00, 0x00, 0x00, 0x00, // Lock time }