From c6b9b7dd818012e78a7dc69bb6a86cfbe7b2d336 Mon Sep 17 00:00:00 2001 From: Paladz Date: Fri, 16 Jul 2021 12:33:02 +0800 Subject: [PATCH] edit check coinbase (#2040) * edit check coinbase * fix bug Co-authored-by: paladz --- protocol/validation/block.go | 67 +++++++++++++-------------------------- protocol/validation/block_test.go | 4 +-- 2 files changed, 24 insertions(+), 47 deletions(-) diff --git a/protocol/validation/block.go b/protocol/validation/block.go index 1ac5ed82..ddd7d45f 100644 --- a/protocol/validation/block.go +++ b/protocol/validation/block.go @@ -9,12 +9,11 @@ import ( "github.com/bytom/bytom/consensus" "github.com/bytom/bytom/crypto/ed25519/chainkd" "github.com/bytom/bytom/errors" - "github.com/bytom/bytom/protocol/bc" "github.com/bytom/bytom/protocol/bc/types" "github.com/bytom/bytom/protocol/state" ) -const logModule = "leveldb" +const logModule = "validation" var ( errBadTimestamp = errors.New("block timestamp is not in the valid range") @@ -38,69 +37,47 @@ func checkBlockTime(b, parent *types.BlockHeader) error { return nil } -func checkCoinbaseAmount(b *bc.Block, checkpoint *state.Checkpoint) error { +func checkCoinbaseAmount(b *types.Block, checkpoint *state.Checkpoint) error { if len(b.Transactions) == 0 { return errors.Wrap(ErrWrongCoinbaseTransaction, "block is empty") } tx := b.Transactions[0] - if len(tx.TxHeader.ResultIds) == 0 { - return errors.Wrap(ErrWrongCoinbaseTransaction, "tx header resultIds is empty") - } - - if b.Height%consensus.ActiveNetParams.BlocksOfEpoch != 1 || b.Height == 1 { - output, err := tx.OriginalOutput(*tx.TxHeader.ResultIds[0]) - if err != nil { - return err - } - - if output.Source.Value.Amount != 0 { - return errors.Wrap(ErrWrongCoinbaseTransaction, "dismatch output amount") + for _, output := range tx.Outputs { + if output.OutputType() != types.OriginalOutputType || *output.AssetId != *consensus.BTMAssetID { + return errors.Wrap(ErrWrongCoinbaseTransaction, "dismatch output type or asset") } + } - if len(tx.TxHeader.ResultIds) != 1 { - return errors.Wrap(ErrWrongCoinbaseTransaction, "have more than 1 output") + if b.Height%consensus.ActiveNetParams.BlocksOfEpoch != 1 { + if len(tx.Outputs) != 1 || tx.Outputs[0].Amount != 0 { + return errors.Wrap(ErrWrongCoinbaseTransaction, "dismatch output number or amount") } - return nil } return checkoutRewardCoinbase(tx, checkpoint) } -func checkoutRewardCoinbase(tx *bc.Tx, checkpoint *state.Checkpoint) error { - resultIdLen := len(tx.TxHeader.ResultIds) - if resultIdLen != len(checkpoint.Rewards) && resultIdLen != len(checkpoint.Rewards)+1 { - return errors.Wrap(ErrWrongCoinbaseTransaction) - } - - var startIndex int - if resultIdLen == len(checkpoint.Rewards)+1 { - output, err := tx.OriginalOutput(*tx.TxHeader.ResultIds[0]) - if err != nil { - return err - } - - if output.Source.Value.Amount != 0 { - return errors.Wrap(ErrWrongCoinbaseTransaction, "dismatch output amount") +func checkoutRewardCoinbase(tx *types.Tx, checkpoint *state.Checkpoint) error { + outputMap := map[string]uint64{} + for i, output := range tx.Outputs { + if i == 0 && output.Amount == 0 { + continue } - startIndex = 1 + outputMap[hex.EncodeToString(output.ControlProgram)] += output.Amount } - rewards := checkpoint.Rewards - for i := startIndex; i < resultIdLen; i++ { - output := tx.TxHeader.ResultIds[i] - out, err := tx.OriginalOutput(*output) - if err != nil { - return err - } + if len(outputMap) != len(checkpoint.Rewards) { + return errors.Wrap(ErrWrongCoinbaseTransaction, "dismatch output number") + } - if rewards[hex.EncodeToString(out.ControlProgram.Code)] != out.Source.Value.Amount { - return errors.Wrap(ErrWrongCoinbaseTransaction) + for cp, amount := range checkpoint.Rewards { + if outputMap[cp] != amount { + return errors.Wrap(ErrWrongCoinbaseTransaction, "dismatch output amount") } } - return nil } @@ -161,7 +138,7 @@ func ValidateBlock(b *types.Block, parent *types.BlockHeader, checkpoint *state. } } - if err := checkCoinbaseAmount(bcBlock, checkpoint); err != nil { + if err := checkCoinbaseAmount(b, checkpoint); err != nil { return err } diff --git a/protocol/validation/block_test.go b/protocol/validation/block_test.go index d468d2b6..0e5970e4 100644 --- a/protocol/validation/block_test.go +++ b/protocol/validation/block_test.go @@ -109,7 +109,7 @@ func TestCheckCoinbaseAmount(t *testing.T) { types.NewTx(types.TxData{ Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)}, Outputs: []*types.TxOutput{ - types.NewOriginalTxOutput(*consensus.BTMAssetID, 0, []byte("controlProgram"), nil), + types.NewOriginalTxOutput(*consensus.BTMAssetID, 0, []byte("controlProgramX1"), nil), types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram"), nil), }, }), @@ -171,7 +171,7 @@ func TestCheckCoinbaseAmount(t *testing.T) { } for i, c := range cases { - if err := checkCoinbaseAmount(types.MapBlock(c.block), c.checkpoint); rootErr(err) != c.err { + if err := checkCoinbaseAmount(c.block, c.checkpoint); rootErr(err) != c.err { t.Errorf("case %d got error %v, want %v", i, err, c.err) } } -- 2.11.0