// TestNewBlockFromBytes tests creation of a Block from serialized bytes. func TestNewBlockFromBytes(t *testing.T) { // Serialize the test block. var block100000Buf bytes.Buffer err := Block100000.Serialize(&block100000Buf) if err != nil { t.Errorf("Serialize: %v", err) } block100000Bytes := block100000Buf.Bytes() // Create a new block from the serialized bytes. b, err := btcutil.NewBlockFromBytes(block100000Bytes) if err != nil { t.Errorf("NewBlockFromBytes: %v", err) return } // Ensure we get the same data back out. serializedBytes, err := b.Bytes() if err != nil { t.Errorf("Bytes: %v", err) return } if !bytes.Equal(serializedBytes, block100000Bytes) { t.Errorf("Bytes: wrong bytes - got %v, want %v", spew.Sdump(serializedBytes), spew.Sdump(block100000Bytes)) } // Ensure the generated MsgBlock is correct. if msgBlock := b.MsgBlock(); !reflect.DeepEqual(msgBlock, &Block100000) { t.Errorf("MsgBlock: mismatched MsgBlock - got %v, want %v", spew.Sdump(msgBlock), spew.Sdump(&Block100000)) } }
// processBlock potentially imports the block into the database. It first // deserializes the raw block while checking for errors. Already known blocks // are skipped and orphan blocks are considered errors. Finally, it runs the // block through the chain rules to ensure it follows all rules and matches // up to the known checkpoint. Returns whether the block was imported along // with any potential errors. func (bi *blockImporter) processBlock(serializedBlock []byte) (bool, error) { // Deserialize the block which includes checks for malformed blocks. block, err := btcutil.NewBlockFromBytes(serializedBlock) if err != nil { return false, err } blockSha, err := block.Sha() if err != nil { return false, err } // update progress statistics bi.lastBlockTime = block.MsgBlock().Header.Timestamp bi.receivedLogTx += int64(len(block.MsgBlock().Transactions)) // Skip blocks that already exist. exists, err := bi.db.ExistsSha(blockSha) if err != nil { return false, err } if exists { return false, nil } // Don't bother trying to process orphans. prevHash := &block.MsgBlock().Header.PrevBlock if !prevHash.IsEqual(&zeroHash) { exists, err := bi.db.ExistsSha(prevHash) if err != nil { return false, err } if !exists { return false, fmt.Errorf("import file contains block "+ "%v which does not link to the available "+ "block chain", prevHash) } } // Ensure the blocks follows all of the chain rules and match up to the // known checkpoints. isOrphan, err := bi.chain.ProcessBlock(block, btcchain.BFFastAdd) if err != nil { return false, err } if isOrphan { return false, fmt.Errorf("import file contains an orphan "+ "block: %v", blockSha) } return true, nil }
// TestBlockErrors tests the error paths for the Block API. func TestBlockErrors(t *testing.T) { // Ensure out of range errors are as expected. wantErr := "transaction index -1 is out of range - max 3" testErr := btcutil.OutOfRangeError(wantErr) if testErr.Error() != wantErr { t.Errorf("OutOfRangeError: wrong error - got %v, want %v", testErr.Error(), wantErr) } // Serialize the test block. var block100000Buf bytes.Buffer err := Block100000.Serialize(&block100000Buf) if err != nil { t.Errorf("Serialize: %v", err) } block100000Bytes := block100000Buf.Bytes() // Create a new block from the serialized bytes. b, err := btcutil.NewBlockFromBytes(block100000Bytes) if err != nil { t.Errorf("NewBlockFromBytes: %v", err) return } // Truncate the block byte buffer to force errors. shortBytes := block100000Bytes[:80] _, err = btcutil.NewBlockFromBytes(shortBytes) if err != io.EOF { t.Errorf("NewBlockFromBytes: did not get expected error - "+ "got %v, want %v", err, io.EOF) } // Ensure TxSha returns expected error on invalid indices. _, err = b.TxSha(-1) if _, ok := err.(btcutil.OutOfRangeError); !ok { t.Errorf("TxSha: wrong error - got: %v <%T>, "+ "want: <%T>", err, err, btcutil.OutOfRangeError("")) } _, err = b.TxSha(len(Block100000.Transactions) + 1) if _, ok := err.(btcutil.OutOfRangeError); !ok { t.Errorf("TxSha: wrong error - got: %v <%T>, "+ "want: <%T>", err, err, btcutil.OutOfRangeError("")) } // Ensure Tx returns expected error on invalid indices. _, err = b.Tx(-1) if _, ok := err.(btcutil.OutOfRangeError); !ok { t.Errorf("Tx: wrong error - got: %v <%T>, "+ "want: <%T>", err, err, btcutil.OutOfRangeError("")) } _, err = b.Tx(len(Block100000.Transactions) + 1) if _, ok := err.(btcutil.OutOfRangeError); !ok { t.Errorf("Tx: wrong error - got: %v <%T>, "+ "want: <%T>", err, err, btcutil.OutOfRangeError("")) } // Ensure TxLoc returns expected error with short byte buffer. // This makes use of the test package only function, SetBlockBytes, to // inject a short byte buffer. b.SetBlockBytes(shortBytes) _, err = b.TxLoc() if err != io.EOF { t.Errorf("TxLoc: did not get expected error - "+ "got %v, want %v", err, io.EOF) } }