X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=protocol%2Fvalidation%2Fblock.go;h=8ea143c0d5083c0a87907181fdd62dfff3c88d47;hb=3c4421ccea81457046e3ff00e46fa9f6692204de;hp=e55e22c09193870e75e163c412cc9fdbe447ba2d;hpb=cc968002ceac2dfd7665c2ac2b4c32ab6017b525;p=bytom%2Fvapor.git diff --git a/protocol/validation/block.go b/protocol/validation/block.go index e55e22c0..8ea143c0 100644 --- a/protocol/validation/block.go +++ b/protocol/validation/block.go @@ -5,13 +5,10 @@ import ( log "github.com/sirupsen/logrus" - "github.com/vapor/chain" "github.com/vapor/consensus" - engine "github.com/vapor/consensus/consensus" "github.com/vapor/errors" "github.com/vapor/protocol/bc" "github.com/vapor/protocol/bc/types" - "github.com/vapor/protocol/state" ) const logModule = "leveldb" @@ -27,14 +24,15 @@ var ( errVersionRegression = errors.New("version regression") ) -func checkBlockTime(b *bc.Block, parent *state.BlockNode) error { - if b.Timestamp > uint64(time.Now().Unix())+consensus.MaxTimeOffsetSeconds { +func checkBlockTime(b *bc.Block, parent *types.BlockHeader) error { + now := uint64(time.Now().UnixNano() / 1e6) + if b.Timestamp < (parent.Timestamp + consensus.BlockTimeInterval) { return errBadTimestamp } - - if b.Timestamp <= parent.CalcPastMedianTime() { + if b.Timestamp > (now + consensus.MaxTimeOffsetMs) { return errBadTimestamp } + return nil } @@ -44,70 +42,63 @@ func checkCoinbaseAmount(b *bc.Block, amount uint64) error { } tx := b.Transactions[0] - output, err := tx.Output(*tx.TxHeader.ResultIds[0]) - if err != nil { - return err + if len(tx.TxHeader.ResultIds) != 1 { + return errors.Wrap(ErrWrongCoinbaseTransaction, "have more than 1 output") } - if output.Source.Value.Amount != amount { + var SourceAmount uint64 + switch output := tx.Entries[*tx.TxHeader.ResultIds[0]].(type) { + case *bc.IntraChainOutput: + SourceAmount = output.Source.Value.Amount + case *bc.VoteOutput: + SourceAmount = output.Source.Value.Amount + default: + return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", tx.TxHeader.ResultIds[0].Bytes(), output) + } + + if SourceAmount != amount { return errors.Wrap(ErrWrongCoinbaseTransaction, "dismatch output amount") } return nil } // ValidateBlockHeader check the block's header -func ValidateBlockHeader(b *bc.Block, block *types.Block, parent *state.BlockNode, c chain.Chain, engine engine.Engine) error { - if b.Version < parent.Version { +func ValidateBlockHeader(b *bc.Block, parent *types.BlockHeader) error { + if b.Version != 1 { return errors.WithDetailf(errVersionRegression, "previous block verson %d, current block version %d", parent.Version, b.Version) } if b.Height != parent.Height+1 { return errors.WithDetailf(errMisorderedBlockHeight, "previous block height %d, current block height %d", parent.Height, b.Height) } - if parent.Hash != *b.PreviousBlockId { - return errors.WithDetailf(errMismatchedBlock, "previous block ID %x, current block wants %x", parent.Hash.Bytes(), b.PreviousBlockId.Bytes()) - } - if err := checkBlockTime(b, parent); err != nil { - return err - } - if err := engine.VerifyHeader(c, &block.BlockHeader, false); err != nil { - return err + if parent.Hash() != *b.PreviousBlockId { + return errors.WithDetailf(errMismatchedBlock, "previous block ID %x, current block wants %x", parent.Hash().Bytes(), b.PreviousBlockId.Bytes()) } - return nil + return checkBlockTime(b, parent) } // ValidateBlock validates a block and the transactions within. -func ValidateBlock(b *bc.Block, parent *state.BlockNode, block *types.Block, c chain.Chain, engine engine.Engine, authoritys map[string]string, position uint64) error { +func ValidateBlock(b *bc.Block, parent *types.BlockHeader) error { startTime := time.Now() - if err := ValidateBlockHeader(b, block, parent, c, engine); err != nil { + if err := ValidateBlockHeader(b, parent); err != nil { return err } - /* - time.Sleep(3 * time.Second) - // 验证出块人 - controlProgram := hex.EncodeToString(block.Proof.ControlProgram) - xpub := &chainkd.XPub{} - xpub.UnmarshalText([]byte(authoritys[controlProgram])) - msg := block.BlockCommitment.TransactionsMerkleRoot.Bytes() - if !xpub.Verify(msg, block.Proof.Sign) { - return errors.New("Verification signature failed") - } - */ blockGasSum := uint64(0) coinbaseAmount := consensus.BlockSubsidy(b.BlockHeader.Height) b.TransactionStatus = bc.NewTransactionStatus() - for i, tx := range b.Transactions { - gasStatus, err := ValidateTx(tx, b) - if !gasStatus.GasValid { - return errors.Wrapf(err, "validate of transaction %d of %d", i, len(b.Transactions)) + + validateResults := ValidateTxs(b.Transactions, b) + for i, validateResult := range validateResults { + if !validateResult.gasStatus.GasValid { + return errors.Wrapf(validateResult.err, "validate of transaction %d of %d", i, len(b.Transactions)) } - if err := b.TransactionStatus.SetStatus(i, err != nil); err != nil { + if err := b.TransactionStatus.SetStatus(i, validateResult.err != nil); err != nil { return err } - coinbaseAmount += gasStatus.BTMValue - if blockGasSum += uint64(gasStatus.GasUsed); blockGasSum > consensus.MaxBlockGas { + coinbaseAmount += validateResult.gasStatus.BTMValue + if blockGasSum += uint64(validateResult.gasStatus.GasUsed); blockGasSum > consensus.MaxBlockGas { return errOverBlockLimit } } @@ -121,7 +112,7 @@ func ValidateBlock(b *bc.Block, parent *state.BlockNode, block *types.Block, c c return errors.Wrap(err, "computing transaction id merkle root") } if txMerkleRoot != *b.TransactionsRoot { - return errors.WithDetailf(errMismatchedMerkleRoot, "transaction id merkle root") + return errors.WithDetailf(errMismatchedMerkleRoot, "transaction id merkle root. compute: %v, given: %v", txMerkleRoot, *b.TransactionsRoot) } txStatusHash, err := types.TxStatusMerkleRoot(b.TransactionStatus.VerifyStatus)