"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"
+ "github.com/bytom/bytom/consensus"
+ "github.com/bytom/bytom/crypto/sha3pool"
+ "github.com/bytom/bytom/errors"
+ "github.com/bytom/bytom/protocol/bc"
+ "github.com/bytom/bytom/protocol/bc/types"
+ "github.com/bytom/bytom/protocol/vm"
+ "github.com/bytom/bytom/protocol/vm/vmutil"
+ "github.com/bytom/bytom/testutil"
)
func init() {
f: func(input *GasState) error {
return input.setGas(-10000, 0)
},
- err: errGasCalculate,
+ err: ErrGasCalculate,
},
{
input: &GasState{
BTMValue: 0,
},
output: &GasState{
- GasLeft: 100000,
+ GasLeft: 200000,
GasUsed: 0,
BTMValue: 80000000000,
},
},
{
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,
f: func(input *GasState) error {
return input.updateUsage(-1)
},
- err: errGasCalculate,
+ err: ErrGasCalculate,
},
{
input: &GasState{
},
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 {
}
}
+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
iss := tx.Entries[*mux.Sources[0].Ref].(*bc.Issuance)
iss.WitnessDestination.Value.Amount++
},
- err: errUnbalanced,
+ err: ErrUnbalanced,
},
{
desc: "unbalanced mux amounts",
f: func() {
mux.WitnessDestinations[0].Value.Amount++
},
- err: errUnbalanced,
+ err: ErrUnbalanced,
},
{
desc: "balanced mux amounts",
iss := tx.Entries[*mux.Sources[0].Ref].(*bc.Issuance)
iss.WitnessDestination.Value.Amount = math.MaxInt64
},
- err: errOverflow,
+ err: ErrOverflow,
},
{
desc: "underflowing mux destination amounts",
out = tx.Entries[*mux.WitnessDestinations[1].Ref].(*bc.Output)
out.Source.Value.Amount = math.MaxInt64
},
- err: errOverflow,
+ err: ErrOverflow,
},
{
desc: "unbalanced mux assets",
sp := tx.Entries[*mux.Sources[1].Ref].(*bc.Spend)
sp.WitnessDestination.Value.AssetId = newAssetID(255)
},
- err: errUnbalanced,
+ err: ErrUnbalanced,
},
{
desc: "mismatched output source / mux dest position",
f: func() {
tx.Entries[*tx.ResultIds[0]].(*bc.Output).Source.Position = 1
},
- err: errMismatchedPosition,
+ 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",
tx.Entries[*out2ID] = out2
mux.WitnessDestinations[0].Ref = out2ID
},
- err: errMismatchedReference,
+ 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,
+ err: ErrPosition,
},
{
desc: "mismatched mux dest value / output source value",
}
mux.Sources[0].Value.Amount++ // the mux must still balance
},
- err: errMismatchedValue,
+ err: ErrMismatchedValue,
},
{
desc: "empty tx results",
f: func() {
tx.ResultIds = nil
},
- err: errEmptyResults,
+ err: ErrEmptyResults,
},
{
desc: "empty tx results, but that's OK",
Amount: spend.WitnessDestination.Value.Amount + 1,
}
},
- err: errMismatchedValue,
+ err: ErrMismatchedValue,
},
{
desc: "gas out of limit",
f: func() {
vs.tx.SerializedSize = 10000000
},
- err: errOverGasCredit,
- },
- {
- desc: "overflowing storage gas",
- f: func() {
- vs.tx.SerializedSize = math.MaxInt64
- },
- err: errGasCalculate,
+ err: ErrOverGasCredit,
},
{
desc: "can't find gas spend input in entries",
Amount: spend.WitnessDestination.Value.Amount + 1,
}
},
- err: errMismatchedValue,
+ err: ErrMismatchedValue,
},
{
desc: "mismatched witness asset destination",
issuance := tx.Entries[*issuanceID].(*bc.Issuance)
issuance.WitnessAssetDefinition.Data = &bc.Hash{V0: 9999}
},
- err: errMismatchedAssetID,
+ err: ErrMismatchedAssetID,
},
{
desc: "issuance witness position greater than length of mux sources",
issuance := tx.Entries[*issuanceID].(*bc.Issuance)
issuance.WitnessDestination.Position = uint64(len(mux.Sources) + 1)
},
- err: errPosition,
+ err: ErrPosition,
},
{
desc: "normal coinbase tx",
f: func() {
addCoinbase(&bc.AssetID{V1: 100}, 100000, nil)
},
- err: errWrongCoinbaseAsset,
+ err: ErrWrongCoinbaseAsset,
},
{
desc: "coinbase tx is not first tx in block",
addCoinbase(consensus.BTMAssetID, 100000, nil)
vs.block.Transactions[0] = nil
},
- err: errWrongCoinbaseTransaction,
+ err: ErrWrongCoinbaseTransaction,
},
{
desc: "coinbase arbitrary size out of limit",
arbitrary := make([]byte, consensus.CoinbaseArbitrarySizeLimit+1)
addCoinbase(consensus.BTMAssetID, 100000, arbitrary)
},
- err: errCoinbaseArbitraryOversize,
+ err: ErrCoinbaseArbitraryOversize,
},
{
desc: "normal retirement output",
}
mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
},
- err: errNoSource,
+ err: ErrNoSource,
},
}
- for _, c := range cases {
+ for i, c := range cases {
t.Run(c.desc, func(t *testing.T) {
fixture = sample(t, nil)
tx = types.NewTx(*fixture.tx).Tx
err := checkValid(vs, tx.TxHeader)
if rootErr(err) != c.err {
- t.Errorf("got error %s, want %s; validationState is:\n%s", err, c.err, spew.Sdump(vs))
+ 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) {
- CbTx := mockCoinbaseTx(5000000000)
+ 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
- tx *bc.Tx
+ txIndex int
GasValid bool
err error
}{
{
block: &bc.Block{
- BlockHeader: &bc.BlockHeader{
- Height: 666,
- },
+ BlockHeader: &bc.BlockHeader{Height: 666},
Transactions: []*bc.Tx{CbTx},
},
- 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.tx, c.block)
+ 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)
}
}
+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
timeRange: 1521625824,
err: false,
},
- {
- timeRange: 1421625824,
- err: true,
- },
}
block := &bc.Block{
}
}
+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
result.issuanceProg = bc.Program{VmVersion: 1, Code: prog}
}
if len(result.issuanceArgs) == 0 {
- result.issuanceArgs = [][]byte{[]byte{2}, []byte{3}}
+ result.issuanceArgs = [][]byte{{2}, {3}}
}
if len(result.assetDef) == 0 {
result.assetDef = []byte{2}
if err != nil {
tb.Fatal(err)
}
- args1 := [][]byte{[]byte{4}, []byte{5}}
+ args1 := [][]byte{{4}, {5}}
cp2, err := vm.Assemble("ADD 13 NUMEQUAL")
if err != nil {
tb.Fatal(err)
}
- args2 := [][]byte{[]byte{6}, []byte{7}}
+ args2 := [][]byte{{6}, {7}}
result.txInputs = []*types.TxInput{
types.NewIssuanceInput([]byte{3}, 10, result.issuanceProg.Code, result.issuanceArgs, result.assetDef),
}
}
-func mockCoinbaseTx(amount uint64) *bc.Tx {
- cp, _ := vmutil.DefaultCoinbaseProgram()
- return types.MapTx(&types.TxData{
- SerializedSize: 1,
- Inputs: []*types.TxInput{
- types.NewCoinbaseInput(nil),
- },
- Outputs: []*types.TxOutput{
- types.NewTxOutput(*consensus.BTMAssetID, amount, cp),
- },
- })
-}
-
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 {
- for {
- e = errors.Root(e)
- if e2, ok := e.(vm.Error); ok {
- e = e2.Err
- continue
- }
- return e
- }
+ return errors.Root(e)
}
func hashData(data []byte) bc.Hash {