From: muscle_boy Date: Wed, 17 Apr 2019 14:50:39 +0000 (+0800) Subject: politic (#1702) X-Git-Url: http://git.osdn.net/view?p=bytom%2Fbytom.git;a=commitdiff_plain;h=d7a1e6f0a36c68cb705be538fdb826dd6ade4e75 politic (#1702) * politic * refactor * update travis * fix ci * fix ci --- diff --git a/.travis.yml b/.travis.yml index b2483472..29ba9e0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ branches: only: - master - dev + - politic script: - make ci diff --git a/blockchain/txbuilder/finalize.go b/blockchain/txbuilder/finalize.go index 6e144497..1b63505e 100644 --- a/blockchain/txbuilder/finalize.go +++ b/blockchain/txbuilder/finalize.go @@ -39,10 +39,6 @@ func FinalizeTx(ctx context.Context, c *protocol.Chain, tx *types.Tx) error { return err } - if len(tx.GasInputIDs) == 0 { - return ErrNoGasInput - } - // This part is use for prevent tx size is 0 data, err := tx.TxData.MarshalText() if err != nil { diff --git a/consensus/difficulty/difficulty.go b/consensus/difficulty/difficulty.go index 5f5249ae..939f7e1c 100644 --- a/consensus/difficulty/difficulty.go +++ b/consensus/difficulty/difficulty.go @@ -4,7 +4,6 @@ import ( "math/big" "github.com/bytom/consensus" - "github.com/bytom/mining/tensority" "github.com/bytom/protocol/bc" "github.com/bytom/protocol/bc/types" ) @@ -118,8 +117,7 @@ func BigToCompact(n *big.Int) uint64 { // CheckProofOfWork checks whether the hash is valid for a given difficulty. func CheckProofOfWork(hash, seed *bc.Hash, bits uint64) bool { - compareHash := tensority.AIHash.Hash(hash, seed) - return HashToBig(compareHash).Cmp(CompactToBig(bits)) <= 0 + return true } // CalcNextRequiredDifficulty return the difficulty using compact representation diff --git a/consensus/difficulty/difficulty_test.go b/consensus/difficulty/difficulty_test.go index fbacde45..4a598705 100644 --- a/consensus/difficulty/difficulty_test.go +++ b/consensus/difficulty/difficulty_test.go @@ -6,333 +6,8 @@ import ( "strconv" "testing" - "github.com/bytom/consensus" "github.com/bytom/protocol/bc" - "github.com/bytom/protocol/bc/types" ) - -// A lower difficulty Int actually reflects a more difficult mining progress. -func TestCalcNextRequiredDifficulty(t *testing.T) { - targetTimeSpan := uint64(consensus.BlocksPerRetarget * consensus.TargetSecondsPerBlock) - cases := []struct { - lastBH *types.BlockHeader - compareBH *types.BlockHeader - want uint64 - }{ - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - }, - BigToCompact(big.NewInt(1000)), - }, - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan * 2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - }, - BigToCompact(big.NewInt(2000)), - }, - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan*2 - consensus.TargetSecondsPerBlock, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - }, - BigToCompact(big.NewInt(1000)), - }, - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan / 2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - }, - BigToCompact(big.NewInt(500)), - }, - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget * 2, - Timestamp: targetTimeSpan + targetTimeSpan*2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(2000)), - }, - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget * 2, - Timestamp: targetTimeSpan + targetTimeSpan/2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(500)), - }, - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget*2 - 1, - Timestamp: targetTimeSpan + targetTimeSpan*2 - consensus.TargetSecondsPerBlock, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(1000)), - }, - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget*2 - 1, - Timestamp: targetTimeSpan + targetTimeSpan/2 - consensus.TargetSecondsPerBlock, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(1000)), - }, - // lastBH.Height: 0, lastBH.Timestamp - compareBH.Timestamp: 0, lastBH.Bits: 0 - { - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - Bits: 0, - }, - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - }, - 0, - }, - // lastBH.Height: 0, lastBH.Timestamp - compareBH.Timestamp: 0, lastBH.Bits: 18446744073709551615 - { - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - Bits: 18446744073709551615, - }, - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - }, - 18446744073709551615, - }, - // lastBH.Height: 0, lastBH.Timestamp - compareBH.Timestamp: 0, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: 0, - Timestamp: 0, - }, - BigToCompact(big.NewInt(1000)), - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 0, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan, - }, - 0, - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: -9223372036854775808, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan + 9223372036854775808, - }, - 540431955291560988, - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 9223372036854775807, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan + 9223372036854775807, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan, - }, - 504403158272597019, - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 18446744073709551615, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: 18446744073709551615, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: 0, - }, - 108086391056957440, - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan * 2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(1000)), - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 604800, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan * 3, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan, - }, - 144115188076367872, - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 151200, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan + 9223372036854775807, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan, - }, - 504403158272597019, - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: 0 - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan * 2, - Bits: 0, - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan, - }, - 0, - }, - // lastBH.Height: consensus.BlocksPerRetarget, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: 18446744073709551615 - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan * 2, - Bits: 18446744073709551615, - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan, - }, - 252201579141136384, - }, - // lastBH.Height: consensus.BlocksPerRetarget + 1, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget + 1, - Timestamp: targetTimeSpan * 2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(1000)), - }, - // lastBH.Height: consensus.BlocksPerRetarget - 1, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 1, - Timestamp: targetTimeSpan * 2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget - 2, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(1000)), - }, - // lastBH.Height: consensus.BlocksPerRetarget * 2, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget * 2, - Timestamp: targetTimeSpan * 2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget*2 - 1, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(1000)), - }, - // lastBH.Height: consensus.BlocksPerRetarget / 2, lastBH.Timestamp - compareBH.Timestamp: 302400, lastBH.Bits: bigInt(1000) - { - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget / 2, - Timestamp: targetTimeSpan * 2, - Bits: BigToCompact(big.NewInt(1000)), - }, - &types.BlockHeader{ - Height: consensus.BlocksPerRetarget/2 - 1, - Timestamp: targetTimeSpan, - }, - BigToCompact(big.NewInt(1000)), - }, - } - - for i, c := range cases { - if got := CalcNextRequiredDifficulty(c.lastBH, c.compareBH); got != c.want { - t.Errorf("Compile(%d) = %d want %d\n", i, got, c.want) - return - } - } -} - func TestHashToBig(t *testing.T) { cases := []struct { in [32]byte diff --git a/consensus/general.go b/consensus/general.go index 1085ed82..4225685f 100644 --- a/consensus/general.go +++ b/consensus/general.go @@ -24,7 +24,7 @@ const ( // config for pow mining BlocksPerRetarget = uint64(2016) - TargetSecondsPerBlock = uint64(150) + TargetSecondsPerBlock = uint64(5) SeedPerRetarget = uint64(256) // MaxTimeOffsetSeconds is the maximum number of seconds a block time is allowed to be ahead of the current time diff --git a/mining/cpuminer/cpuminer.go b/mining/cpuminer/cpuminer.go index 6742e2eb..1e9afe41 100644 --- a/mining/cpuminer/cpuminer.go +++ b/mining/cpuminer/cpuminer.go @@ -7,11 +7,11 @@ import ( log "github.com/sirupsen/logrus" "github.com/bytom/account" - "github.com/bytom/consensus/difficulty" "github.com/bytom/event" "github.com/bytom/mining" "github.com/bytom/protocol" "github.com/bytom/protocol/bc/types" + "github.com/bytom/consensus" ) const ( @@ -42,12 +42,8 @@ type CPUMiner struct { // target difficulty. func (m *CPUMiner) solveBlock(block *types.Block, ticker *time.Ticker, quit chan struct{}) bool { header := &block.BlockHeader - seed, err := m.chain.CalcNextSeed(&header.PreviousBlockHash) - if err != nil { - return false - } - - for i := uint64(0); i <= maxNonce; i++ { + blockTimer := time.NewTimer(time.Second * time.Duration(consensus.TargetSecondsPerBlock)) + for { select { case <-quit: return false @@ -55,13 +51,9 @@ func (m *CPUMiner) solveBlock(block *types.Block, ticker *time.Ticker, quit chan if m.chain.BestBlockHeight() >= header.Height { return false } - default: - } - - header.Nonce = i - headerHash := header.Hash() - if difficulty.CheckProofOfWork(&headerHash, seed, header.Bits) { + case <-blockTimer.C: return true + default: } } return false diff --git a/protocol/txpool.go b/protocol/txpool.go index f24710c5..730b9f2c 100644 --- a/protocol/txpool.go +++ b/protocol/txpool.go @@ -211,7 +211,7 @@ func isTransactionZeroOutput(tx *types.Tx) bool { } func (tp *TxPool) IsDust(tx *types.Tx) bool { - return isTransactionNoBtmInput(tx) || isTransactionZeroOutput(tx) + return isTransactionZeroOutput(tx) } func (tp *TxPool) processTransaction(tx *types.Tx, statusFail bool, height, fee uint64) (bool, error) { diff --git a/protocol/txpool_test.go b/protocol/txpool_test.go index 243b39f1..42843593 100644 --- a/protocol/txpool_test.go +++ b/protocol/txpool_test.go @@ -4,8 +4,6 @@ import ( "testing" "time" - "github.com/davecgh/go-spew/spew" - "github.com/bytom/consensus" "github.com/bytom/database/storage" "github.com/bytom/event" @@ -605,95 +603,3 @@ func (s *mockStore1) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) func (s *mockStore1) LoadBlockIndex(uint64) (*state.BlockIndex, error) { return nil, nil } func (s *mockStore1) SaveBlock(*types.Block, *bc.TransactionStatus) error { return nil } func (s *mockStore1) SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error { return nil } - -func TestProcessTransaction(t *testing.T) { - txPool := &TxPool{ - pool: make(map[bc.Hash]*TxDesc), - utxo: make(map[bc.Hash]*types.Tx), - orphans: make(map[bc.Hash]*orphanTx), - orphansByPrev: make(map[bc.Hash]map[bc.Hash]*orphanTx), - store: &mockStore1{}, - eventDispatcher: event.NewDispatcher(), - } - cases := []struct { - want *TxPool - addTx *TxDesc - }{ - //Dust tx - { - want: &TxPool{}, - addTx: &TxDesc{ - Tx: testTxs[3], - StatusFail: false, - }, - }, - //Dust tx - { - want: &TxPool{}, - addTx: &TxDesc{ - Tx: testTxs[4], - StatusFail: false, - }, - }, - //Dust tx - { - want: &TxPool{}, - addTx: &TxDesc{ - Tx: testTxs[5], - StatusFail: false, - }, - }, - //Dust tx - { - want: &TxPool{}, - addTx: &TxDesc{ - Tx: testTxs[6], - StatusFail: false, - }, - }, - //normal tx - { - want: &TxPool{ - pool: map[bc.Hash]*TxDesc{ - testTxs[2].ID: { - Tx: testTxs[2], - StatusFail: false, - Weight: 150, - }, - }, - utxo: map[bc.Hash]*types.Tx{ - *testTxs[2].ResultIds[0]: testTxs[2], - *testTxs[2].ResultIds[1]: testTxs[2], - }, - }, - addTx: &TxDesc{ - Tx: testTxs[2], - StatusFail: false, - }, - }, - } - - for i, c := range cases { - txPool.ProcessTransaction(c.addTx.Tx, c.addTx.StatusFail, 0, 0) - for _, txD := range txPool.pool { - txD.Added = time.Time{} - } - for _, txD := range txPool.orphans { - txD.Added = time.Time{} - txD.expiration = time.Time{} - } - - if !testutil.DeepEqual(txPool.pool, c.want.pool) { - t.Errorf("case %d: test ProcessTransaction pool mismatch got %s want %s", i, spew.Sdump(txPool.pool), spew.Sdump(c.want.pool)) - } - if !testutil.DeepEqual(txPool.utxo, c.want.utxo) { - t.Errorf("case %d: test ProcessTransaction utxo mismatch got %s want %s", i, spew.Sdump(txPool.utxo), spew.Sdump(c.want.utxo)) - } - if !testutil.DeepEqual(txPool.orphans, c.want.orphans) { - t.Errorf("case %d: test ProcessTransaction orphans mismatch got %s want %s", i, spew.Sdump(txPool.orphans), spew.Sdump(c.want.orphans)) - } - if !testutil.DeepEqual(txPool.orphansByPrev, c.want.orphansByPrev) { - t.Errorf("case %d: test ProcessTransaction orphansByPrev mismatch got %s want %s", i, spew.Sdump(txPool.orphansByPrev), spew.Sdump(c.want.orphansByPrev)) - } - } -} diff --git a/protocol/validation/block_test.go b/protocol/validation/block_test.go deleted file mode 100644 index 8ac32c0f..00000000 --- a/protocol/validation/block_test.go +++ /dev/null @@ -1,510 +0,0 @@ -package validation - -import ( - "math" - "testing" - "time" - - "github.com/bytom/consensus" - "github.com/bytom/mining/tensority" - "github.com/bytom/protocol/bc" - "github.com/bytom/protocol/bc/types" - "github.com/bytom/protocol/state" - "github.com/bytom/protocol/vm" - "github.com/bytom/protocol/vm/vmutil" - "github.com/bytom/testutil" -) - -func TestCheckBlockTime(t *testing.T) { - cases := []struct { - desc string - blockTime uint64 - parentTime []uint64 - err error - }{ - { - blockTime: 1520000001, - parentTime: []uint64{1520000000}, - err: nil, - }, - { - desc: "timestamp less than past median time (blocktest#1005)", - blockTime: 1510000094, - parentTime: []uint64{1520000000, 1510000099, 1510000098, 1510000097, 1510000096, 1510000095, 1510000094, 1510000093, 1510000092, 1510000091, 1510000090}, - err: errBadTimestamp, - }, - { - desc: "timestamp greater than max limit (blocktest#1006)", - blockTime: 9999999999, - parentTime: []uint64{1520000000}, - err: errBadTimestamp, - }, - { - desc: "timestamp of the block and the parent block are both greater than max limit (blocktest#1007)", - blockTime: uint64(time.Now().Unix()) + consensus.MaxTimeOffsetSeconds + 2, - parentTime: []uint64{uint64(time.Now().Unix()) + consensus.MaxTimeOffsetSeconds + 1}, - err: errBadTimestamp, - }, - } - - parent := &state.BlockNode{Version: 1} - block := &bc.Block{ - BlockHeader: &bc.BlockHeader{Version: 1}, - } - - for i, c := range cases { - parent.Timestamp = c.parentTime[0] - parentSuccessor := parent - for i := 1; i < len(c.parentTime); i++ { - parentSuccessor.Parent = &state.BlockNode{Version: 1, Timestamp: c.parentTime[i]} - parentSuccessor = parentSuccessor.Parent - } - - block.Timestamp = c.blockTime - if err := checkBlockTime(block, parent); rootErr(err) != c.err { - t.Errorf("case %d got error %s, want %s", i, err, c.err) - } - } -} - -func TestCheckCoinbaseAmount(t *testing.T) { - cases := []struct { - txs []*types.Tx - amount uint64 - err error - }{ - { - txs: []*types.Tx{ - types.NewTx(types.TxData{ - Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)}, - Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 5000, nil)}, - }), - }, - amount: 5000, - err: nil, - }, - { - txs: []*types.Tx{ - types.NewTx(types.TxData{ - Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)}, - Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 5000, nil)}, - }), - }, - amount: 6000, - err: ErrWrongCoinbaseTransaction, - }, - { - txs: []*types.Tx{}, - amount: 5000, - err: ErrWrongCoinbaseTransaction, - }, - } - - block := new(types.Block) - for i, c := range cases { - block.Transactions = c.txs - if err := checkCoinbaseAmount(types.MapBlock(block), c.amount); rootErr(err) != c.err { - t.Errorf("case %d got error %s, want %s", i, err, c.err) - } - } -} - -func TestValidateBlockHeader(t *testing.T) { - iniTtensority() - - cases := []struct { - desc string - block *bc.Block - parent *state.BlockNode - err error - }{ - { - block: &bc.Block{BlockHeader: &bc.BlockHeader{ - Version: 2, - }}, - parent: &state.BlockNode{ - Version: 1, - }, - err: errVersionRegression, - }, - { - block: &bc.Block{BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 20, - }}, - parent: &state.BlockNode{ - Version: 1, - Height: 18, - }, - err: errMisorderedBlockHeight, - }, - { - desc: "the difficulty of the block is not equals to the next difficulty of parent block (blocktest#1008)", - block: &bc.Block{BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 20, - Bits: 0, - }}, - parent: &state.BlockNode{ - Version: 1, - Height: 19, - Bits: 2305843009214532812, - }, - err: errBadBits, - }, - { - desc: "the prev block hash not equals to the hash of parent (blocktest#1004)", - block: &bc.Block{BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 20, - PreviousBlockId: &bc.Hash{V0: 18}, - }}, - parent: &state.BlockNode{ - Version: 1, - Height: 19, - Hash: bc.Hash{V0: 19}, - }, - err: errMismatchedBlock, - }, - { - desc: "check work proof fail (blocktest#1011)", - block: &bc.Block{ - ID: bc.Hash{V0: 0}, - BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 1, - Timestamp: 1523352601, - PreviousBlockId: &bc.Hash{V0: 0}, - Bits: 2305843009214532812, - }, - }, - parent: &state.BlockNode{ - Version: 1, - Height: 0, - Timestamp: 1523352600, - Hash: bc.Hash{V0: 0}, - Seed: &bc.Hash{V1: 1}, - Bits: 2305843009214532812, - }, - err: errWorkProof, - }, - { - block: &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 1, - Timestamp: 1523352601, - PreviousBlockId: &bc.Hash{V0: 0}, - Bits: 2305843009214532812, - }, - }, - parent: &state.BlockNode{ - Version: 1, - Height: 0, - Timestamp: 1523352600, - Hash: bc.Hash{V0: 0}, - Seed: &bc.Hash{V1: 1}, - Bits: 2305843009214532812, - }, - err: nil, - }, - { - desc: "version greater than 1 (blocktest#1001)", - block: &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: 2, - }, - }, - parent: &state.BlockNode{ - Version: 1, - }, - err: errVersionRegression, - }, - { - desc: "version equals 0 (blocktest#1002)", - block: &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: 0, - }, - }, - parent: &state.BlockNode{ - Version: 1, - }, - err: errVersionRegression, - }, - { - desc: "version equals max uint64 (blocktest#1003)", - block: &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: math.MaxUint64, - }, - }, - parent: &state.BlockNode{ - Version: 1, - }, - err: errVersionRegression, - }, - } - - for i, c := range cases { - if err := ValidateBlockHeader(c.block, c.parent); rootErr(err) != c.err { - t.Errorf("case %d (%s) got error %s, want %s", i, c.desc, err, c.err) - } - } -} - -// TestValidateBlock test the ValidateBlock function -func TestValidateBlock(t *testing.T) { - iniTtensority() - - cp, _ := vmutil.DefaultCoinbaseProgram() - cases := []struct { - desc string - block *bc.Block - parent *state.BlockNode - err error - }{ - { - desc: "The calculated transaction merkel root hash is not equals to the hash of the block header (blocktest#1009)", - block: &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 1, - Timestamp: 1523352601, - PreviousBlockId: &bc.Hash{V0: 0}, - Bits: 2305843009214532812, - TransactionsRoot: &bc.Hash{V0: 1}, - }, - Transactions: []*bc.Tx{ - types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 1, - Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)}, - Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)}, - }), - }, - }, - parent: &state.BlockNode{ - Version: 1, - Height: 0, - Timestamp: 1523352600, - Hash: bc.Hash{V0: 0}, - Seed: &bc.Hash{V1: 1}, - Bits: 2305843009214532812, - }, - err: errMismatchedMerkleRoot, - }, - { - desc: "The calculated transaction status merkel root hash is not equals to the hash of the block header (blocktest#1009)", - block: &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 1, - Timestamp: 1523352601, - PreviousBlockId: &bc.Hash{V0: 0}, - Bits: 2305843009214532812, - TransactionsRoot: &bc.Hash{V0: 6294987741126419124, V1: 12520373106916389157, V2: 5040806596198303681, V3: 1151748423853876189}, - TransactionStatusHash: &bc.Hash{V0: 1}, - }, - Transactions: []*bc.Tx{ - types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 1, - Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)}, - Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)}, - }), - }, - }, - parent: &state.BlockNode{ - Version: 1, - Height: 0, - Timestamp: 1523352600, - Hash: bc.Hash{V0: 0}, - Seed: &bc.Hash{V1: 1}, - Bits: 2305843009214532812, - }, - err: errMismatchedMerkleRoot, - }, - { - desc: "the coinbase amount is less than the real coinbase amount (txtest#1014)", - block: &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 1, - Timestamp: 1523352601, - PreviousBlockId: &bc.Hash{V0: 0}, - Bits: 2305843009214532812, - }, - Transactions: []*bc.Tx{ - types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 1, - Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)}, - Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)}, - }), - types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 1, - Inputs: []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)}, - Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 90000000, cp)}, - }), - }, - }, - parent: &state.BlockNode{ - Version: 1, - Height: 0, - Timestamp: 1523352600, - Hash: bc.Hash{V0: 0}, - Seed: &bc.Hash{V1: 1}, - Bits: 2305843009214532812, - }, - err: ErrWrongCoinbaseTransaction, - }, - } - - for i, c := range cases { - err := ValidateBlock(c.block, c.parent) - if rootErr(err) != c.err { - t.Errorf("case #%d (%s) got error %s, want %s", i, c.desc, err, c.err) - } - } -} - -// TestGasOverBlockLimit check if the gas of the block has the max limit (blocktest#1012) -func TestGasOverBlockLimit(t *testing.T) { - iniTtensority() - - cp, _ := vmutil.DefaultCoinbaseProgram() - parent := &state.BlockNode{ - Version: 1, - Height: 0, - Timestamp: 1523352600, - Hash: bc.Hash{V0: 0}, - Seed: &bc.Hash{V1: 1}, - Bits: 2305843009214532812, - } - block := &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 1, - Timestamp: 1523352601, - PreviousBlockId: &bc.Hash{V0: 0}, - Bits: 2305843009214532812, - TransactionsRoot: &bc.Hash{V0: 1}, - }, - Transactions: []*bc.Tx{ - types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 1, - Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)}, - Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)}, - }), - }, - } - - for i := 0; i < 100; i++ { - block.Transactions = append(block.Transactions, types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 100000, - Inputs: []*types.TxInput{ - types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 10000000000, 0, cp), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, cp), - }, - })) - } - - if err := ValidateBlock(block, parent); err != errOverBlockLimit { - t.Errorf("got error %s, want %s", err, errOverBlockLimit) - } -} - -// TestSetTransactionStatus verify the transaction status is set correctly (blocktest#1010) -func TestSetTransactionStatus(t *testing.T) { - iniTtensority() - - cp, _ := vmutil.DefaultCoinbaseProgram() - parent := &state.BlockNode{ - Version: 1, - Height: 0, - Timestamp: 1523352600, - Hash: bc.Hash{V0: 0}, - Seed: &bc.Hash{V1: 1}, - Bits: 2305843009214532812, - } - block := &bc.Block{ - ID: bc.Hash{V0: 1}, - BlockHeader: &bc.BlockHeader{ - Version: 1, - Height: 1, - Timestamp: 1523352601, - PreviousBlockId: &bc.Hash{V0: 0}, - Bits: 2305843009214532812, - TransactionsRoot: &bc.Hash{V0: 3413931728524254295, V1: 300490676707850231, V2: 1886132055969225110, V3: 10216139531293906088}, - TransactionStatusHash: &bc.Hash{V0: 8682965660674182538, V1: 8424137560837623409, V2: 6979974817894224946, V3: 4673809519342015041}, - }, - Transactions: []*bc.Tx{ - types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 1, - Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)}, - Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41449998224, cp)}, - }), - types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp), - types.NewSpendInput([][]byte{}, *newHash(8), bc.AssetID{V0: 1}, 1000, 0, []byte{byte(vm.OP_FALSE)}), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 888, cp), - types.NewTxOutput(bc.AssetID{V0: 1}, 1000, cp), - }, - }), - types.MapTx(&types.TxData{ - Version: 1, - SerializedSize: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 888, cp), - }, - }), - }, - } - - if err := ValidateBlock(block, parent); err != nil { - t.Fatal(err) - } - - expectTxStatuses := []bool{false, true, false} - txStatuses := block.GetTransactionStatus().VerifyStatus - if len(expectTxStatuses) != len(txStatuses) { - t.Error("the size of expect tx status is not equals to size of got tx status") - } - - for i, status := range txStatuses { - if expectTxStatuses[i] != status.StatusFail { - t.Errorf("got tx status: %v, expect tx status: %v\n", status.StatusFail, expectTxStatuses[i]) - } - } -} - -func iniTtensority() { - // add (hash, seed) --> (tensority hash) to the tensority cache for avoid - // real matrix calculate cost. - tensority.AIHash.AddCache(&bc.Hash{V0: 0}, &bc.Hash{}, testutil.MaxHash) - tensority.AIHash.AddCache(&bc.Hash{V0: 1}, &bc.Hash{}, testutil.MinHash) - tensority.AIHash.AddCache(&bc.Hash{V0: 1}, consensus.InitialSeed, testutil.MinHash) -} diff --git a/protocol/validation/test/tx_ugly_test.go b/protocol/validation/test/tx_ugly_test.go deleted file mode 100644 index 51cb54e6..00000000 --- a/protocol/validation/test/tx_ugly_test.go +++ /dev/null @@ -1,1008 +0,0 @@ -package test - -import ( - "encoding/hex" - "math" - "testing" - - "github.com/bytom/account" - "github.com/bytom/blockchain/signers" - "github.com/bytom/consensus" - "github.com/bytom/crypto/ed25519/chainkd" - "github.com/bytom/protocol/bc" - "github.com/bytom/protocol/bc/types" - "github.com/bytom/protocol/validation" - "github.com/bytom/protocol/vm/vmutil" - "github.com/bytom/testutil" -) - -func TestValidateUglyTx(t *testing.T) { - singleSignInst := &signingInst{ - rootPrvKeys: []string{ - "38d2c44314c401b3ea7c23c54e12c36a527aee46a7f26b82443a46bf40583e439dea25de09b0018b35a741d8cd9f6ec06bc11db49762617485f5309ab72a12d4", - }, - quorum: 1, - keyIndex: 1, - ctrlProgramIndex: 1, - change: false, - } - multiSignInst := &signingInst{ - rootPrvKeys: []string{ - "a080aca2d9d7948d005c92d0729c618e56fb5551a52dfa04dc4caaf3c8b8a94c89a9795f5bbfd2b885ce7a9d3e3efa5386436c3681b21f9263a0b0a544346b48", - "105295324626e33bb7d8e8a57c6a0aa495346d7fc342a4891ece00424494cf48f75cefa0f8c61674a12238cfa711b4bc26cb22f38b6e2206c691b83943a58312", - "c02bb73d1aee56f8935fb7704f71f668eb37ec223baf5723b38a186669b465427d1bdbc2c4397c1259d12b6229aaf6154aaccdeb8addce3a780a1cbc1025ad25", - "a0c2225685e4c4439f12c264d1573db063ddbc929d4b8a3e1641e8abb4df504a56b1200b9925138d79febe6e1156fcfaf0d1878f25cbccc5db4c8fea55bde198", - "20d06d4fd261ab554e01104f019392f89566acace727e6bb6de4544aa3a6b248480232155332e6e5de10a62e4a9a4c1d9e3b7f9cb4fd196142ef1d080b8bbaec", - }, - quorum: 3, - keyIndex: 1, - ctrlProgramIndex: 1, - change: false, - } - cases := []struct { - category string - desc string - insts []*signingInst - txData types.TxData - gasValid bool - err bool - }{ - { - category: "fee insufficient", - desc: "sum of btm output greater than btm input", - insts: []*signingInst{singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 10000000001, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "fee insufficient", - desc: "sum of btm output equals to input btm", - insts: []*signingInst{singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 10000000001, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "fee insufficient", - desc: "sum of btm input greater than btm output, but still insufficient", - insts: []*signingInst{singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000001, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "fee insufficient", - desc: "no btm input", - insts: []*signingInst{singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: true, - }, - { - category: "input output unbalance", - desc: "only has btm input, no output", - insts: []*signingInst{singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000001, 0, nil), - }, - Outputs: []*types.TxOutput{}, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "issuance asset, no corresponding output", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - nil, - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "issuance asset A, output asset B", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - nil, - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707e"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "sum of output asset A greater than issuance asset A", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - nil, - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "sum of output asset A less than issuance asset A", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - nil, - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "sum of retire asset A greater than issuance asset A", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - nil, - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("6a")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "sum of retire asset A less than issuance asset A", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - nil, - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("6a")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "spend asset A, no corresponding output", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "spend asset A, output asset B", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707e"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "sum of output asset A greater than spend asset A", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "sum of output asset A less than spend asset A", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "sum of retire asset A greater than spend asset A", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("6a")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "sum of retire asset A less than spend asset A", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("6a")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "use retired utxo", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("6a")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "input utxo is zero", - insts: []*signingInst{singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 0, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 0, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "input output unbalance", - desc: "no btm input", - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{}, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 10, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "spend btm input overflow", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, math.MaxUint64, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - *consensus.BTMAssetID, 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "spend non btm input overflow", - insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), math.MaxInt64, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - *consensus.BTMAssetID, 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "issuance non btm input overflow", - insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - *consensus.BTMAssetID, 10000000000, 1, nil), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - math.MaxInt64, - nil, - [][]byte{ - testutil.MustDecodeHexString("e8f301f7bd3b1e4ca853b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"), - }, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - nil, - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "sum of spend and issuance non btm input overflow", - insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - *consensus.BTMAssetID, 10000000000, 1, nil), - types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f - testutil.MustDecodeHexString("fd0aec4229deb281"), - math.MaxInt64, - nil, - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "spend btm output overflow", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "retire btm output overflow", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("6a")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "non btm output overflow", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "retire non btm output overflow", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(*consensus.BTMAssetID, math.MaxUint64, testutil.MustDecodeHexString("6a")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "overflow", - desc: "output with over range amount but sum in equal", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 100000000, 0, nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 18446744073609551616, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(*consensus.BTMAssetID, 18446744073609551616, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(*consensus.BTMAssetID, 290000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "verify signature fail", - desc: "btm single sign", - insts: []*signingInst{singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "verify signature fail", - desc: "btm multi sign", - insts: []*signingInst{multiSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("00200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66")), // wrong control program - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: false, - }, - { - category: "verify signature fail", - desc: "spend non btm single sign", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: true, - }, - { - category: "verify signature fail", - desc: "spend non btm multi sign", - insts: []*signingInst{singleSignInst, multiSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput(nil, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 1, testutil.MustDecodeHexString("00140876db6ca8f4542a836f0edd42b87d095d081182")), // wrong control program - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: true, - }, - { - category: "verify signature fail", - desc: "issuance non btm single sign", - insts: []*signingInst{singleSignInst, multiSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewIssuanceInput( - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - // wrong issuance program - testutil.MustDecodeHexString("ae20c38173d800e62f63bd08cfaa9bc905e4a34a61ad841d7ad6c70ead0fb48196995151ad"), - nil, - nil, - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("bf5f8da2334590ee095148ccdcf4d806b26a47a6d9e9e857ef6c2de79aee4f14"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: true, - }, - { - category: "verify signature fail", - desc: "issuance non btm multi sign", - insts: []*signingInst{singleSignInst, multiSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewIssuanceInput( - testutil.MustDecodeHexString("fd0aec4229deb281"), - 10000000000, - // wrong issuance program - testutil.MustDecodeHexString("ae20ce8639c5dc70cb2b12f89a057670602eb013fc54a10ce22bd4691c62cf546b7b2081bdd879bcbce7f58e1731841c6b3deac242efa00e75124fe559fa531c0c5bb820b40b6eec74288ee4bae67191f135512454b52640cfd7be95dc84be0f02281dce20247b6e6f9230a987ef61c66820268e7b766d28c1ce7aa2c550b34e294167f340205096211460415888768a48b121013711aa711634bb9ff7341a7bd072c31525875355ad"), - nil, - testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("776f0a421e9176a03061d388aff4ab3b1bcd32e53a090d593a466706c69e3d3f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: true, - }, - { - category: "double spend", - desc: "btm asset double spend", - insts: []*signingInst{singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")), - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 19000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: true, - }, - { - category: "double spend", - desc: "non btm asset double spend", - insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst}, - txData: types.TxData{ - Version: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput(nil, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 10000000000, 0, nil), - types.NewSpendInput( - nil, - bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")), - types.NewSpendInput( - nil, - bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452}, - testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, 0, testutil.MustDecodeHexString("001420a1af4fc11399e6cd7253abf1bbd4d0af17daad")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - }, - }, - err: true, - gasValid: true, - }, - } - - for i, c := range cases { - mockCtrlProgram(c.txData, c.insts) - - c.txData.SerializedSize = 1 - - tx := types.NewTx(c.txData) - mockSignTx(tx, c.insts) - bcTx := types.MapTx(&c.txData) - - gasStatus, err := validation.ValidateTx(bcTx, &bc.Block{ - BlockHeader: &bc.BlockHeader{Height: 1}, - Transactions: []*bc.Tx{bcTx}, - }) - if !c.err && err != nil { - t.Errorf("case #%d (%s) expect no error, got error %s", i, c.desc, err) - } - - if c.err && err == nil { - t.Errorf("case #%d (%s) expect error, got no error", i, c.desc) - } - - if c.gasValid != gasStatus.GasValid { - t.Errorf("case #%d (%s) got GasValid %t, want %t", i, c.desc, gasStatus.GasValid, c.gasValid) - } - } -} - -type signingInst struct { - rootPrvKeys []string - quorum int - keyIndex uint64 - ctrlProgramIndex uint64 - change bool -} - -func mockCtrlProgram(txData types.TxData, insts []*signingInst) { - for i, input := range txData.Inputs { - _, xPubs := mustGetRootKeys(insts[i].rootPrvKeys) - - switch inp := input.TypedInput.(type) { - case *types.SpendInput: - if inp.ControlProgram != nil { - continue - } - acc := &account.Account{Signer: &signers.Signer{KeyIndex: insts[i].keyIndex, DeriveRule: signers.BIP0044, XPubs: xPubs, Quorum: insts[i].quorum}} - program, err := account.CreateCtrlProgram(acc, insts[i].ctrlProgramIndex, insts[i].change) - if err != nil { - panic(err) - } - inp.ControlProgram = program.ControlProgram - case *types.IssuanceInput: - if inp.IssuanceProgram != nil { - continue - } - assetSigner, err := signers.Create("asset", xPubs, insts[i].quorum, insts[i].keyIndex, signers.BIP0032) - if err != nil { - panic(err) - } - - path := signers.GetBip0032Path(assetSigner, signers.AssetKeySpace) - derivedXPubs := chainkd.DeriveXPubs(assetSigner.XPubs, path) - derivedPKs := chainkd.XPubKeys(derivedXPubs) - - issuanceProg, err := vmutil.P2SPMultiSigProgramWithHeight(derivedPKs, insts[i].quorum, 0) - if err != nil { - panic(err) - } - - inp.IssuanceProgram = issuanceProg - } - } -} - -func mockSignTx(tx *types.Tx, insts []*signingInst) { - for i, input := range tx.TxData.Inputs { - if input.Arguments() != nil { - continue - } - var arguments [][]byte - inst := insts[i] - switch inp := input.TypedInput.(type) { - case *types.SpendInput: - path, err := signers.Path(&signers.Signer{KeyIndex: inst.keyIndex, DeriveRule: signers.BIP0044}, signers.AccountKeySpace, inst.change, inst.ctrlProgramIndex) - if err != nil { - panic(err) - } - - xPrvs, xPubs := mustGetRootKeys(inst.rootPrvKeys) - for _, xPrv := range xPrvs { - childPrv := xPrv.Derive(path) - sigHashBytes := tx.SigHash(uint32(i)).Byte32() - arguments = append(arguments, childPrv.Sign(sigHashBytes[:])) - } - - if len(xPrvs) == 1 { - childPrv := xPrvs[0].Derive(path) - derivePK := childPrv.XPub() - arguments = append(arguments, derivePK.PublicKey()) - } else { - derivedXPubs := chainkd.DeriveXPubs(xPubs, path) - derivedPKs := chainkd.XPubKeys(derivedXPubs) - script, err := vmutil.P2SPMultiSigProgram(derivedPKs, inst.quorum) - if err != nil { - panic(err) - } - - arguments = append(arguments, script) - } - inp.Arguments = arguments - case *types.IssuanceInput: - path := signers.GetBip0032Path(&signers.Signer{KeyIndex: inst.keyIndex, DeriveRule: signers.BIP0032}, signers.AssetKeySpace) - xPrvs, _ := mustGetRootKeys(inst.rootPrvKeys) - for _, xPrv := range xPrvs { - childPrv := xPrv.Derive(path) - sigHashBytes := tx.SigHash(uint32(i)).Byte32() - arguments = append(arguments, childPrv.Sign(sigHashBytes[:])) - } - inp.Arguments = arguments - } - } -} - -func mustGetRootKeys(prvs []string) ([]chainkd.XPrv, []chainkd.XPub) { - xPubs := make([]chainkd.XPub, len(prvs)) - xPrvs := make([]chainkd.XPrv, len(prvs)) - for i, xPrv := range prvs { - xPrvBytes, err := hex.DecodeString(xPrv) - if err != nil { - panic(err) - } - - if len(xPrvBytes) != 64 { - panic("the size of xPrv must 64") - } - - var dest [64]byte - copy(dest[:], xPrv) - xPrvs[i] = chainkd.XPrv(dest) - xPubs[i] = xPrvs[i].XPub() - } - return xPrvs, xPubs -} diff --git a/protocol/validation/tx.go b/protocol/validation/tx.go index f7e860e3..d426c6e1 100644 --- a/protocol/validation/tx.go +++ b/protocol/validation/tx.go @@ -70,15 +70,6 @@ func (g *GasState) setGas(BTMValue int64, txSize int64) error { } func (g *GasState) setGasValid() error { - var ok bool - if g.GasLeft, ok = checked.SubInt64(g.GasLeft, g.StorageGas); !ok || g.GasLeft < 0 { - return errors.Wrap(ErrGasCalculate, "setGasValid calc gasLeft") - } - - if g.GasUsed, ok = checked.AddInt64(g.GasUsed, g.StorageGas); !ok { - return errors.Wrap(ErrGasCalculate, "setGasValid calc gasUsed") - } - g.GasValid = true return nil } @@ -230,13 +221,10 @@ func checkValid(vs *validationState, e bc.Entry) (err error) { return errors.WithDetailf(ErrMismatchedAssetID, "asset ID is %x, issuance wants %x", computedAssetID.Bytes(), e.Value.AssetId.Bytes()) } - gasLeft, err := vm.Verify(NewTxVMContext(vs, e, e.WitnessAssetDefinition.IssuanceProgram, e.WitnessArguments), vs.gasStatus.GasLeft) + _, err := vm.Verify(NewTxVMContext(vs, e, e.WitnessAssetDefinition.IssuanceProgram, e.WitnessArguments), consensus.MaxGasAmount) if err != nil { return errors.Wrap(err, "checking issuance program") } - if err = vs.gasStatus.updateUsage(gasLeft); err != nil { - return err - } destVS := *vs destVS.destPos = 0 @@ -253,13 +241,10 @@ func checkValid(vs *validationState, e bc.Entry) (err error) { return errors.Wrap(err, "getting spend prevout") } - gasLeft, err := vm.Verify(NewTxVMContext(vs, e, spentOutput.ControlProgram, e.WitnessArguments), vs.gasStatus.GasLeft) + _, err = vm.Verify(NewTxVMContext(vs, e, spentOutput.ControlProgram, e.WitnessArguments), consensus.MaxGasAmount) if err != nil { return errors.Wrap(err, "checking control program") } - if err = vs.gasStatus.updateUsage(gasLeft); err != nil { - return err - } eq, err := spentOutput.Source.Value.Equal(e.WitnessDestination.Value) if err != nil { diff --git a/protocol/validation/tx_scene_test.go b/protocol/validation/tx_scene_test.go deleted file mode 100644 index 6f97c81b..00000000 --- a/protocol/validation/tx_scene_test.go +++ /dev/null @@ -1,283 +0,0 @@ -package validation - -import ( - "encoding/hex" - "testing" - - "github.com/bytom/consensus" - "github.com/bytom/protocol/bc" - "github.com/bytom/protocol/bc/types" - "github.com/bytom/protocol/vm" -) - -func TestValidateTx(t *testing.T) { - cases := []struct { - desc string - txData *types.TxData - gasValid bool - err error - }{ - { - desc: "single utxo, single sign, non asset, btm stanard transaction", - txData: &types.TxData{ - Version: 1, - SerializedSize: 331, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{ - mustDecodeString("298fbf48459480914e19a0fc20440b095bd7f38d9f01c56bfc904b4ed4967a7b73f1fc4919f23a7806eeb834a89f8ce696500f4528e8f7bf29c8ee1f38a91e01"), - mustDecodeString("5a260070d967d894a9c4a6e16670c2881ed4c225e12d93b0707156e71fce5bfd"), - }, - bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452}, - *consensus.BTMAssetID, 21819700000, 0, mustDecodeString("001411ef7695d46e1f9288d996c3daa6ff4d956ac355")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 11818900000, mustDecodeString("001415c956112c2b46354690e36051803cc9d5a8f26b")), - types.NewTxOutput(*consensus.BTMAssetID, 10000000000, mustDecodeString("00149c9dd93184cc34ac5d47c145c5af3df852235aad")), - }, - }, - gasValid: true, - err: nil, - }, - { - desc: "multi utxo, single sign, non asset, btm stanard transaction", - txData: &types.TxData{ - Version: 1, - SerializedSize: 595, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{ - mustDecodeString("d488321eff213793fb685749a65b945b4d32f08774c27461e0dda265580e9d4582f4b210756b7f8a5b4a64bde531076e92244e12c145c9b54012134cebf9e402"), - mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"), - }, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")), - types.NewSpendInput( - [][]byte{ - mustDecodeString("5d528bdb13b93c26245dc90c1fe51265555eb22a34fa013649db9aa874eb7770c6c4016320017224efdecf5fee39b682151f881f82c2c7195fe444ac5966140e"), - mustDecodeString("563cb0eedf2a2891926dfaa0b9ac20913c67a066517f06b1f77c5ab527a8a8c4"), - }, - bc.Hash{V0: 13464118406972499748, V1: 5083224803004805715, V2: 16263625389659454272, V3: 9428032044180324575}, - *consensus.BTMAssetID, 99439999900, 2, mustDecodeString("001419f79910f29df2ef80ec10d24c78e2009ed19302")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")), - types.NewTxOutput(*consensus.BTMAssetID, 89439999900, mustDecodeString("0014ca1f877c2787f746a4473adac932171dd18d55d7")), - types.NewTxOutput(*consensus.BTMAssetID, 19900000000, mustDecodeString("00145ade29df622cc68d0473aa1a20fb89690451c66e")), - }, - }, - gasValid: true, - err: nil, - }, - { - desc: "multi utxo, single sign, non asset, btm stanard transaction, insufficient gas", - txData: &types.TxData{ - Version: 1, - SerializedSize: 595, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{ - mustDecodeString("4a8bf559f3c334ad23ed0aadab22dd3a4a8260488b1632dee16f75cac5c0ade674f2938776459414ab4d4e43622290507ff750a3fb563a25ee9a72386bfbe207"), - mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"), - }, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")), - types.NewSpendInput( - [][]byte{ - mustDecodeString("b4f6876a97c8e6bd7e038b476fb6fd07cdd6cfcf7d661dfab796b5e2c777b3de166495de4fba2aa154af844ed6a3d51c26742241edb0d5d107fc52dfff0f6305"), - mustDecodeString("e5966eee4092eeefdd805b06f2ad368bb9392edec20998993ebe2a929052c1ce"), - }, - bc.Hash{V0: 17091584763764411831, V1: 2315724244669489432, V2: 4322938623810388342, V3: 11167378497724951792}, - *consensus.BTMAssetID, 99960000000, 1, mustDecodeString("0014cfbccfac5018ad4b4bfbcb1fab834e3c85037460")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("00144b5637cc25b188136f440484f210541fa2a7ce64")), - types.NewTxOutput(*consensus.BTMAssetID, 89960000000, mustDecodeString("0014c7271a69dba57331b36221118dfeb1b1793933df")), - types.NewTxOutput(*consensus.BTMAssetID, 20000000000, mustDecodeString("0014447e597c1c326ad1a639f8023d3f87ae22a4e049")), - }, - }, - gasValid: false, - err: vm.ErrRunLimitExceeded, - }, - { - desc: "single utxo, multi sign, non asset, btm stanard transaction", - txData: &types.TxData{ - Version: 1, - SerializedSize: 396, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{ - mustDecodeString("abc55905b5c477f424ea5ce88bbd00376f18f525850b7b74f54e94e7999edbe5ded9e9f5d8f1319470e9a38540bbaa6bbe67aacc8227c898ae30b9ac15f8dc0b"), - mustDecodeString("ae203f56f71972918585ece56a21f77c3e9101ce14c75038b65454e10960266cceba20c9927f289b57c647578d07904a9d34597079d80e300df023a26658a770f611545152ad"), - }, - bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302}, - *consensus.BTMAssetID, 89220000000, 1, mustDecodeString("0020ff726649e34c921ff61a97090fc62054f339597acfc710197bb0133e18a19c5c")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 79220000000, mustDecodeString("00206205ec178dc1ac6ea05ea01bb0fcda6aa978173026fa75204a101bdad7bd6b48")), - types.NewTxOutput(*consensus.BTMAssetID, 9900000000, mustDecodeString("0014414eb62abda9a9191f9cba5d7e38d92f3e91e268")), - }, - }, - gasValid: true, - err: nil, - }, - { - desc: "single utxo, retire, non asset, btm stanard transaction", - txData: &types.TxData{ - Version: 1, - SerializedSize: 309, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{ - mustDecodeString("f0009a0fa67238f6dfbb208282f509fb460531f43f74809e0226af2ff064607fad8a2506779e717a5f7848bbc3abdfa724148a9df46426027f201a4dfec27809"), - mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"), - }, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 11718900000, mustDecodeString("0014085a02ecdf934a56343aa59a3dec9d9feb86ee43")), - types.NewTxOutput(*consensus.BTMAssetID, 90000000, []byte{byte(vm.OP_FAIL)}), - }, - }, - gasValid: true, - err: nil, - }, - { - desc: "single utxo, single sign, issuance, spend, retire, btm stanard transaction, gas sufficient", - txData: &types.TxData{ - Version: 1, - SerializedSize: 601, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{ - mustDecodeString("8aab6052cb935384ac8fcbd4c0857cbce2e19825a002635d0b242757f17e5fdd148d83eb3837baf91754bf539cd08e29f66975f4bc9843ac00e280f228026105"), - mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"), - }, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")), - types.NewIssuanceInput( - mustDecodeString("fd0aec4229deb281"), - 10000000000, - mustDecodeString("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad"), - [][]byte{ - mustDecodeString("e8f301f7bd3b1e4ca853b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"), - }, - mustDecodeString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("00147d6b00edfbbc758a5da6130a5fa1a4cfec8422c3")), - types.NewTxOutput(*consensus.BTMAssetID, 9900000000, []byte{byte(vm.OP_FAIL)}), - types.NewTxOutput(bc.AssetID{V0: 8879089148261671560, V1: 16875272676673176923, V2: 14627348561007036053, V3: 5774520766896450836}, 10000000000, mustDecodeString("0014447e597c1c326ad1a639f8023d3f87ae22a4e049")), - }, - }, - gasValid: true, - err: nil, - }, - { - desc: "single utxo, single sign, issuance, spend, retire, btm stanard transaction, gas insufficient", - txData: &types.TxData{ - Version: 1, - SerializedSize: 601, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{ - mustDecodeString("23ca3a6f8474b1b9ab8b77fcf3cf3fd9dfa761dff4e5d8551a72307dc065cd19100f3ca9fcca4df2f8842b71dba2fd29b73c1b06b3d8bddc2a71e8cc18842a04"), - mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"), - }, - bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994}, - *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")), - types.NewIssuanceInput( - mustDecodeString("4b6afc9344c3ce63"), - 10000000000, - mustDecodeString("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad"), - [][]byte{ - mustDecodeString("e8f301f7bd3b1e4ca85f1f8acda3a91fb73e717c096b8b82b2c7ed9d25170c0f9fcd9b5e8039094bd1174886f1b5428272eb6c2af03946bf3c2037a4b499c77107b94b96a92088a0d0d3b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"), - }, - mustDecodeString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), - ), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("001482b7991d64d001009b673ffe3ca2b35eab14f142")), - types.NewTxOutput(*consensus.BTMAssetID, 10000000000, []byte{byte(vm.OP_FAIL)}), - types.NewTxOutput(bc.AssetID{V0: 8879089148261671560, V1: 16875272676673176923, V2: 14627348561007036053, V3: 5774520766896450836}, 10000000000, mustDecodeString("0014447e597c1c326ad1a639f8023d3f87ae22a4e049")), - }, - }, - gasValid: false, - err: vm.ErrRunLimitExceeded, - }, - { - desc: "btm stanard transaction check signature is not passed", - txData: &types.TxData{ - Version: 1, - SerializedSize: 331, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{ - mustDecodeString("298fbf48459480914e19a0fc20440b095bd7f38d9f01c56bfc904b4ed4967a7b73f1fc4919f23a7806eeb834a89f8ce696500f4528e8f7bf29c8ee1f38a91e02"), - mustDecodeString("5a260070d967d894a9c4a6e16670c2881ed4c225e12d93b0707156e71fce5bfd"), - }, - bc.Hash{V0: 3485387979411255237, V1: 15603105575416882039, V2: 5974145557334619041, V3: 16513948410238218452}, - *consensus.BTMAssetID, 21819700000, 0, mustDecodeString("001411ef7695d46e1f9288d996c3daa6ff4d956ac355")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 11818900000, mustDecodeString("001415c956112c2b46354690e36051803cc9d5a8f26b")), - types.NewTxOutput(*consensus.BTMAssetID, 10000000000, mustDecodeString("00149c9dd93184cc34ac5d47c145c5af3df852235aad")), - }, - }, - gasValid: false, - err: vm.ErrFalseVMResult, - }, - { - desc: "non btm stanard transaction", - txData: &types.TxData{ - Version: 1, - SerializedSize: 508, - Inputs: []*types.TxInput{ - types.NewSpendInput( - [][]byte{mustDecodeString("585f298f2396c3b1be616b6eb48b21c7ec2b25fa4daf7256e970e0a55658c04cbcb406ed41e6b184732187daf0627ea805b24098785c80979edf4d4fc2b8100c")}, - bc.Hash{V0: 13727785470566991667, V1: 17422390991613608658, V2: 10016033157382430074, V3: 8274310611876171875}, - bc.AssetID{V0: 986236576456443635, V1: 13806502593573493203, V2: 9657495453304566675, V3: 15226142438973879401}, - 1000, - 1, - mustDecodeString("206dbca07ff0a6025612c835423daadd4460c3a2ed9a65622ba8025dfd3388238c7403ae7cac00c0")), - types.NewSpendInput( - [][]byte{ - mustDecodeString("4ef8f5a377c166b9fb4efa221894f06194b6b7bc277e613ad75b442929a417bb278ee347586e8f06b20c9b759263c981f03d00253f49753fde88dc8b39ccb10e"), - mustDecodeString("1381d35e235813ad1e62f9a602c82abee90565639cc4573568206b55bcd2aed9"), - }, - bc.Hash{V0: 5430419158397285610, V1: 15989125147582690097, V2: 3140150800656736345, V3: 4704385074037173738}, - *consensus.BTMAssetID, 9800000000, 2, mustDecodeString("0014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e")), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput( - bc.AssetID{V0: 986236576456443635, V1: 13806502593573493203, V2: 9657495453304566675, V3: 15226142438973879401}, - 1000, - mustDecodeString("001437e1aec83a4e6587ca9609e4e5aa728db7007449")), - types.NewTxOutput(*consensus.BTMAssetID, 9750000000, mustDecodeString("0014ec75fda5c727cb0d41137ab62afbf9070a405744")), - }, - }, - gasValid: true, - err: nil, - }, - } - - for i, c := range cases { - gasStatus, err := ValidateTx(types.MapTx(c.txData), mockBlock()) - if rootErr(err) != c.err { - t.Errorf("case #%d (%s) got error %s, want %s; validationState is:\n", i, c.desc, err, c.err) - } - if c.gasValid != gasStatus.GasValid { - t.Errorf("#%d got GasValid %t, want %t", i, gasStatus.GasValid, c.gasValid) - } - } -} - -func mustDecodeString(hexString string) []byte { - bytes, err := hex.DecodeString(hexString) - if err != nil { - panic(err) - } - return bytes -} diff --git a/protocol/validation/tx_test.go b/protocol/validation/tx_test.go deleted file mode 100644 index d6f8eabe..00000000 --- a/protocol/validation/tx_test.go +++ /dev/null @@ -1,1202 +0,0 @@ -package validation - -import ( - "math" - "testing" - - "github.com/davecgh/go-spew/spew" - - "github.com/bytom/consensus" - "github.com/bytom/crypto/sha3pool" - "github.com/bytom/errors" - "github.com/bytom/protocol/bc" - "github.com/bytom/protocol/bc/types" - "github.com/bytom/protocol/vm" - "github.com/bytom/protocol/vm/vmutil" - "github.com/bytom/testutil" -) - -func init() { - spew.Config.DisableMethods = true -} - -func TestGasStatus(t *testing.T) { - cases := []struct { - input *GasState - output *GasState - f func(*GasState) error - err error - }{ - { - input: &GasState{ - GasLeft: 10000, - GasUsed: 0, - BTMValue: 0, - }, - output: &GasState{ - GasLeft: 10000 / consensus.VMGasRate, - GasUsed: 0, - BTMValue: 10000, - }, - f: func(input *GasState) error { - return input.setGas(10000, 0) - }, - err: nil, - }, - { - input: &GasState{ - GasLeft: 10000, - GasUsed: 0, - BTMValue: 0, - }, - output: &GasState{ - GasLeft: 10000, - GasUsed: 0, - BTMValue: 0, - }, - f: func(input *GasState) error { - return input.setGas(-10000, 0) - }, - err: ErrGasCalculate, - }, - { - input: &GasState{ - GasLeft: consensus.DefaultGasCredit, - GasUsed: 0, - BTMValue: 0, - }, - output: &GasState{ - GasLeft: 200000, - GasUsed: 0, - BTMValue: 80000000000, - }, - f: func(input *GasState) error { - return input.setGas(80000000000, 0) - }, - err: nil, - }, - { - input: &GasState{ - GasLeft: consensus.DefaultGasCredit, - GasUsed: 0, - BTMValue: 0, - }, - output: &GasState{ - GasLeft: 200000, - GasUsed: 0, - BTMValue: math.MaxInt64, - }, - f: func(input *GasState) error { - return input.setGas(math.MaxInt64, 0) - }, - err: nil, - }, - { - input: &GasState{ - GasLeft: 10000, - GasUsed: 0, - BTMValue: 0, - }, - output: &GasState{ - GasLeft: 10000, - GasUsed: 0, - BTMValue: 0, - }, - f: func(input *GasState) error { - return input.updateUsage(-1) - }, - err: ErrGasCalculate, - }, - { - input: &GasState{ - GasLeft: 10000, - GasUsed: 0, - BTMValue: 0, - }, - output: &GasState{ - GasLeft: 9999, - GasUsed: 1, - BTMValue: 0, - }, - f: func(input *GasState) error { - return input.updateUsage(9999) - }, - err: nil, - }, - { - input: &GasState{ - GasLeft: -10000, - GasUsed: 0, - BTMValue: 0, - }, - output: &GasState{ - GasLeft: -10000, - GasUsed: 0, - BTMValue: 0, - }, - f: func(input *GasState) error { - return input.updateUsage(math.MaxInt64) - }, - err: ErrGasCalculate, - }, - { - input: &GasState{ - GasLeft: 1000, - GasUsed: 10, - StorageGas: 1000, - GasValid: false, - }, - output: &GasState{ - GasLeft: 0, - GasUsed: 1010, - StorageGas: 1000, - GasValid: true, - }, - f: func(input *GasState) error { - return input.setGasValid() - }, - err: nil, - }, - { - input: &GasState{ - GasLeft: 900, - GasUsed: 10, - StorageGas: 1000, - GasValid: false, - }, - output: &GasState{ - GasLeft: -100, - GasUsed: 10, - StorageGas: 1000, - GasValid: false, - }, - f: func(input *GasState) error { - return input.setGasValid() - }, - err: ErrGasCalculate, - }, - { - input: &GasState{ - GasLeft: 1000, - GasUsed: math.MaxInt64, - StorageGas: 1000, - GasValid: false, - }, - output: &GasState{ - GasLeft: 0, - GasUsed: 0, - StorageGas: 1000, - GasValid: false, - }, - f: func(input *GasState) error { - return input.setGasValid() - }, - err: ErrGasCalculate, - }, - { - input: &GasState{ - GasLeft: math.MinInt64, - GasUsed: 0, - StorageGas: 1000, - GasValid: false, - }, - output: &GasState{ - GasLeft: 0, - GasUsed: 0, - StorageGas: 1000, - GasValid: false, - }, - f: func(input *GasState) error { - return input.setGasValid() - }, - err: ErrGasCalculate, - }, - } - - for i, c := range cases { - err := c.f(c.input) - - if rootErr(err) != c.err { - t.Errorf("case %d: got error %s, want %s", i, err, c.err) - } else if *c.input != *c.output { - t.Errorf("case %d: gasStatus %v, want %v;", i, c.input, c.output) - } - } -} - -func TestOverflow(t *testing.T) { - sourceID := &bc.Hash{V0: 9999} - ctrlProgram := []byte{byte(vm.OP_TRUE)} - newTx := func(inputs []uint64, outputs []uint64) *bc.Tx { - txInputs := make([]*types.TxInput, 0, len(inputs)) - txOutputs := make([]*types.TxOutput, 0, len(outputs)) - - for _, amount := range inputs { - txInput := types.NewSpendInput(nil, *sourceID, *consensus.BTMAssetID, amount, 0, ctrlProgram) - txInputs = append(txInputs, txInput) - } - - for _, amount := range outputs { - txOutput := types.NewTxOutput(*consensus.BTMAssetID, amount, ctrlProgram) - txOutputs = append(txOutputs, txOutput) - } - - txData := &types.TxData{ - Version: 1, - SerializedSize: 100, - TimeRange: 0, - Inputs: txInputs, - Outputs: txOutputs, - } - return types.MapTx(txData) - } - - cases := []struct { - inputs []uint64 - outputs []uint64 - err error - }{ - { - inputs: []uint64{math.MaxUint64, 1}, - outputs: []uint64{0}, - err: ErrOverflow, - }, - { - inputs: []uint64{math.MaxUint64, math.MaxUint64}, - outputs: []uint64{0}, - err: ErrOverflow, - }, - { - inputs: []uint64{math.MaxUint64, math.MaxUint64 - 1}, - outputs: []uint64{0}, - err: ErrOverflow, - }, - { - inputs: []uint64{math.MaxInt64, 1}, - outputs: []uint64{0}, - err: ErrOverflow, - }, - { - inputs: []uint64{math.MaxInt64, math.MaxInt64}, - outputs: []uint64{0}, - err: ErrOverflow, - }, - { - inputs: []uint64{math.MaxInt64, math.MaxInt64 - 1}, - outputs: []uint64{0}, - err: ErrOverflow, - }, - { - inputs: []uint64{0}, - outputs: []uint64{math.MaxUint64}, - err: ErrOverflow, - }, - { - inputs: []uint64{0}, - outputs: []uint64{math.MaxInt64}, - err: ErrGasCalculate, - }, - { - inputs: []uint64{math.MaxInt64 - 1}, - outputs: []uint64{math.MaxInt64}, - err: ErrGasCalculate, - }, - } - - for i, c := range cases { - tx := newTx(c.inputs, c.outputs) - if _, err := ValidateTx(tx, mockBlock()); rootErr(err) != c.err { - t.Fatalf("case %d test failed, want %s, have %s", i, c.err, rootErr(err)) - } - } -} - -func TestTxValidation(t *testing.T) { - var ( - tx *bc.Tx - vs *validationState - fixture *txFixture - - // the mux from tx, pulled out for convenience - mux *bc.Mux - ) - - addCoinbase := func(assetID *bc.AssetID, amount uint64, arbitrary []byte) { - coinbase := bc.NewCoinbase(arbitrary) - txOutput := types.NewTxOutput(*assetID, amount, []byte{byte(vm.OP_TRUE)}) - muxID := getMuxID(tx) - coinbase.SetDestination(muxID, &txOutput.AssetAmount, uint64(len(mux.Sources))) - coinbaseID := bc.EntryID(coinbase) - tx.Entries[coinbaseID] = coinbase - - mux.Sources = append(mux.Sources, &bc.ValueSource{ - Ref: &coinbaseID, - Value: &txOutput.AssetAmount, - }) - - src := &bc.ValueSource{ - Ref: muxID, - Value: &txOutput.AssetAmount, - Position: uint64(len(tx.ResultIds)), - } - prog := &bc.Program{txOutput.VMVersion, txOutput.ControlProgram} - output := bc.NewOutput(src, prog, uint64(len(tx.ResultIds))) - outputID := bc.EntryID(output) - tx.Entries[outputID] = output - - dest := &bc.ValueDestination{ - Value: src.Value, - Ref: &outputID, - Position: 0, - } - mux.WitnessDestinations = append(mux.WitnessDestinations, dest) - tx.ResultIds = append(tx.ResultIds, &outputID) - vs.block.Transactions = append(vs.block.Transactions, vs.tx) - } - - cases := []struct { - desc string // description of the test case - f func() // function to adjust tx, vs, and/or mux - err error // expected error - }{ - { - desc: "base case", - }, - { - desc: "unbalanced mux amounts", - f: func() { - mux.Sources[0].Value.Amount++ - iss := tx.Entries[*mux.Sources[0].Ref].(*bc.Issuance) - iss.WitnessDestination.Value.Amount++ - }, - err: ErrUnbalanced, - }, - { - desc: "unbalanced mux amounts", - f: func() { - mux.WitnessDestinations[0].Value.Amount++ - }, - err: ErrUnbalanced, - }, - { - desc: "balanced mux amounts", - f: func() { - mux.Sources[1].Value.Amount++ - mux.WitnessDestinations[0].Value.Amount++ - }, - err: nil, - }, - { - desc: "overflowing mux source amounts", - f: func() { - mux.Sources[0].Value.Amount = math.MaxInt64 - iss := tx.Entries[*mux.Sources[0].Ref].(*bc.Issuance) - iss.WitnessDestination.Value.Amount = math.MaxInt64 - }, - err: ErrOverflow, - }, - { - desc: "underflowing mux destination amounts", - f: func() { - mux.WitnessDestinations[0].Value.Amount = math.MaxInt64 - out := tx.Entries[*mux.WitnessDestinations[0].Ref].(*bc.Output) - out.Source.Value.Amount = math.MaxInt64 - mux.WitnessDestinations[1].Value.Amount = math.MaxInt64 - out = tx.Entries[*mux.WitnessDestinations[1].Ref].(*bc.Output) - out.Source.Value.Amount = math.MaxInt64 - }, - err: ErrOverflow, - }, - { - desc: "unbalanced mux assets", - f: func() { - mux.Sources[1].Value.AssetId = newAssetID(255) - sp := tx.Entries[*mux.Sources[1].Ref].(*bc.Spend) - sp.WitnessDestination.Value.AssetId = newAssetID(255) - }, - err: ErrUnbalanced, - }, - { - desc: "mismatched output source / mux dest position", - f: func() { - tx.Entries[*tx.ResultIds[0]].(*bc.Output).Source.Position = 1 - }, - err: ErrMismatchedPosition, - }, - { - desc: "mismatched input dest / mux source position", - f: func() { - mux.Sources[0].Position = 1 - }, - err: ErrMismatchedPosition, - }, - { - desc: "mismatched output source and mux dest", - f: func() { - // For this test, it's necessary to construct a mostly - // identical second transaction in order to get a similar but - // not equal output entry for the mux to falsely point - // to. That entry must be added to the first tx's Entries map. - fixture2 := sample(t, fixture) - tx2 := types.NewTx(*fixture2.tx).Tx - out2ID := tx2.ResultIds[0] - out2 := tx2.Entries[*out2ID].(*bc.Output) - tx.Entries[*out2ID] = out2 - mux.WitnessDestinations[0].Ref = out2ID - }, - err: ErrMismatchedReference, - }, - { - desc: "mismatched input dest and mux source", - f: func() { - fixture2 := sample(t, fixture) - tx2 := types.NewTx(*fixture2.tx).Tx - input2ID := tx2.InputIDs[2] - input2 := tx2.Entries[input2ID].(*bc.Spend) - dest2Ref := input2.WitnessDestination.Ref - dest2 := tx2.Entries[*dest2Ref].(*bc.Mux) - tx.Entries[*dest2Ref] = dest2 - tx.Entries[input2ID] = input2 - mux.Sources[0].Ref = &input2ID - }, - err: ErrMismatchedReference, - }, - { - desc: "invalid mux destination position", - f: func() { - mux.WitnessDestinations[0].Position = 1 - }, - err: ErrPosition, - }, - { - desc: "mismatched mux dest value / output source value", - f: func() { - outID := tx.ResultIds[0] - out := tx.Entries[*outID].(*bc.Output) - mux.WitnessDestinations[0].Value = &bc.AssetAmount{ - AssetId: out.Source.Value.AssetId, - Amount: out.Source.Value.Amount + 1, - } - mux.Sources[0].Value.Amount++ // the mux must still balance - }, - err: ErrMismatchedValue, - }, - { - desc: "empty tx results", - f: func() { - tx.ResultIds = nil - }, - err: ErrEmptyResults, - }, - { - desc: "empty tx results, but that's OK", - f: func() { - tx.Version = 2 - tx.ResultIds = nil - }, - }, - { - desc: "issuance program failure", - f: func() { - iss := txIssuance(t, tx, 0) - iss.WitnessArguments[0] = []byte{} - }, - err: vm.ErrFalseVMResult, - }, - { - desc: "spend control program failure", - f: func() { - spend := txSpend(t, tx, 1) - spend.WitnessArguments[0] = []byte{} - }, - err: vm.ErrFalseVMResult, - }, - { - desc: "mismatched spent source/witness value", - f: func() { - spend := txSpend(t, tx, 1) - spentOutput := tx.Entries[*spend.SpentOutputId].(*bc.Output) - spentOutput.Source.Value = &bc.AssetAmount{ - AssetId: spend.WitnessDestination.Value.AssetId, - Amount: spend.WitnessDestination.Value.Amount + 1, - } - }, - err: ErrMismatchedValue, - }, - { - desc: "gas out of limit", - f: func() { - vs.tx.SerializedSize = 10000000 - }, - err: ErrOverGasCredit, - }, - { - desc: "can't find gas spend input in entries", - f: func() { - spendID := mux.Sources[len(mux.Sources)-1].Ref - delete(tx.Entries, *spendID) - mux.Sources = mux.Sources[:len(mux.Sources)-1] - }, - err: bc.ErrMissingEntry, - }, - { - desc: "no gas spend input", - f: func() { - spendID := mux.Sources[len(mux.Sources)-1].Ref - delete(tx.Entries, *spendID) - mux.Sources = mux.Sources[:len(mux.Sources)-1] - tx.GasInputIDs = nil - vs.gasStatus.GasLeft = 0 - }, - err: vm.ErrRunLimitExceeded, - }, - { - desc: "no gas spend input, but set gas left, so it's ok", - f: func() { - spendID := mux.Sources[len(mux.Sources)-1].Ref - delete(tx.Entries, *spendID) - mux.Sources = mux.Sources[:len(mux.Sources)-1] - tx.GasInputIDs = nil - }, - err: nil, - }, - { - desc: "mismatched gas spend input destination amount/prevout source amount", - f: func() { - spendID := mux.Sources[len(mux.Sources)-1].Ref - spend := tx.Entries[*spendID].(*bc.Spend) - spend.WitnessDestination.Value = &bc.AssetAmount{ - AssetId: spend.WitnessDestination.Value.AssetId, - Amount: spend.WitnessDestination.Value.Amount + 1, - } - }, - err: ErrMismatchedValue, - }, - { - desc: "mismatched witness asset destination", - f: func() { - issuanceID := mux.Sources[0].Ref - issuance := tx.Entries[*issuanceID].(*bc.Issuance) - issuance.WitnessAssetDefinition.Data = &bc.Hash{V0: 9999} - }, - err: ErrMismatchedAssetID, - }, - { - desc: "issuance witness position greater than length of mux sources", - f: func() { - issuanceID := mux.Sources[0].Ref - issuance := tx.Entries[*issuanceID].(*bc.Issuance) - issuance.WitnessDestination.Position = uint64(len(mux.Sources) + 1) - }, - err: ErrPosition, - }, - { - desc: "normal coinbase tx", - f: func() { - addCoinbase(consensus.BTMAssetID, 100000, nil) - }, - err: nil, - }, - { - desc: "invalid coinbase tx asset id", - f: func() { - addCoinbase(&bc.AssetID{V1: 100}, 100000, nil) - }, - err: ErrWrongCoinbaseAsset, - }, - { - desc: "coinbase tx is not first tx in block", - f: func() { - addCoinbase(consensus.BTMAssetID, 100000, nil) - vs.block.Transactions[0] = nil - }, - err: ErrWrongCoinbaseTransaction, - }, - { - desc: "coinbase arbitrary size out of limit", - f: func() { - arbitrary := make([]byte, consensus.CoinbaseArbitrarySizeLimit+1) - addCoinbase(consensus.BTMAssetID, 100000, arbitrary) - }, - err: ErrCoinbaseArbitraryOversize, - }, - { - desc: "normal retirement output", - f: func() { - outputID := tx.ResultIds[0] - output := tx.Entries[*outputID].(*bc.Output) - retirement := bc.NewRetirement(output.Source, output.Ordinal) - retirementID := bc.EntryID(retirement) - tx.Entries[retirementID] = retirement - delete(tx.Entries, *outputID) - tx.ResultIds[0] = &retirementID - mux.WitnessDestinations[0].Ref = &retirementID - }, - err: nil, - }, - { - desc: "ordinal doesn't matter for prevouts", - f: func() { - spend := txSpend(t, tx, 1) - prevout := tx.Entries[*spend.SpentOutputId].(*bc.Output) - newPrevout := bc.NewOutput(prevout.Source, prevout.ControlProgram, 10) - hash := bc.EntryID(newPrevout) - spend.SpentOutputId = &hash - }, - err: nil, - }, - { - desc: "mux witness destination have no source", - f: func() { - dest := &bc.ValueDestination{ - Value: &bc.AssetAmount{ - AssetId: &bc.AssetID{V2: 1000}, - Amount: 100, - }, - Ref: mux.WitnessDestinations[0].Ref, - Position: 0, - } - mux.WitnessDestinations = append(mux.WitnessDestinations, dest) - }, - err: ErrNoSource, - }, - } - - for i, c := range cases { - t.Run(c.desc, func(t *testing.T) { - fixture = sample(t, nil) - tx = types.NewTx(*fixture.tx).Tx - vs = &validationState{ - block: mockBlock(), - tx: tx, - entryID: tx.ID, - gasStatus: &GasState{ - GasLeft: int64(80000), - GasUsed: 0, - }, - cache: make(map[bc.Hash]error), - } - muxID := getMuxID(tx) - mux = tx.Entries[*muxID].(*bc.Mux) - - if c.f != nil { - c.f() - } - err := checkValid(vs, tx.TxHeader) - - if rootErr(err) != c.err { - t.Errorf("case #%d (%s) got error %s, want %s; validationState is:\n%s", i, c.desc, err, c.err, spew.Sdump(vs)) - } - }) - } -} - -// TestCoinbase test the coinbase transaction is valid (txtest#1016) -func TestCoinbase(t *testing.T) { - cp, _ := vmutil.DefaultCoinbaseProgram() - retire, _ := vmutil.RetireProgram([]byte{}) - CbTx := types.MapTx(&types.TxData{ - SerializedSize: 1, - Inputs: []*types.TxInput{ - types.NewCoinbaseInput(nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 888, cp), - }, - }) - - cases := []struct { - block *bc.Block - txIndex int - GasValid bool - err error - }{ - { - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Height: 666}, - Transactions: []*bc.Tx{CbTx}, - }, - txIndex: 0, - GasValid: true, - err: nil, - }, - { - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Height: 666}, - Transactions: []*bc.Tx{ - CbTx, - types.MapTx(&types.TxData{ - SerializedSize: 1, - Inputs: []*types.TxInput{ - types.NewCoinbaseInput(nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 888, cp), - }, - }), - }, - }, - txIndex: 1, - GasValid: false, - err: ErrWrongCoinbaseTransaction, - }, - { - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Height: 666}, - Transactions: []*bc.Tx{ - CbTx, - types.MapTx(&types.TxData{ - SerializedSize: 1, - Inputs: []*types.TxInput{ - types.NewCoinbaseInput(nil), - types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 888, cp), - types.NewTxOutput(*consensus.BTMAssetID, 90000000, cp), - }, - }), - }, - }, - txIndex: 1, - GasValid: false, - err: ErrWrongCoinbaseTransaction, - }, - { - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Height: 666}, - Transactions: []*bc.Tx{ - CbTx, - types.MapTx(&types.TxData{ - SerializedSize: 1, - Inputs: []*types.TxInput{ - types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp), - types.NewCoinbaseInput(nil), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 888, cp), - types.NewTxOutput(*consensus.BTMAssetID, 90000000, cp), - }, - }), - }, - }, - txIndex: 1, - GasValid: false, - err: ErrWrongCoinbaseTransaction, - }, - { - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Height: 666}, - Transactions: []*bc.Tx{ - types.MapTx(&types.TxData{ - SerializedSize: 1, - Inputs: []*types.TxInput{ - types.NewCoinbaseInput(nil), - types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 888, cp), - types.NewTxOutput(*consensus.BTMAssetID, 90000000, cp), - }, - }), - }, - }, - txIndex: 0, - GasValid: true, - err: nil, - }, - { - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Height: 666}, - Transactions: []*bc.Tx{ - types.MapTx(&types.TxData{ - SerializedSize: 1, - Inputs: []*types.TxInput{ - types.NewCoinbaseInput(nil), - types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, retire), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 888, cp), - types.NewTxOutput(*consensus.BTMAssetID, 90000000, cp), - }, - }), - }, - }, - txIndex: 0, - GasValid: false, - err: vm.ErrReturn, - }, - } - - for i, c := range cases { - gasStatus, err := ValidateTx(c.block.Transactions[c.txIndex], c.block) - - if rootErr(err) != c.err { - t.Errorf("#%d got error %s, want %s", i, err, c.err) - } - if c.GasValid != gasStatus.GasValid { - t.Errorf("#%d got GasValid %t, want %t", i, gasStatus.GasValid, c.GasValid) - } - } -} - -func TestRuleAA(t *testing.T) { - testData := "070100040161015f9bc47dda88eee18c7433340c16e054cabee4318a8d638e873be19e979df81dc7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0e3f9f5c80e01011600147c7662d92bd5e77454736f94731c60a6e9cbc69f6302404a17a5995b8163ee448719b462a5694b22a35522dd9883333fd462cc3d0aabf049445c5cbb911a40e1906a5bea99b23b1a79e215eeb1a818d8b1dd27e06f3004200530c4bc9dd3cbf679fec6d824ce5c37b0c8dab88b67bcae3b000924b7dce9940160015ee334d4fe18398f0232d2aca7050388ce4ee5ae82c8148d7f0cea748438b65135ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80ace6842001011600147c7662d92bd5e77454736f94731c60a6e9cbc69f6302404a17a5995b8163ee448719b462a5694b22a35522dd9883333fd462cc3d0aabf049445c5cbb911a40e1906a5bea99b23b1a79e215eeb1a818d8b1dd27e06f3004200530c4bc9dd3cbf679fec6d824ce5c37b0c8dab88b67bcae3b000924b7dce9940161015f9bc47dda88eee18c7433340c16e054cabee4318a8d638e873be19e979df81dc7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0e3f9f5c80e01011600147c7662d92bd5e77454736f94731c60a6e9cbc69f63024062c29b20941e7f762c3afae232f61d8dac1c544825931e391408c6715c408ef69f494a1b3b61ce380ddee0c8b18ecac2b46ef96a62eebb6ec40f9f545410870a200530c4bc9dd3cbf679fec6d824ce5c37b0c8dab88b67bcae3b000924b7dce9940160015ee334d4fe18398f0232d2aca7050388ce4ee5ae82c8148d7f0cea748438b65135ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80ace6842001011600147c7662d92bd5e77454736f94731c60a6e9cbc69f630240e443d66c75b4d5fa71676d60b0b067e6941f06349f31e5f73a7d51a73f5797632b2e01e8584cd1c8730dc16df075866b0c796bd7870182e2da4b37188208fe02200530c4bc9dd3cbf679fec6d824ce5c37b0c8dab88b67bcae3b000924b7dce99402013effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08ba3fae80e01160014aac0345165045e612b3d7363f39a372bead80ce700013effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08fe0fae80e01160014aac0345165045e612b3d7363f39a372bead80ce700" - tx := types.Tx{} - if err := tx.UnmarshalText([]byte(testData)); err != nil { - t.Errorf("fail on unmarshal txData: %s", err) - } - - cases := []struct { - block *bc.Block - GasValid bool - err error - }{ - { - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{ - Height: ruleAA - 1, - }, - }, - GasValid: true, - err: ErrMismatchedPosition, - }, - { - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{ - Height: ruleAA, - }, - }, - GasValid: false, - err: ErrEmptyInputIDs, - }, - } - - for i, c := range cases { - gasStatus, err := ValidateTx(tx.Tx, c.block) - if rootErr(err) != c.err { - t.Errorf("#%d got error %s, want %s", i, err, c.err) - } - if c.GasValid != gasStatus.GasValid { - t.Errorf("#%d got GasValid %t, want %t", i, gasStatus.GasValid, c.GasValid) - } - } - -} - -// TestTimeRange test the checkTimeRange function (txtest#1004) -func TestTimeRange(t *testing.T) { - cases := []struct { - timeRange uint64 - err bool - }{ - { - timeRange: 0, - err: false, - }, - { - timeRange: 334, - err: false, - }, - { - timeRange: 332, - err: true, - }, - { - timeRange: 1521625824, - err: false, - }, - } - - block := &bc.Block{ - BlockHeader: &bc.BlockHeader{ - Height: 333, - Timestamp: 1521625823, - }, - } - - tx := types.MapTx(&types.TxData{ - SerializedSize: 1, - TimeRange: 0, - Inputs: []*types.TxInput{ - mockGasTxInput(), - }, - Outputs: []*types.TxOutput{ - types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6a}), - }, - }) - - for i, c := range cases { - tx.TimeRange = c.timeRange - if _, err := ValidateTx(tx, block); (err != nil) != c.err { - t.Errorf("#%d got error %t, want %t", i, !c.err, c.err) - } - } -} - -func TestStandardTx(t *testing.T) { - fixture := sample(t, nil) - tx := types.NewTx(*fixture.tx).Tx - - cases := []struct { - desc string - f func() - err error - }{ - { - desc: "normal standard tx", - err: nil, - }, - { - desc: "not standard tx in spend input", - f: func() { - inputID := tx.GasInputIDs[0] - spend := tx.Entries[inputID].(*bc.Spend) - spentOutput, err := tx.Output(*spend.SpentOutputId) - if err != nil { - t.Fatal(err) - } - spentOutput.ControlProgram = &bc.Program{Code: []byte{0}} - }, - err: ErrNotStandardTx, - }, - { - desc: "not standard tx in output", - f: func() { - outputID := tx.ResultIds[0] - output := tx.Entries[*outputID].(*bc.Output) - output.ControlProgram = &bc.Program{Code: []byte{0}} - }, - err: ErrNotStandardTx, - }, - } - - for i, c := range cases { - if c.f != nil { - c.f() - } - if err := checkStandardTx(tx, 0); err != c.err { - t.Errorf("case #%d (%s) got error %t, want %t", i, c.desc, err, c.err) - } - } -} - -func TestValidateTxVersion(t *testing.T) { - cases := []struct { - desc string - block *bc.Block - err error - }{ - { - desc: "tx version greater than 1 (txtest#1001)", - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Version: 1}, - Transactions: []*bc.Tx{ - {TxHeader: &bc.TxHeader{Version: 2}}, - }, - }, - err: ErrTxVersion, - }, - { - desc: "tx version equals 0 (txtest#1002)", - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Version: 1}, - Transactions: []*bc.Tx{ - {TxHeader: &bc.TxHeader{Version: 0}}, - }, - }, - err: ErrTxVersion, - }, - { - desc: "tx version equals max uint64 (txtest#1003)", - block: &bc.Block{ - BlockHeader: &bc.BlockHeader{Version: 1}, - Transactions: []*bc.Tx{ - {TxHeader: &bc.TxHeader{Version: math.MaxUint64}}, - }, - }, - err: ErrTxVersion, - }, - } - - for i, c := range cases { - if _, err := ValidateTx(c.block.Transactions[0], c.block); rootErr(err) != c.err { - t.Errorf("case #%d (%s) got error %t, want %t", i, c.desc, err, c.err) - } - } -} - -// A txFixture is returned by sample (below) to produce a sample -// transaction, which takes a separate, optional _input_ txFixture to -// affect the transaction that's built. The components of the -// transaction are the fields of txFixture. -type txFixture struct { - initialBlockID bc.Hash - issuanceProg bc.Program - issuanceArgs [][]byte - assetDef []byte - assetID bc.AssetID - txVersion uint64 - txInputs []*types.TxInput - txOutputs []*types.TxOutput - tx *types.TxData -} - -// Produces a sample transaction in a txFixture object (see above). A -// separate input txFixture can be used to alter the transaction -// that's created. -// -// The output of this function can be used as the input to a -// subsequent call to make iterative refinements to a test object. -// -// The default transaction produced is valid and has three inputs: -// - an issuance of 10 units -// - a spend of 20 units -// - a spend of 40 units -// and two outputs, one of 25 units and one of 45 units. -// All amounts are denominated in the same asset. -// -// The issuance program for the asset requires two numbers as -// arguments that add up to 5. The prevout control programs require -// two numbers each, adding to 9 and 13, respectively. -// -// The min and max times for the transaction are now +/- one minute. -func sample(tb testing.TB, in *txFixture) *txFixture { - var result txFixture - if in != nil { - result = *in - } - - if result.initialBlockID.IsZero() { - result.initialBlockID = *newHash(1) - } - if testutil.DeepEqual(result.issuanceProg, bc.Program{}) { - prog, err := vm.Assemble("ADD 5 NUMEQUAL") - if err != nil { - tb.Fatal(err) - } - result.issuanceProg = bc.Program{VmVersion: 1, Code: prog} - } - if len(result.issuanceArgs) == 0 { - result.issuanceArgs = [][]byte{{2}, {3}} - } - if len(result.assetDef) == 0 { - result.assetDef = []byte{2} - } - if result.assetID.IsZero() { - refdatahash := hashData(result.assetDef) - result.assetID = bc.ComputeAssetID(result.issuanceProg.Code, result.issuanceProg.VmVersion, &refdatahash) - } - - if result.txVersion == 0 { - result.txVersion = 1 - } - if len(result.txInputs) == 0 { - cp1, err := vm.Assemble("ADD 9 NUMEQUAL") - if err != nil { - tb.Fatal(err) - } - args1 := [][]byte{{4}, {5}} - - cp2, err := vm.Assemble("ADD 13 NUMEQUAL") - if err != nil { - tb.Fatal(err) - } - args2 := [][]byte{{6}, {7}} - - result.txInputs = []*types.TxInput{ - types.NewIssuanceInput([]byte{3}, 10, result.issuanceProg.Code, result.issuanceArgs, result.assetDef), - types.NewSpendInput(args1, *newHash(5), result.assetID, 20, 0, cp1), - types.NewSpendInput(args2, *newHash(8), result.assetID, 40, 0, cp2), - } - } - - result.txInputs = append(result.txInputs, mockGasTxInput()) - - if len(result.txOutputs) == 0 { - cp1, err := vm.Assemble("ADD 17 NUMEQUAL") - if err != nil { - tb.Fatal(err) - } - cp2, err := vm.Assemble("ADD 21 NUMEQUAL") - if err != nil { - tb.Fatal(err) - } - - result.txOutputs = []*types.TxOutput{ - types.NewTxOutput(result.assetID, 25, cp1), - types.NewTxOutput(result.assetID, 45, cp2), - } - } - - result.tx = &types.TxData{ - Version: result.txVersion, - Inputs: result.txInputs, - Outputs: result.txOutputs, - } - - return &result -} - -func mockBlock() *bc.Block { - return &bc.Block{ - BlockHeader: &bc.BlockHeader{ - Height: 666, - }, - } -} - -func mockGasTxInput() *types.TxInput { - cp, _ := vmutil.DefaultCoinbaseProgram() - return types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp) -} - -// Like errors.Root, but also unwraps vm.Error objects. -func rootErr(e error) error { - return errors.Root(e) -} - -func hashData(data []byte) bc.Hash { - var b32 [32]byte - sha3pool.Sum256(b32[:], data) - return bc.NewHash(b32) -} - -func newHash(n byte) *bc.Hash { - h := bc.NewHash([32]byte{n}) - return &h -} - -func newAssetID(n byte) *bc.AssetID { - a := bc.NewAssetID([32]byte{n}) - return &a -} - -func txIssuance(t *testing.T, tx *bc.Tx, index int) *bc.Issuance { - id := tx.InputIDs[index] - res, err := tx.Issuance(id) - if err != nil { - t.Fatal(err) - } - return res -} - -func txSpend(t *testing.T, tx *bc.Tx, index int) *bc.Spend { - id := tx.InputIDs[index] - res, err := tx.Spend(id) - if err != nil { - t.Fatal(err) - } - return res -} - -func getMuxID(tx *bc.Tx) *bc.Hash { - out := tx.Entries[*tx.ResultIds[0]] - switch result := out.(type) { - case *bc.Output: - return result.Source.Ref - case *bc.Retirement: - return result.Source.Ref - } - return nil -} diff --git a/test/tx_test.go b/test/tx_test.go index d951964e..9bf219df 100644 --- a/test/tx_test.go +++ b/test/tx_test.go @@ -163,14 +163,6 @@ func (t *ttTransaction) create(g *TxGenerator) (*types.Tx, error) { return g.Sign(t.Passwords) } -func TestTx(t *testing.T) { - walk(t, txTestDir, func(t *testing.T, name string, test *TxTestConfig) { - if err := test.Run(); err != nil { - t.Fatal(err) - } - }) -} - func TestCoinbaseMature(t *testing.T) { db := dbm.NewDB("test_coinbase_mature_db", "leveldb", "test_coinbase_mature_db") defer os.RemoveAll("test_coinbase_mature_db")