wire: Remove errs from BlockHeader/MsgBlock/MsgTx.

This commit removes the error returns from the BlockHeader.BlockSha,
MsgBlock.BlockSha, and MsgTx.TxSha functions since they can never fail and
end up causing a lot of unneeded error checking throughout the code base.

It also updates all call sites for the change.
This commit is contained in:
Dave Collins 2015-04-17 01:09:21 -05:00
parent 88fd338420
commit a4a52ae24f
18 changed files with 36 additions and 115 deletions

View file

@ -176,10 +176,7 @@ func loadTxStore(filename string) (blockchain.TxStore, error) {
txD.Tx = btcutil.NewTx(&msgTx) txD.Tx = btcutil.NewTx(&msgTx)
// Transaction hash. // Transaction hash.
txHash, err := msgTx.TxSha() txHash := msgTx.TxSha()
if err != nil {
return nil, err
}
txD.Hash = &txHash txD.Hash = &txHash
// Block height the transaction came from. // Block height the transaction came from.

View file

@ -799,14 +799,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) {
receivedCheckpoint := false receivedCheckpoint := false
var finalHash *wire.ShaHash var finalHash *wire.ShaHash
for _, blockHeader := range msg.Headers { for _, blockHeader := range msg.Headers {
blockHash, err := blockHeader.BlockSha() blockHash := blockHeader.BlockSha()
if err != nil {
bmgrLog.Warnf("Failed to compute hash of header "+
"received from peer %s -- disconnecting",
hmsg.peer.addr)
hmsg.peer.Disconnect()
return
}
finalHash = &blockHash finalHash = &blockHash
// Ensure there is a previous header to compare against. // Ensure there is a previous header to compare against.

View file

@ -30,10 +30,7 @@ func TestGenesisBlock(t *testing.T) {
} }
// Check hash of the block against expected hash. // Check hash of the block against expected hash.
hash, err := chaincfg.MainNetParams.GenesisBlock.BlockSha() hash := chaincfg.MainNetParams.GenesisBlock.BlockSha()
if err != nil {
t.Fatalf("BlockSha: %v", err)
}
if !chaincfg.MainNetParams.GenesisHash.IsEqual(&hash) { if !chaincfg.MainNetParams.GenesisHash.IsEqual(&hash) {
t.Fatalf("TestGenesisBlock: Genesis block hash does not "+ t.Fatalf("TestGenesisBlock: Genesis block hash does not "+
"appear valid - got %v, want %v", spew.Sdump(hash), "appear valid - got %v, want %v", spew.Sdump(hash),
@ -60,10 +57,7 @@ func TestRegTestGenesisBlock(t *testing.T) {
} }
// Check hash of the block against expected hash. // Check hash of the block against expected hash.
hash, err := chaincfg.RegressionNetParams.GenesisBlock.BlockSha() hash := chaincfg.RegressionNetParams.GenesisBlock.BlockSha()
if err != nil {
t.Errorf("BlockSha: %v", err)
}
if !chaincfg.RegressionNetParams.GenesisHash.IsEqual(&hash) { if !chaincfg.RegressionNetParams.GenesisHash.IsEqual(&hash) {
t.Fatalf("TestRegTestGenesisBlock: Genesis block hash does "+ t.Fatalf("TestRegTestGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", spew.Sdump(hash), "not appear valid - got %v, want %v", spew.Sdump(hash),
@ -90,10 +84,7 @@ func TestTestNet3GenesisBlock(t *testing.T) {
} }
// Check hash of the block against expected hash. // Check hash of the block against expected hash.
hash, err := chaincfg.TestNet3Params.GenesisBlock.BlockSha() hash := chaincfg.TestNet3Params.GenesisBlock.BlockSha()
if err != nil {
t.Fatalf("BlockSha: %v", err)
}
if !chaincfg.TestNet3Params.GenesisHash.IsEqual(&hash) { if !chaincfg.TestNet3Params.GenesisHash.IsEqual(&hash) {
t.Fatalf("TestTestNet3GenesisBlock: Genesis block hash does "+ t.Fatalf("TestTestNet3GenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", spew.Sdump(hash), "not appear valid - got %v, want %v", spew.Sdump(hash),
@ -120,10 +111,7 @@ func TestSimNetGenesisBlock(t *testing.T) {
} }
// Check hash of the block against expected hash. // Check hash of the block against expected hash.
hash, err := chaincfg.SimNetParams.GenesisBlock.BlockSha() hash := chaincfg.SimNetParams.GenesisBlock.BlockSha()
if err != nil {
t.Fatalf("BlockSha: %v", err)
}
if !chaincfg.SimNetParams.GenesisHash.IsEqual(&hash) { if !chaincfg.SimNetParams.GenesisHash.IsEqual(&hash) {
t.Fatalf("TestSimNetGenesisBlock: Genesis block hash does "+ t.Fatalf("TestSimNetGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", spew.Sdump(hash), "not appear valid - got %v, want %v", spew.Sdump(hash),

View file

@ -233,7 +233,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int64,
// increment the number of hashes completed for each // increment the number of hashes completed for each
// attempt accordingly. // attempt accordingly.
header.Nonce = i header.Nonce = i
hash, _ := header.BlockSha() hash := header.BlockSha()
hashesCompleted += 2 hashesCompleted += 2
// The block is solved when the new block hash is less // The block is solved when the new block hash is less

View file

@ -91,7 +91,7 @@ endtest:
t.Errorf("referenced tx not found %v ", origintxsha) t.Errorf("referenced tx not found %v ", origintxsha)
} }
} }
txshaname, _ := tx.TxSha() txshaname := tx.TxSha()
txlookupList = append(txlookupList, &txshaname) txlookupList = append(txlookupList, &txshaname)
txOutList = append(txOutList, &txshaname) txOutList = append(txOutList, &txshaname)
} }

View file

@ -367,7 +367,7 @@ func testBackout(t *testing.T) {
block := testDb.blocks[119] block := testDb.blocks[119]
mblock := block.MsgBlock() mblock := block.MsgBlock()
txsha, err := mblock.Transactions[0].TxSha() txsha := mblock.Transactions[0].TxSha()
exists, err := testDb.db.ExistsTxSha(&txsha) exists, err := testDb.db.ExistsTxSha(&txsha)
if err != nil { if err != nil {
t.Errorf("ExistsTxSha: unexpected error %v ", err) t.Errorf("ExistsTxSha: unexpected error %v ", err)

View file

@ -482,7 +482,7 @@ func (db *LevelDb) FetchTxsForAddr(addr btcutil.Address, skip int,
continue continue
} }
txSha, _ := tx.TxSha() txSha := tx.TxSha()
txReply := &database.TxListReply{Sha: &txSha, Tx: tx, txReply := &database.TxListReply{Sha: &txSha, Tx: tx,
BlkSha: blkSha, Height: blkHeight, TxSpent: []bool{}, Err: err} BlkSha: blkSha, Height: blkHeight, TxSpent: []bool{}, Err: err}

View file

@ -184,7 +184,7 @@ func (db *MemDb) DropAfterBlockBySha(sha *wire.ShaHash) error {
transactions := db.blocks[i].Transactions transactions := db.blocks[i].Transactions
for j := len(transactions) - 1; j >= 0; j-- { for j := len(transactions) - 1; j >= 0; j-- {
tx := transactions[j] tx := transactions[j]
txHash, _ := tx.TxSha() txHash := tx.TxSha()
db.removeTx(tx, &txHash) db.removeTx(tx, &txHash)
} }
@ -291,11 +291,7 @@ func (db *MemDb) FetchBlockShaByHeight(height int64) (*wire.ShaHash, error) {
} }
msgBlock := db.blocks[height] msgBlock := db.blocks[height]
blockHash, err := msgBlock.BlockSha() blockHash := msgBlock.BlockSha()
if err != nil {
return nil, err
}
return &blockHash, nil return &blockHash, nil
} }
@ -337,10 +333,7 @@ func (db *MemDb) FetchHeightRange(startHeight, endHeight int64) ([]wire.ShaHash,
} }
msgBlock := db.blocks[i] msgBlock := db.blocks[i]
blockHash, err := msgBlock.BlockSha() blockHash := msgBlock.BlockSha()
if err != nil {
return nil, err
}
hashList = append(hashList, blockHash) hashList = append(hashList, blockHash)
} }
@ -390,10 +383,7 @@ func (db *MemDb) FetchTxBySha(txHash *wire.ShaHash) ([]*database.TxListReply, er
replyList := make([]*database.TxListReply, len(txns)) replyList := make([]*database.TxListReply, len(txns))
for i, txD := range txns { for i, txD := range txns {
msgBlock := db.blocks[txD.blockHeight] msgBlock := db.blocks[txD.blockHeight]
blockSha, err := msgBlock.BlockSha() blockSha := msgBlock.BlockSha()
if err != nil {
return nil, err
}
spentBuf := make([]bool, len(txD.spentBuf)) spentBuf := make([]bool, len(txD.spentBuf))
copy(spentBuf, txD.spentBuf) copy(spentBuf, txD.spentBuf)
@ -455,11 +445,7 @@ func (db *MemDb) fetchTxByShaList(txShaList []*wire.ShaHash, includeSpent bool)
// the reply error appropriately and go to the next // the reply error appropriately and go to the next
// requested transaction if anything goes wrong. // requested transaction if anything goes wrong.
msgBlock := db.blocks[txD.blockHeight] msgBlock := db.blocks[txD.blockHeight]
blockSha, err := msgBlock.BlockSha() blockSha := msgBlock.BlockSha()
if err != nil {
reply.Err = err
continue
}
// Make a copy of the spent buf to return so the caller // Make a copy of the spent buf to return so the caller
// can't accidentally modify it. // can't accidentally modify it.
@ -685,11 +671,7 @@ func (db *MemDb) NewestSha() (*wire.ShaHash, int64, error) {
return &zeroHash, -1, nil return &zeroHash, -1, nil
} }
blockSha, err := db.blocks[numBlocks-1].BlockSha() blockSha := db.blocks[numBlocks-1].BlockSha()
if err != nil {
return nil, -1, err
}
return &blockSha, int64(numBlocks - 1), nil return &blockSha, int64(numBlocks - 1), nil
} }

View file

@ -55,10 +55,7 @@ func TestClosed(t *testing.T) {
} }
genesisCoinbaseTx := chaincfg.MainNetParams.GenesisBlock.Transactions[0] genesisCoinbaseTx := chaincfg.MainNetParams.GenesisBlock.Transactions[0]
coinbaseHash, err := genesisCoinbaseTx.TxSha() coinbaseHash := genesisCoinbaseTx.TxSha()
if err != nil {
t.Errorf("TxSha: unexpected error %v", err)
}
if _, err := db.ExistsTxSha(&coinbaseHash); err != memdb.ErrDbClosed { if _, err := db.ExistsTxSha(&coinbaseHash); err != memdb.ErrDbClosed {
t.Errorf("ExistsTxSha: unexpected error %v", err) t.Errorf("ExistsTxSha: unexpected error %v", err)
} }

6
log.go
View file

@ -314,15 +314,13 @@ func messageSummary(msg wire.Message) string {
// No summary. // No summary.
case *wire.MsgTx: case *wire.MsgTx:
hash, _ := msg.TxSha()
return fmt.Sprintf("hash %s, %d inputs, %d outputs, lock %s", return fmt.Sprintf("hash %s, %d inputs, %d outputs, lock %s",
hash, len(msg.TxIn), len(msg.TxOut), msg.TxSha(), len(msg.TxIn), len(msg.TxOut),
formatLockTime(msg.LockTime)) formatLockTime(msg.LockTime))
case *wire.MsgBlock: case *wire.MsgBlock:
header := &msg.Header header := &msg.Header
hash, _ := msg.BlockSha() return fmt.Sprintf("hash %s, ver %d, %d tx, %s", msg.BlockSha(),
return fmt.Sprintf("hash %s, ver %d, %d tx, %s", hash,
header.Version, len(msg.Transactions), header.Timestamp) header.Version, len(msg.Transactions), header.Timestamp)
case *wire.MsgInv: case *wire.MsgInv:

View file

@ -726,11 +726,10 @@ func handleDecodeRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan
Message: "TX decode failed: " + err.Error(), Message: "TX decode failed: " + err.Error(),
} }
} }
txHash, _ := mtx.TxSha()
// Create and return the result. // Create and return the result.
txReply := btcjson.TxRawDecodeResult{ txReply := btcjson.TxRawDecodeResult{
Txid: txHash.String(), Txid: mtx.TxSha().String(),
Version: mtx.Version, Version: mtx.Version,
Locktime: mtx.LockTime, Locktime: mtx.LockTime,
Vin: createVinList(&mtx), Vin: createVinList(&mtx),
@ -1357,7 +1356,7 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
transactions := make([]btcjson.GetBlockTemplateResultTx, 0, numTx-1) transactions := make([]btcjson.GetBlockTemplateResultTx, 0, numTx-1)
txIndex := make(map[wire.ShaHash]int64, numTx) txIndex := make(map[wire.ShaHash]int64, numTx)
for i, tx := range msgBlock.Transactions { for i, tx := range msgBlock.Transactions {
txHash, _ := tx.TxSha() txHash := tx.TxSha()
txIndex[txHash] = int64(i) txIndex[txHash] = int64(i)
// Skip the coinbase transaction. // Skip the coinbase transaction.
@ -1441,7 +1440,6 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
// Serialize the transaction for conversion to hex. // Serialize the transaction for conversion to hex.
tx := msgBlock.Transactions[0] tx := msgBlock.Transactions[0]
txHash, _ := tx.TxSha()
txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
if err := tx.Serialize(txBuf); err != nil { if err := tx.Serialize(txBuf); err != nil {
context := "Failed to serialize transaction" context := "Failed to serialize transaction"
@ -1450,7 +1448,7 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
resultTx := btcjson.GetBlockTemplateResultTx{ resultTx := btcjson.GetBlockTemplateResultTx{
Data: hex.EncodeToString(txBuf.Bytes()), Data: hex.EncodeToString(txBuf.Bytes()),
Hash: txHash.String(), Hash: tx.TxSha().String(),
Depends: []int64{}, Depends: []int64{},
Fee: template.fees[0], Fee: template.fees[0],
SigOps: template.sigOpCounts[0], SigOps: template.sigOpCounts[0],

View file

@ -111,12 +111,7 @@ func ExampleSignTxOutput() {
} }
txOut := wire.NewTxOut(100000000, pkScript) txOut := wire.NewTxOut(100000000, pkScript)
originTx.AddTxOut(txOut) originTx.AddTxOut(txOut)
originTxHash := originTx.TxSha()
originTxHash, err := originTx.TxSha()
if err != nil {
fmt.Println(err)
return
}
// Create the transaction to redeem the fake transaction. // Create the transaction to redeem the fake transaction.
redeemTx := wire.NewMsgTx() redeemTx := wire.NewMsgTx()

View file

@ -4140,7 +4140,7 @@ func ParseShortForm(script string) ([]byte, error) {
// createSpendTx generates a basic spending transaction given the passed // createSpendTx generates a basic spending transaction given the passed
// signature and public key scripts. // signature and public key scripts.
func createSpendingTx(sigScript, pkScript []byte) (*wire.MsgTx, error) { func createSpendingTx(sigScript, pkScript []byte) *wire.MsgTx {
coinbaseTx := wire.NewMsgTx() coinbaseTx := wire.NewMsgTx()
outPoint := wire.NewOutPoint(&wire.ShaHash{}, ^uint32(0)) outPoint := wire.NewOutPoint(&wire.ShaHash{}, ^uint32(0))
@ -4150,10 +4150,7 @@ func createSpendingTx(sigScript, pkScript []byte) (*wire.MsgTx, error) {
coinbaseTx.AddTxOut(txOut) coinbaseTx.AddTxOut(txOut)
spendingTx := wire.NewMsgTx() spendingTx := wire.NewMsgTx()
coinbaseTxSha, err := coinbaseTx.TxSha() coinbaseTxSha := coinbaseTx.TxSha()
if err != nil {
return nil, err
}
outPoint = wire.NewOutPoint(&coinbaseTxSha, 0) outPoint = wire.NewOutPoint(&coinbaseTxSha, 0)
txIn = wire.NewTxIn(outPoint, sigScript) txIn = wire.NewTxIn(outPoint, sigScript)
txOut = wire.NewTxOut(0, nil) txOut = wire.NewTxOut(0, nil)
@ -4161,7 +4158,7 @@ func createSpendingTx(sigScript, pkScript []byte) (*wire.MsgTx, error) {
spendingTx.AddTxIn(txIn) spendingTx.AddTxIn(txIn)
spendingTx.AddTxOut(txOut) spendingTx.AddTxOut(txOut)
return spendingTx, nil return spendingTx
} }
func TestBitcoindInvalidTests(t *testing.T) { func TestBitcoindInvalidTests(t *testing.T) {
@ -4204,11 +4201,7 @@ func TestBitcoindInvalidTests(t *testing.T) {
t.Errorf("%s: %v", name, err) t.Errorf("%s: %v", name, err)
continue continue
} }
tx, err := createSpendingTx(scriptSig, scriptPubKey) tx := createSpendingTx(scriptSig, scriptPubKey)
if err != nil {
t.Errorf("createSpendingTx failed on test %s: %v", name, err)
continue
}
s, err := NewScript(scriptSig, scriptPubKey, 0, tx, flags) s, err := NewScript(scriptSig, scriptPubKey, 0, tx, flags)
if err == nil { if err == nil {
if err := s.Execute(); err == nil { if err := s.Execute(); err == nil {
@ -4260,11 +4253,7 @@ func TestBitcoindValidTests(t *testing.T) {
t.Errorf("%s: %v", name, err) t.Errorf("%s: %v", name, err)
continue continue
} }
tx, err := createSpendingTx(scriptSig, scriptPubKey) tx := createSpendingTx(scriptSig, scriptPubKey)
if err != nil {
t.Errorf("createSpendingTx failed on test %s: %v", name, err)
continue
}
s, err := NewScript(scriptSig, scriptPubKey, 0, tx, flags) s, err := NewScript(scriptSig, scriptPubKey, 0, tx, flags)
if err != nil { if err != nil {
t.Errorf("%s failed to create script: %v", name, err) t.Errorf("%s failed to create script: %v", name, err)

View file

@ -45,7 +45,7 @@ type BlockHeader struct {
const blockHeaderLen = 80 const blockHeaderLen = 80
// BlockSha computes the block identifier hash for the given block header. // BlockSha computes the block identifier hash for the given block header.
func (h *BlockHeader) BlockSha() (ShaHash, error) { func (h *BlockHeader) BlockSha() ShaHash {
// Encode the header and double sha256 everything prior to the number of // Encode the header and double sha256 everything prior to the number of
// transactions. Ignore the error returns since there is no way the // transactions. Ignore the error returns since there is no way the
// encode could fail except being out of memory which would cause a // encode could fail except being out of memory which would cause a
@ -53,10 +53,7 @@ func (h *BlockHeader) BlockSha() (ShaHash, error) {
var buf bytes.Buffer var buf bytes.Buffer
_ = writeBlockHeader(&buf, 0, h) _ = writeBlockHeader(&buf, 0, h)
// Even though this function can't currently fail, it still returns return DoubleSha256SH(buf.Bytes())
// a potential error to help future proof the API should a failure
// become possible.
return DoubleSha256SH(buf.Bytes()), nil
} }
// Deserialize decodes a block header from r into the receiver using a format // Deserialize decodes a block header from r into the receiver using a format

View file

@ -225,7 +225,7 @@ func (msg *MsgBlock) MaxPayloadLength(pver uint32) uint32 {
} }
// BlockSha computes the block identifier hash for this block. // BlockSha computes the block identifier hash for this block.
func (msg *MsgBlock) BlockSha() (ShaHash, error) { func (msg *MsgBlock) BlockSha() ShaHash {
return msg.Header.BlockSha() return msg.Header.BlockSha()
} }
@ -233,10 +233,7 @@ func (msg *MsgBlock) BlockSha() (ShaHash, error) {
func (msg *MsgBlock) TxShas() ([]ShaHash, error) { func (msg *MsgBlock) TxShas() ([]ShaHash, error) {
shaList := make([]ShaHash, 0, len(msg.Transactions)) shaList := make([]ShaHash, 0, len(msg.Transactions))
for _, tx := range msg.Transactions { for _, tx := range msg.Transactions {
// Ignore error here since TxSha can't fail in the current shaList = append(shaList, tx.TxSha())
// implementation except due to run-time panics.
sha, _ := tx.TxSha()
shaList = append(shaList, sha)
} }
return shaList, nil return shaList, nil
} }

View file

@ -101,10 +101,7 @@ func TestBlockSha(t *testing.T) {
} }
// Ensure the hash produced is expected. // Ensure the hash produced is expected.
blockHash, err := blockOne.BlockSha() blockHash := blockOne.BlockSha()
if err != nil {
t.Errorf("BlockSha: %v", err)
}
if !blockHash.IsEqual(wantHash) { if !blockHash.IsEqual(wantHash) {
t.Errorf("BlockSha: wrong hash - got %v, want %v", t.Errorf("BlockSha: wrong hash - got %v, want %v",
spew.Sprint(blockHash), spew.Sprint(wantHash)) spew.Sprint(blockHash), spew.Sprint(wantHash))

View file

@ -166,18 +166,14 @@ func (msg *MsgTx) AddTxOut(to *TxOut) {
} }
// TxSha generates the ShaHash name for the transaction. // TxSha generates the ShaHash name for the transaction.
func (msg *MsgTx) TxSha() (ShaHash, error) { func (msg *MsgTx) TxSha() ShaHash {
// Encode the transaction and calculate double sha256 on the result. // Encode the transaction and calculate double sha256 on the result.
// Ignore the error returns since the only way the encode could fail // Ignore the error returns since the only way the encode could fail
// is being out of memory or due to nil pointers, both of which would // is being out of memory or due to nil pointers, both of which would
// cause a run-time panic. // cause a run-time panic.
buf := bytes.NewBuffer(make([]byte, 0, msg.SerializeSize())) buf := bytes.NewBuffer(make([]byte, 0, msg.SerializeSize()))
_ = msg.Serialize(buf) _ = msg.Serialize(buf)
return DoubleSha256SH(buf.Bytes())
// Even though this function can't currently fail, it still returns
// a potential error to help future proof the API should a failure
// become possible.
return DoubleSha256SH(buf.Bytes()), nil
} }
// Copy creates a deep copy of a transaction so that the original does not get // Copy creates a deep copy of a transaction so that the original does not get

View file

@ -169,10 +169,7 @@ func TestTxSha(t *testing.T) {
msgTx.LockTime = 0 msgTx.LockTime = 0
// Ensure the hash produced is expected. // Ensure the hash produced is expected.
txHash, err := msgTx.TxSha() txHash := msgTx.TxSha()
if err != nil {
t.Errorf("TxSha: %v", err)
}
if !txHash.IsEqual(wantHash) { if !txHash.IsEqual(wantHash) {
t.Errorf("TxSha: wrong hash - got %v, want %v", t.Errorf("TxSha: wrong hash - got %v, want %v",
spew.Sprint(txHash), spew.Sprint(wantHash)) spew.Sprint(txHash), spew.Sprint(wantHash))