only:
- master
- dev
+ - politic
script:
- make ci
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 {
"math/big"
"github.com/bytom/consensus"
- "github.com/bytom/mining/tensority"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
)
// 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
"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
// 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
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 (
// 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
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
}
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) {
"testing"
"time"
- "github.com/davecgh/go-spew/spew"
-
"github.com/bytom/consensus"
"github.com/bytom/database/storage"
"github.com/bytom/event"
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))
- }
- }
-}
+++ /dev/null
-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)
-}
+++ /dev/null
-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
-}
}
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
}
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
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 {
+++ /dev/null
-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
-}
+++ /dev/null
-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
-}
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")