mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-10-14 00:59:33 +00:00
[DEV-345] Enforce requirement for transactions from 1(DAGCoin) or 2(sub network registry) sub network to have gas = 0 (#157)
* [DEV-345] Validate that gas and payload are 0 when required by sub-network * [DEV-345] Remove check for txOut.Value < 0, since txOut.Value is a uint64 * [DEV-345] Added tests for CheckTransactionSanity * [DEV-345] Remove checks for Gas and Payload validity in wire.MsgTx.Decode * [DEV-345] Verify that payload in Gas sub-network is always 8 bytes (uint64). * [DEV-345] Renamed tstCheck{Script/Rule}Error to check{Script/Rule}Error * [DEV-345] Improved formatting
This commit is contained in:
parent
1743877b66
commit
6b55950901
@ -7,9 +7,11 @@ package blockdag
|
|||||||
import (
|
import (
|
||||||
"compress/bzip2"
|
"compress/bzip2"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -220,3 +222,35 @@ func buildNodeGenerator(phantomK uint32, withChildren bool) func(parents blockSe
|
|||||||
}
|
}
|
||||||
return buildNode
|
return buildNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkRuleError ensures the type of the two passed errors are of the
|
||||||
|
// same type (either both nil or both of type RuleError) and their error codes
|
||||||
|
// match when not nil.
|
||||||
|
func checkRuleError(gotErr, wantErr error) error {
|
||||||
|
// Ensure the error code is of the expected type and the error
|
||||||
|
// code matches the value specified in the test instance.
|
||||||
|
if reflect.TypeOf(gotErr) != reflect.TypeOf(wantErr) {
|
||||||
|
return fmt.Errorf("wrong error - got %T (%[1]v), want %T",
|
||||||
|
gotErr, wantErr)
|
||||||
|
}
|
||||||
|
if gotErr == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the want error type is a script error.
|
||||||
|
werr, ok := wantErr.(RuleError)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unexpected test error type %T", wantErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the error codes match. It's safe to use a raw type assert
|
||||||
|
// here since the code above already proved they are the same type and
|
||||||
|
// the want error is a script error.
|
||||||
|
gotErrorCode := gotErr.(RuleError).ErrorCode
|
||||||
|
if gotErrorCode != werr.ErrorCode {
|
||||||
|
return fmt.Errorf("mismatched error code - got %v (%v), want %v",
|
||||||
|
gotErrorCode, gotErr, werr.ErrorCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -220,6 +220,10 @@ const (
|
|||||||
// by subnetwork
|
// by subnetwork
|
||||||
ErrInvalidGas
|
ErrInvalidGas
|
||||||
|
|
||||||
|
// ErrInvalidPayload transaction includes a payload in a sub-network that doesn't allow
|
||||||
|
// a Payload
|
||||||
|
ErrInvalidPayload
|
||||||
|
|
||||||
// ErrSubNetwork indicates that a block doesn't adhere to the sub-network
|
// ErrSubNetwork indicates that a block doesn't adhere to the sub-network
|
||||||
// registry rules
|
// registry rules
|
||||||
ErrSubNetworkRegistry
|
ErrSubNetworkRegistry
|
||||||
@ -270,6 +274,7 @@ var errorCodeStrings = map[ErrorCode]string{
|
|||||||
ErrFinality: "ErrFinality",
|
ErrFinality: "ErrFinality",
|
||||||
ErrTransactionsNotSorted: "ErrTransactionsNotSorted",
|
ErrTransactionsNotSorted: "ErrTransactionsNotSorted",
|
||||||
ErrInvalidGas: "ErrInvalidGas",
|
ErrInvalidGas: "ErrInvalidGas",
|
||||||
|
ErrInvalidPayload: "ErrInvalidPayload",
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the ErrorCode as a human-readable name.
|
// String returns the ErrorCode as a human-readable name.
|
||||||
|
@ -58,6 +58,7 @@ func TestErrorCodeStringer(t *testing.T) {
|
|||||||
{ErrFinality, "ErrFinality"},
|
{ErrFinality, "ErrFinality"},
|
||||||
{ErrTransactionsNotSorted, "ErrTransactionsNotSorted"},
|
{ErrTransactionsNotSorted, "ErrTransactionsNotSorted"},
|
||||||
{ErrInvalidGas, "ErrInvalidGas"},
|
{ErrInvalidGas, "ErrInvalidGas"},
|
||||||
|
{ErrInvalidPayload, "ErrInvalidPayload"},
|
||||||
{0xffff, "Unknown ErrorCode (65535)"},
|
{0xffff, "Unknown ErrorCode (65535)"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,12 @@ package blockdag
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/daglabs/btcd/util/subnetworkid"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/daglabs/btcd/util/subnetworkid"
|
||||||
|
|
||||||
"github.com/daglabs/btcd/dagconfig"
|
"github.com/daglabs/btcd/dagconfig"
|
||||||
"github.com/daglabs/btcd/dagconfig/daghash"
|
"github.com/daglabs/btcd/dagconfig/daghash"
|
||||||
"github.com/daglabs/btcd/database"
|
"github.com/daglabs/btcd/database"
|
||||||
@ -104,6 +105,41 @@ func DAGSetup(dbName string, config Config) (*BlockDAG, func(), error) {
|
|||||||
// OpTrueScript is script returning TRUE
|
// OpTrueScript is script returning TRUE
|
||||||
var OpTrueScript = []byte{txscript.OpTrue}
|
var OpTrueScript = []byte{txscript.OpTrue}
|
||||||
|
|
||||||
|
type txSubnetworkData struct {
|
||||||
|
subnetworkID subnetworkid.SubNetworkID
|
||||||
|
Gas uint64
|
||||||
|
Payload []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTxForTest(numInputs uint32, numOutputs uint32, outputValue uint64, subnetworkData *txSubnetworkData) *wire.MsgTx {
|
||||||
|
tx := wire.NewMsgTx(wire.TxVersion)
|
||||||
|
|
||||||
|
for i := uint32(0); i < numInputs; i++ {
|
||||||
|
tx.AddTxIn(&wire.TxIn{
|
||||||
|
PreviousOutPoint: *wire.NewOutPoint(&daghash.Hash{}, i),
|
||||||
|
SignatureScript: []byte{},
|
||||||
|
Sequence: wire.MaxTxInSequenceNum,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for i := uint32(0); i < numOutputs; i++ {
|
||||||
|
tx.AddTxOut(&wire.TxOut{
|
||||||
|
PkScript: OpTrueScript,
|
||||||
|
Value: outputValue,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if subnetworkData != nil {
|
||||||
|
tx.SubNetworkID = subnetworkData.subnetworkID
|
||||||
|
tx.Gas = subnetworkData.Gas
|
||||||
|
tx.Payload = subnetworkData.Payload
|
||||||
|
} else {
|
||||||
|
tx.SubNetworkID = wire.SubNetworkDAGCoin
|
||||||
|
tx.Gas = 0
|
||||||
|
tx.Payload = []byte{}
|
||||||
|
}
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
|
||||||
// createCoinbaseTxForTest returns a coinbase transaction with the requested number of
|
// createCoinbaseTxForTest returns a coinbase transaction with the requested number of
|
||||||
// outputs paying an appropriate subsidy based on the passed block height to the
|
// outputs paying an appropriate subsidy based on the passed block height to the
|
||||||
// address associated with the harness. It automatically uses a standard
|
// address associated with the harness. It automatically uses a standard
|
||||||
|
@ -204,11 +204,6 @@ func CheckTransactionSanity(tx *util.Tx) error {
|
|||||||
var totalSatoshi uint64
|
var totalSatoshi uint64
|
||||||
for _, txOut := range msgTx.TxOut {
|
for _, txOut := range msgTx.TxOut {
|
||||||
satoshi := txOut.Value
|
satoshi := txOut.Value
|
||||||
if satoshi < 0 {
|
|
||||||
str := fmt.Sprintf("transaction output has negative "+
|
|
||||||
"value of %v", satoshi)
|
|
||||||
return ruleError(ErrBadTxOutValue, str)
|
|
||||||
}
|
|
||||||
if satoshi > util.MaxSatoshi {
|
if satoshi > util.MaxSatoshi {
|
||||||
str := fmt.Sprintf("transaction output value of %v is "+
|
str := fmt.Sprintf("transaction output value of %v is "+
|
||||||
"higher than max allowed value of %v", satoshi,
|
"higher than max allowed value of %v", satoshi,
|
||||||
@ -267,6 +262,30 @@ func CheckTransactionSanity(tx *util.Tx) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transactions in native and SubNetworkRegistry SubNetworks must have Gas = 0
|
||||||
|
if (msgTx.SubNetworkID == wire.SubNetworkDAGCoin ||
|
||||||
|
msgTx.SubNetworkID == wire.SubNetworkRegistry) &&
|
||||||
|
msgTx.Gas > 0 {
|
||||||
|
|
||||||
|
return ruleError(ErrInvalidGas, "transaction in the native or "+
|
||||||
|
"registry sub-networks has gas > 0 ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if msgTx.SubNetworkID == wire.SubNetworkDAGCoin &&
|
||||||
|
len(msgTx.Payload) > 0 {
|
||||||
|
|
||||||
|
return ruleError(ErrInvalidPayload,
|
||||||
|
"transaction in the native sub-network includes a payload")
|
||||||
|
}
|
||||||
|
|
||||||
|
if msgTx.SubNetworkID == wire.SubNetworkRegistry &&
|
||||||
|
len(msgTx.Payload) != 8 {
|
||||||
|
|
||||||
|
return ruleError(ErrInvalidPayload,
|
||||||
|
"transaction in the sub-network registry include a payload "+
|
||||||
|
"with length != 8 bytes")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,3 +1145,51 @@ var BlockWithWrongTxOrder = wire.MsgBlock{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckTransactionSanity(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
numInputs uint32
|
||||||
|
numOutputs uint32
|
||||||
|
outputValue uint64
|
||||||
|
subnetworkData *txSubnetworkData
|
||||||
|
extraModificationsFunc func(*wire.MsgTx)
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{"good one", 1, 1, 1, nil, nil, nil},
|
||||||
|
{"no inputs", 0, 1, 1, nil, nil, ruleError(ErrNoTxInputs, "")},
|
||||||
|
{"no outputs", 1, 0, 1, nil, nil, ruleError(ErrNoTxOutputs, "")},
|
||||||
|
{"too big", 100000, 1, 1, nil, nil, ruleError(ErrTxTooBig, "")},
|
||||||
|
{"too much satoshi in one output", 1, 1, util.MaxSatoshi + 1, nil, nil, ruleError(ErrBadTxOutValue, "")},
|
||||||
|
{"too much satoshi in total outputs", 1, 2, util.MaxSatoshi - 1, nil, nil, ruleError(ErrBadTxOutValue, "")},
|
||||||
|
{"duplicate inputs", 2, 1, 1, nil,
|
||||||
|
func(tx *wire.MsgTx) { tx.TxIn[1].PreviousOutPoint.Index = 0 },
|
||||||
|
ruleError(ErrDuplicateTxInputs, "")},
|
||||||
|
{"non-zero gas in DAGCoin", 1, 1, 0,
|
||||||
|
&txSubnetworkData{wire.SubNetworkDAGCoin, 1, []byte{}},
|
||||||
|
nil, ruleError(ErrInvalidGas, "")},
|
||||||
|
{"non-zero gas in subnetwork registry", 1, 1, 0,
|
||||||
|
&txSubnetworkData{wire.SubNetworkRegistry, 1, []byte{}},
|
||||||
|
nil, ruleError(ErrInvalidGas, "")},
|
||||||
|
{"non-zero payload in DAGCoin", 1, 1, 0,
|
||||||
|
&txSubnetworkData{wire.SubNetworkDAGCoin, 0, []byte{1}},
|
||||||
|
nil, ruleError(ErrInvalidPayload, "")},
|
||||||
|
{"payload in subnetwork registry isn't 8 bytes", 1, 1, 0,
|
||||||
|
&txSubnetworkData{wire.SubNetworkRegistry, 0, []byte{1, 2, 3, 4, 5, 6, 7}},
|
||||||
|
nil, ruleError(ErrInvalidPayload, "")},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
tx := createTxForTest(test.numInputs, test.numOutputs, test.outputValue, test.subnetworkData)
|
||||||
|
|
||||||
|
if test.extraModificationsFunc != nil {
|
||||||
|
test.extraModificationsFunc(tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := CheckTransactionSanity(util.NewTx(tx))
|
||||||
|
if e := checkRuleError(err, test.expectedErr); e != nil {
|
||||||
|
t.Errorf("TestCheckTransactionSanity: '%s': %v", test.name, e)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -156,7 +156,7 @@ func TestCheckErrorCondition(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = vm.CheckErrorCondition(test.finalScript)
|
err = vm.CheckErrorCondition(test.finalScript)
|
||||||
if e := tstCheckScriptError(err, test.expectedErr); e != nil {
|
if e := checkScriptError(err, test.expectedErr); e != nil {
|
||||||
t.Errorf("TestCheckErrorCondition: %d: %s", i, e)
|
t.Errorf("TestCheckErrorCondition: %d: %s", i, e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -443,7 +443,7 @@ func TestDisasmPC(t *testing.T) {
|
|||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
actual, err := vm.DisasmPC()
|
actual, err := vm.DisasmPC()
|
||||||
if e := tstCheckScriptError(err, test.expectedErr); e != nil {
|
if e := checkScriptError(err, test.expectedErr); e != nil {
|
||||||
t.Errorf("TestDisasmPC: %d: %s", i, e)
|
t.Errorf("TestDisasmPC: %d: %s", i, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +505,7 @@ func TestDisasmScript(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
actual, err := vm.DisasmScript(test.index)
|
actual, err := vm.DisasmScript(test.index)
|
||||||
if e := tstCheckScriptError(err, test.expectedErr); e != nil {
|
if e := checkScriptError(err, test.expectedErr); e != nil {
|
||||||
t.Errorf("TestDisasmScript: %d: %s", test.index, e)
|
t.Errorf("TestDisasmScript: %d: %s", test.index, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3654,7 +3654,7 @@ func TestUnparsingInvalidOpcodes(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
_, err := test.pop.bytes()
|
_, err := test.pop.bytes()
|
||||||
if e := tstCheckScriptError(err, test.expectedErr); e != nil {
|
if e := checkScriptError(err, test.expectedErr); e != nil {
|
||||||
t.Errorf("Parsed opcode test '%s': %v", test.name, e)
|
t.Errorf("Parsed opcode test '%s': %v", test.name, e)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ func TestMakeScriptNum(t *testing.T) {
|
|||||||
// code matches the value specified in the test instance.
|
// code matches the value specified in the test instance.
|
||||||
gotNum, err := makeScriptNum(test.serialized,
|
gotNum, err := makeScriptNum(test.serialized,
|
||||||
test.numLen)
|
test.numLen)
|
||||||
if e := tstCheckScriptError(err, test.err); e != nil {
|
if e := checkScriptError(err, test.err); e != nil {
|
||||||
t.Errorf("makeScriptNum(%#x): %v", test.serialized, e)
|
t.Errorf("makeScriptNum(%#x): %v", test.serialized, e)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// tstCheckScriptError ensures the type of the two passed errors are of the
|
// checkScriptError ensures the type of the two passed errors are of the
|
||||||
// same type (either both nil or both of type Error) and their error codes
|
// same type (either both nil or both of type Error) and their error codes
|
||||||
// match when not nil.
|
// match when not nil.
|
||||||
func tstCheckScriptError(gotErr, wantErr error) error {
|
func checkScriptError(gotErr, wantErr error) error {
|
||||||
// Ensure the error code is of the expected type and the error
|
// Ensure the error code is of the expected type and the error
|
||||||
// code matches the value specified in the test instance.
|
// code matches the value specified in the test instance.
|
||||||
if reflect.TypeOf(gotErr) != reflect.TypeOf(wantErr) {
|
if reflect.TypeOf(gotErr) != reflect.TypeOf(wantErr) {
|
||||||
@ -827,7 +827,7 @@ func TestStack(t *testing.T) {
|
|||||||
|
|
||||||
// Ensure the error code is of the expected type and the error
|
// Ensure the error code is of the expected type and the error
|
||||||
// code matches the value specified in the test instance.
|
// code matches the value specified in the test instance.
|
||||||
if e := tstCheckScriptError(err, test.err); e != nil {
|
if e := checkScriptError(err, test.err); e != nil {
|
||||||
t.Errorf("%s: %v", test.name, e)
|
t.Errorf("%s: %v", test.name, e)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -464,7 +464,7 @@ func TestCalcScriptInfo(t *testing.T) {
|
|||||||
pkScript := mustParseShortForm(test.pkScript)
|
pkScript := mustParseShortForm(test.pkScript)
|
||||||
|
|
||||||
si, err := CalcScriptInfo(sigScript, pkScript, test.isP2SH)
|
si, err := CalcScriptInfo(sigScript, pkScript, test.isP2SH)
|
||||||
if e := tstCheckScriptError(err, test.scriptInfoErr); e != nil {
|
if e := checkScriptError(err, test.scriptInfoErr); e != nil {
|
||||||
t.Errorf("scriptinfo test %q: %v", test.name, e)
|
t.Errorf("scriptinfo test %q: %v", test.name, e)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -610,7 +610,7 @@ func TestPayToAddrScript(t *testing.T) {
|
|||||||
t.Logf("Running %d tests", len(tests))
|
t.Logf("Running %d tests", len(tests))
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
pkScript, err := PayToAddrScript(test.in)
|
pkScript, err := PayToAddrScript(test.in)
|
||||||
if e := tstCheckScriptError(err, test.err); e != nil {
|
if e := checkScriptError(err, test.err); e != nil {
|
||||||
t.Errorf("PayToAddrScript #%d unexpected error - "+
|
t.Errorf("PayToAddrScript #%d unexpected error - "+
|
||||||
"got %v, want %v", i, err, test.err)
|
"got %v, want %v", i, err, test.err)
|
||||||
continue
|
continue
|
||||||
@ -716,7 +716,7 @@ func TestMultiSigScript(t *testing.T) {
|
|||||||
t.Logf("Running %d tests", len(tests))
|
t.Logf("Running %d tests", len(tests))
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
script, err := MultiSigScript(test.keys, test.nrequired)
|
script, err := MultiSigScript(test.keys, test.nrequired)
|
||||||
if e := tstCheckScriptError(err, test.err); e != nil {
|
if e := checkScriptError(err, test.err); e != nil {
|
||||||
t.Errorf("MultiSigScript #%d: %v", i, e)
|
t.Errorf("MultiSigScript #%d: %v", i, e)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -768,7 +768,7 @@ func TestCalcMultiSigStats(t *testing.T) {
|
|||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
script := mustParseShortForm(test.script)
|
script := mustParseShortForm(test.script)
|
||||||
_, _, err := CalcMultiSigStats(script)
|
_, _, err := CalcMultiSigStats(script)
|
||||||
if e := tstCheckScriptError(err, test.err); e != nil {
|
if e := checkScriptError(err, test.err); e != nil {
|
||||||
t.Errorf("CalcMultiSigStats #%d (%s): %v", i, test.name,
|
t.Errorf("CalcMultiSigStats #%d (%s): %v", i, test.name,
|
||||||
e)
|
e)
|
||||||
continue
|
continue
|
||||||
@ -1077,7 +1077,7 @@ func TestNullDataScript(t *testing.T) {
|
|||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
script, err := NullDataScript(test.data)
|
script, err := NullDataScript(test.data)
|
||||||
if e := tstCheckScriptError(err, test.err); e != nil {
|
if e := checkScriptError(err, test.err); e != nil {
|
||||||
t.Errorf("NullDataScript: #%d (%s): %v", i, test.name,
|
t.Errorf("NullDataScript: #%d (%s): %v", i, test.name,
|
||||||
e)
|
e)
|
||||||
continue
|
continue
|
||||||
|
@ -476,24 +476,12 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
isRegistrySubNetwork := msg.SubNetworkID == SubNetworkRegistry
|
|
||||||
|
|
||||||
if isRegistrySubNetwork && msg.Gas != 0 {
|
|
||||||
str := fmt.Sprintf("Transactions from subnetwork %v should have 0 gas", msg.SubNetworkID)
|
|
||||||
return messageError("MsgTx.BtcDecode", str)
|
|
||||||
}
|
|
||||||
|
|
||||||
payloadLength, err := ReadVarInt(r, pver)
|
payloadLength, err := ReadVarInt(r, pver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnScriptBuffers()
|
returnScriptBuffers()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isRegistrySubNetwork && payloadLength != 8 {
|
|
||||||
str := fmt.Sprintf("For registry sub network the payload should always be uint64 (8 bytes length)")
|
|
||||||
return messageError("MsgTx.BtcDecode", str)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.Payload = make([]byte, payloadLength)
|
msg.Payload = make([]byte, payloadLength)
|
||||||
_, err = io.ReadFull(r, msg.Payload)
|
_, err = io.ReadFull(r, msg.Payload)
|
||||||
}
|
}
|
||||||
|
@ -624,50 +624,6 @@ func TestTxSerializeErrors(t *testing.T) {
|
|||||||
if err == nil || err.Error() != expectedErr.Error() {
|
if err == nil || err.Error() != expectedErr.Error() {
|
||||||
t.Errorf("TestTxSerializeErrors: expected error %v but got %v", expectedErr, err)
|
t.Errorf("TestTxSerializeErrors: expected error %v but got %v", expectedErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
registryWithGasTxEncoded := []byte{
|
|
||||||
0x01, 0x00, 0x00, 0x00, // Version
|
|
||||||
0x00, // Varint for number of input transactions
|
|
||||||
0x00, // Varint for number of output transactions
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time
|
|
||||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, // Sub Network ID
|
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Gas
|
|
||||||
0x08, // Payload length varint
|
|
||||||
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Payload / Gas limit
|
|
||||||
}
|
|
||||||
|
|
||||||
r = bytes.NewReader(registryWithGasTxEncoded)
|
|
||||||
err = tx.Deserialize(r)
|
|
||||||
|
|
||||||
str = fmt.Sprintf("Transactions from subnetwork %v should have 0 gas", SubNetworkRegistry)
|
|
||||||
expectedErr = messageError("MsgTx.BtcDecode", str)
|
|
||||||
if err == nil || err.Error() != expectedErr.Error() {
|
|
||||||
t.Errorf("TestTxSerializeErrors: expected error %v but got %v", expectedErr, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
registryWithWrongPayloadTxEncoded := []byte{
|
|
||||||
0x01, 0x00, 0x00, 0x00, // Version
|
|
||||||
0x00, // Varint for number of input transactions
|
|
||||||
0x00, // Varint for number of output transactions
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time
|
|
||||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, // Sub Network ID
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Gas
|
|
||||||
0x03, // Payload length varint
|
|
||||||
0x01, 0x02, 0x03, // Payload / Gas limit
|
|
||||||
}
|
|
||||||
|
|
||||||
r = bytes.NewReader(registryWithWrongPayloadTxEncoded)
|
|
||||||
err = tx.Deserialize(r)
|
|
||||||
|
|
||||||
str = fmt.Sprintf("For registry sub network the payload should always be uint64 (8 bytes length)")
|
|
||||||
expectedErr = messageError("MsgTx.BtcDecode", str)
|
|
||||||
if err == nil || err.Error() != expectedErr.Error() {
|
|
||||||
t.Errorf("TestTxSerializeErrors: expected error %v but got %v", expectedErr, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestTxOverflowErrors performs tests to ensure deserializing transactions
|
// TestTxOverflowErrors performs tests to ensure deserializing transactions
|
||||||
|
Loading…
x
Reference in New Issue
Block a user