// TestBlockSerializeSize performs tests to ensure the serialize size for // various blocks is accurate. func TestBlockSerializeSize(t *testing.T) { // Block with no transactions. noTxBlock := btcwire.NewMsgBlock(&blockOne.Header) tests := []struct { in *btcwire.MsgBlock // Block to encode size int // Expected serialized size }{ // Block with no transactions. {noTxBlock, 81}, // First block in the mainnet block chain. {&blockOne, len(blockOneBytes)}, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { serializedSize := test.in.SerializeSize() if serializedSize != test.size { t.Errorf("MsgBlock.SerializeSize: #%d got: %d, want: "+ "%d", i, serializedSize, test.size) continue } } }
// TestBlock tests the MsgBlock API. func TestBlock(t *testing.T) { pver := btcwire.ProtocolVersion // 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(1000000) 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 Test_dupTx(t *testing.T) { // Ignore db remove errors since it means we didn't have an old one. dbname := fmt.Sprintf("tstdbdup0") dbnamever := dbname + ".ver" _ = os.RemoveAll(dbname) _ = os.RemoveAll(dbnamever) db, err := btcdb.CreateDB("leveldb", dbname) if err != nil { t.Errorf("Failed to open test database %v", err) return } defer os.RemoveAll(dbname) defer os.RemoveAll(dbnamever) defer db.Close() testdatafile := filepath.Join("testdata", "blocks1-256.bz2") blocks, err := loadBlocks(t, testdatafile) if err != nil { t.Errorf("Unable to load blocks from test data for: %v", err) return } var lastSha *btcwire.ShaHash // Populate with the fisrt 256 blocks, so we have blocks to 'mess with' err = nil out: for height := int64(0); height < int64(len(blocks)); height++ { block := blocks[height] // except for NoVerify which does not allow lookups check inputs mblock := block.MsgBlock() var txneededList []*btcwire.ShaHash for _, tx := range mblock.Transactions { for _, txin := range tx.TxIn { if txin.PreviousOutpoint.Index == uint32(4294967295) { continue } origintxsha := &txin.PreviousOutpoint.Hash txneededList = append(txneededList, origintxsha) if !db.ExistsTxSha(origintxsha) { t.Errorf("referenced tx not found %v ", origintxsha) } _, err = db.FetchTxBySha(origintxsha) if err != nil { t.Errorf("referenced tx not found %v err %v ", origintxsha, err) } } } txlist := db.FetchUnSpentTxByShaList(txneededList) for _, txe := range txlist { if txe.Err != nil { t.Errorf("tx list fetch failed %v err %v ", txe.Sha, txe.Err) break out } } newheight, err := db.InsertBlock(block) if err != nil { t.Errorf("failed to insert block %v err %v", height, err) break out } if newheight != height { t.Errorf("height mismatch expect %v returned %v", height, newheight) break out } newSha, blkid, err := db.NewestSha() if err != nil { t.Errorf("failed to obtain latest sha %v %v", height, err) } if blkid != height { t.Errorf("height doe not match latest block height %v %v %v", blkid, height, err) } blkSha, _ := block.Sha() if *newSha != *blkSha { t.Errorf("Newest block sha does not match freshly inserted one %v %v %v ", newSha, blkSha, err) } lastSha = blkSha } // genrate a new block based on the last sha // these block are not verified, so there are a bunch of garbage fields // in the 'generated' block. var bh btcwire.BlockHeader bh.Version = 2 bh.PrevBlock = *lastSha // Bits, Nonce are not filled in mblk := btcwire.NewMsgBlock(&bh) hash, _ := btcwire.NewShaHashFromStr("df2b060fa2e5e9c8ed5eaf6a45c13753ec8c63282b2688322eba40cd98ea067a") po := btcwire.NewOutPoint(hash, 0) txI := btcwire.NewTxIn(po, []byte("garbage")) txO := btcwire.NewTxOut(50000000, []byte("garbageout")) var tx btcwire.MsgTx tx.AddTxIn(txI) tx.AddTxOut(txO) mblk.AddTransaction(&tx) blk := btcutil.NewBlock(mblk) fetchList := []*btcwire.ShaHash{hash} listReply := db.FetchUnSpentTxByShaList(fetchList) for _, lr := range listReply { if lr.Err != nil { t.Errorf("sha %v spent %v err %v\n", lr.Sha, lr.TxSpent, lr.Err) } } _, err = db.InsertBlock(blk) if err != nil { t.Errorf("failed to insert phony block %v", err) } // ok, did it 'spend' the tx ? listReply = db.FetchUnSpentTxByShaList(fetchList) for _, lr := range listReply { if lr.Err != btcdb.TxShaMissing { t.Errorf("sha %v spent %v err %v\n", lr.Sha, lr.TxSpent, lr.Err) } } txshalist, _ := blk.TxShas() for _, txsha := range txshalist { txReply, err := db.FetchTxBySha(txsha) if err != nil { t.Errorf("fully spent lookup %v err %v\n", hash, err) } else { for _, lr := range txReply { if lr.Err != nil { fmt.Errorf("stx %v spent %v err %v\n", lr.Sha, lr.TxSpent, lr.Err) } } } } t.Logf("Dropping block") err = db.DropAfterBlockBySha(lastSha) if err != nil { t.Errorf("failed to drop spending block %v", err) } }