forked from TrueCloudLab/neoneo-go
core: add getTransactionSigners method to native Ledger
This commit is contained in:
parent
35d930951c
commit
47d52bd9c5
6 changed files with 237 additions and 17 deletions
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
|
@ -63,6 +64,11 @@ func newLedger() *Ledger {
|
|||
md = newMethodAndPrice(l.getTransactionFromBlock, 1<<16, callflag.ReadStates)
|
||||
l.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("getTransactionSigners", smartcontract.ArrayType,
|
||||
manifest.NewParameter("hash", smartcontract.Hash256Type))
|
||||
md = newMethodAndPrice(l.getTransactionSigners, 1<<15, callflag.ReadStates)
|
||||
l.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("getTransactionVMState", smartcontract.IntegerType,
|
||||
manifest.NewParameter("hash", smartcontract.Hash256Type))
|
||||
md = newMethodAndPrice(l.getTransactionVMState, 1<<15, callflag.ReadStates)
|
||||
|
@ -148,6 +154,15 @@ func (l *Ledger) getTransactionFromBlock(ic *interop.Context, params []stackitem
|
|||
return TransactionToStackItem(block.Transactions[index])
|
||||
}
|
||||
|
||||
// getTransactionSigners returns transaction signers to the SC.
|
||||
func (l *Ledger) getTransactionSigners(ic *interop.Context, params []stackitem.Item) stackitem.Item {
|
||||
tx, h, err := getTransactionAndHeight(ic.DAO, params[0])
|
||||
if err != nil || !isTraceableBlock(ic.Chain, h) {
|
||||
return stackitem.Null{}
|
||||
}
|
||||
return SignersToStackItem(tx.Signers)
|
||||
}
|
||||
|
||||
// getTransactionVMState returns VM state got after transaction invocation.
|
||||
func (l *Ledger) getTransactionVMState(ic *interop.Context, params []stackitem.Item) stackitem.Item {
|
||||
hash, err := getUint256FromItem(params[0])
|
||||
|
@ -242,3 +257,37 @@ func TransactionToStackItem(t *transaction.Transaction) stackitem.Item {
|
|||
stackitem.NewByteArray(t.Script),
|
||||
})
|
||||
}
|
||||
|
||||
// SignersToStackItem converts transaction.Signers to stackitem.Item.
|
||||
func SignersToStackItem(signers []transaction.Signer) stackitem.Item {
|
||||
res := make([]stackitem.Item, len(signers))
|
||||
bw := io.NewBufBinWriter()
|
||||
for i, s := range signers {
|
||||
s.EncodeBinary(bw.BinWriter)
|
||||
if bw.Err != nil {
|
||||
panic(fmt.Errorf("failed to serialize signer %d to stackitem: %w", i, bw.Err))
|
||||
}
|
||||
contracts := make([]stackitem.Item, len(s.AllowedContracts))
|
||||
for j, c := range s.AllowedContracts {
|
||||
contracts[j] = stackitem.NewByteArray(c.BytesBE())
|
||||
}
|
||||
groups := make([]stackitem.Item, len(s.AllowedGroups))
|
||||
for j, g := range s.AllowedGroups {
|
||||
groups[j] = stackitem.NewByteArray(g.Bytes())
|
||||
}
|
||||
rules := make([]stackitem.Item, len(s.Rules))
|
||||
for j, r := range s.Rules {
|
||||
rules[j] = r.ToStackItem()
|
||||
}
|
||||
res[i] = stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray(bw.Bytes()),
|
||||
stackitem.NewByteArray(s.Account.BytesBE()),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(s.Scopes))),
|
||||
stackitem.NewArray(contracts),
|
||||
stackitem.NewArray(groups),
|
||||
stackitem.NewArray(rules),
|
||||
})
|
||||
bw.Reset()
|
||||
}
|
||||
return stackitem.NewArray(res)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -172,3 +174,38 @@ func TestLedger_GetBlock(t *testing.T) {
|
|||
ledgerInvoker.Invoke(t, stackitem.Null{}, "getBlock", b.Hash())
|
||||
})
|
||||
}
|
||||
|
||||
func TestLedger_GetTransactionSigners(t *testing.T) {
|
||||
c := newLedgerClient(t)
|
||||
e := c.Executor
|
||||
ledgerInvoker := c.WithSigners(c.Committee)
|
||||
|
||||
txHash := ledgerInvoker.Invoke(t, e.Chain.BlockHeight(), "currentIndex")
|
||||
|
||||
t.Run("good", func(t *testing.T) {
|
||||
s := &transaction.Signer{
|
||||
Account: c.CommitteeHash,
|
||||
Scopes: transaction.Global,
|
||||
}
|
||||
bw := io.NewBufBinWriter()
|
||||
s.EncodeBinary(bw.BinWriter)
|
||||
require.NoError(t, bw.Err)
|
||||
expected := stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray(bw.Bytes()),
|
||||
stackitem.NewByteArray(s.Account.BytesBE()),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(s.Scopes))),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
}),
|
||||
})
|
||||
ledgerInvoker.Invoke(t, expected, "getTransactionSigners", txHash)
|
||||
})
|
||||
t.Run("unknown transaction", func(t *testing.T) {
|
||||
ledgerInvoker.Invoke(t, stackitem.Null{}, "getTransactionSigners", util.Uint256{1, 2, 3})
|
||||
})
|
||||
t.Run("not a hash", func(t *testing.T) {
|
||||
ledgerInvoker.InvokeFail(t, "expected []byte of size 32", "getTransactionSigners", []byte{1, 2, 3})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@ package transaction
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=WitnessConditionType -linecomment
|
||||
|
@ -50,6 +52,8 @@ type WitnessCondition interface {
|
|||
// DecodeBinarySpecific decodes type-specific binary data from the given
|
||||
// reader (not including type data).
|
||||
DecodeBinarySpecific(*io.BinReader, int)
|
||||
// ToStackItem converts WitnessCondition to stackitem.Item.
|
||||
ToStackItem() stackitem.Item
|
||||
|
||||
json.Marshaler
|
||||
}
|
||||
|
@ -129,6 +133,12 @@ func (c *ConditionBoolean) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionBoolean) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), bool(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionNot) Type() WitnessConditionType {
|
||||
return WitnessNot
|
||||
|
@ -166,6 +176,12 @@ func (c *ConditionNot) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionNot) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), c.Condition)
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionAnd) Type() WitnessConditionType {
|
||||
return WitnessAnd
|
||||
|
@ -242,6 +258,12 @@ func (c *ConditionAnd) MarshalJSON() ([]byte, error) {
|
|||
return arrayToJSON(c, []WitnessCondition(*c))
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionAnd) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), []WitnessCondition(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionOr) Type() WitnessConditionType {
|
||||
return WitnessOr
|
||||
|
@ -282,6 +304,12 @@ func (c *ConditionOr) MarshalJSON() ([]byte, error) {
|
|||
return arrayToJSON(c, []WitnessCondition(*c))
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionOr) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), []WitnessCondition(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionScriptHash) Type() WitnessConditionType {
|
||||
return WitnessScriptHash
|
||||
|
@ -314,6 +342,12 @@ func (c *ConditionScriptHash) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionScriptHash) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), util.Uint160(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionGroup) Type() WitnessConditionType {
|
||||
return WitnessGroup
|
||||
|
@ -346,6 +380,12 @@ func (c *ConditionGroup) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionGroup) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), keys.PublicKey(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c ConditionCalledByEntry) Type() WitnessConditionType {
|
||||
return WitnessCalledByEntry
|
||||
|
@ -376,6 +416,12 @@ func (c ConditionCalledByEntry) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c ConditionCalledByEntry) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), nil)
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionCalledByContract) Type() WitnessConditionType {
|
||||
return WitnessCalledByContract
|
||||
|
@ -408,6 +454,12 @@ func (c *ConditionCalledByContract) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionCalledByContract) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), util.Uint160(*c))
|
||||
}
|
||||
|
||||
// Type implements WitnessCondition interface and returns condition type.
|
||||
func (c *ConditionCalledByGroup) Type() WitnessConditionType {
|
||||
return WitnessCalledByGroup
|
||||
|
@ -440,6 +492,12 @@ func (c *ConditionCalledByGroup) MarshalJSON() ([]byte, error) {
|
|||
return json.Marshal(aux)
|
||||
}
|
||||
|
||||
// ToStackItem implements WitnessCondition interface allowing to convert
|
||||
// to stackitem.Item.
|
||||
func (c *ConditionCalledByGroup) ToStackItem() stackitem.Item {
|
||||
return condToStackItem(c.Type(), keys.PublicKey(*c))
|
||||
}
|
||||
|
||||
// DecodeBinaryCondition decodes and returns condition from the given binary stream.
|
||||
func DecodeBinaryCondition(r *io.BinReader) WitnessCondition {
|
||||
return decodeBinaryCondition(r, MaxConditionNesting)
|
||||
|
@ -573,3 +631,29 @@ func unmarshalConditionJSON(data []byte, maxDepth int) (WitnessCondition, error)
|
|||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func condToStackItem(typ WitnessConditionType, c interface{}) stackitem.Item {
|
||||
res := make([]stackitem.Item, 0, 2)
|
||||
res = append(res, stackitem.NewBigInteger(big.NewInt(int64(typ))))
|
||||
switch typ {
|
||||
case WitnessBoolean:
|
||||
res = append(res, stackitem.NewBool(c.(bool)))
|
||||
case WitnessNot:
|
||||
res = append(res, c.(WitnessCondition).ToStackItem())
|
||||
case WitnessAnd, WitnessOr:
|
||||
v := c.([]WitnessCondition)
|
||||
operands := make([]stackitem.Item, len(v))
|
||||
for i, op := range v {
|
||||
operands[i] = op.ToStackItem()
|
||||
}
|
||||
res = append(res, stackitem.NewArray(operands))
|
||||
case WitnessScriptHash, WitnessCalledByContract:
|
||||
res = append(res, stackitem.NewByteArray(c.(util.Uint160).BytesBE()))
|
||||
case WitnessGroup, WitnessCalledByGroup:
|
||||
g := c.(keys.PublicKey)
|
||||
res = append(res, stackitem.NewByteArray((&g).Bytes()))
|
||||
case WitnessCalledByEntry:
|
||||
// No additional item should be added.
|
||||
}
|
||||
return stackitem.NewArray(res)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -30,10 +32,14 @@ func (c InvalidCondition) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
return json.Marshal(aux)
|
||||
}
|
||||
func (c InvalidCondition) ToStackItem() stackitem.Item {
|
||||
panic("invalid")
|
||||
}
|
||||
|
||||
type condCase struct {
|
||||
condition WitnessCondition
|
||||
success bool
|
||||
condition WitnessCondition
|
||||
success bool
|
||||
expectedStackItem []stackitem.Item
|
||||
}
|
||||
|
||||
func TestWitnessConditionSerDes(t *testing.T) {
|
||||
|
@ -41,19 +47,25 @@ func TestWitnessConditionSerDes(t *testing.T) {
|
|||
pk, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
var cases = []condCase{
|
||||
{(*ConditionBoolean)(&someBool), true},
|
||||
{&ConditionNot{(*ConditionBoolean)(&someBool)}, true},
|
||||
{&ConditionAnd{(*ConditionBoolean)(&someBool), (*ConditionBoolean)(&someBool)}, true},
|
||||
{&ConditionOr{(*ConditionBoolean)(&someBool), (*ConditionBoolean)(&someBool)}, true},
|
||||
{&ConditionScriptHash{1, 2, 3}, true},
|
||||
{(*ConditionGroup)(pk.PublicKey()), true},
|
||||
{ConditionCalledByEntry{}, true},
|
||||
{&ConditionCalledByContract{1, 2, 3}, true},
|
||||
{(*ConditionCalledByGroup)(pk.PublicKey()), true},
|
||||
{InvalidCondition{}, false},
|
||||
{&ConditionAnd{}, false},
|
||||
{&ConditionOr{}, false},
|
||||
{&ConditionNot{&ConditionNot{&ConditionNot{(*ConditionBoolean)(&someBool)}}}, false},
|
||||
{(*ConditionBoolean)(&someBool), true, []stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}},
|
||||
{&ConditionNot{(*ConditionBoolean)(&someBool)}, true, []stackitem.Item{stackitem.Make(WitnessNot), stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)})}},
|
||||
{&ConditionAnd{(*ConditionBoolean)(&someBool), (*ConditionBoolean)(&someBool)}, true, []stackitem.Item{stackitem.Make(WitnessAnd), stackitem.Make([]stackitem.Item{
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}),
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}),
|
||||
})}},
|
||||
{&ConditionOr{(*ConditionBoolean)(&someBool), (*ConditionBoolean)(&someBool)}, true, []stackitem.Item{stackitem.Make(WitnessOr), stackitem.Make([]stackitem.Item{
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}),
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Make(WitnessBoolean), stackitem.Make(someBool)}),
|
||||
})}},
|
||||
{&ConditionScriptHash{1, 2, 3}, true, []stackitem.Item{stackitem.Make(WitnessScriptHash), stackitem.Make(util.Uint160{1, 2, 3}.BytesBE())}},
|
||||
{(*ConditionGroup)(pk.PublicKey()), true, []stackitem.Item{stackitem.Make(WitnessGroup), stackitem.Make(pk.PublicKey().Bytes())}},
|
||||
{ConditionCalledByEntry{}, true, []stackitem.Item{stackitem.Make(WitnessCalledByEntry)}},
|
||||
{&ConditionCalledByContract{1, 2, 3}, true, []stackitem.Item{stackitem.Make(WitnessCalledByContract), stackitem.Make(util.Uint160{1, 2, 3}.BytesBE())}},
|
||||
{(*ConditionCalledByGroup)(pk.PublicKey()), true, []stackitem.Item{stackitem.Make(WitnessCalledByGroup), stackitem.Make(pk.PublicKey().Bytes())}},
|
||||
{InvalidCondition{}, false, nil},
|
||||
{&ConditionAnd{}, false, nil},
|
||||
{&ConditionOr{}, false, nil},
|
||||
{&ConditionNot{&ConditionNot{&ConditionNot{(*ConditionBoolean)(&someBool)}}}, false, nil},
|
||||
}
|
||||
var maxSubCondAnd = &ConditionAnd{}
|
||||
var maxSubCondOr = &ConditionAnd{}
|
||||
|
@ -61,8 +73,8 @@ func TestWitnessConditionSerDes(t *testing.T) {
|
|||
*maxSubCondAnd = append(*maxSubCondAnd, (*ConditionBoolean)(&someBool))
|
||||
*maxSubCondOr = append(*maxSubCondOr, (*ConditionBoolean)(&someBool))
|
||||
}
|
||||
cases = append(cases, condCase{maxSubCondAnd, false})
|
||||
cases = append(cases, condCase{maxSubCondOr, false})
|
||||
cases = append(cases, condCase{maxSubCondAnd, false, nil})
|
||||
cases = append(cases, condCase{maxSubCondOr, false, nil})
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
for i, c := range cases {
|
||||
w := io.NewBufBinWriter()
|
||||
|
@ -94,6 +106,15 @@ func TestWitnessConditionSerDes(t *testing.T) {
|
|||
require.Equal(t, c.condition, res)
|
||||
}
|
||||
})
|
||||
t.Run("stackitem", func(t *testing.T) {
|
||||
for i, c := range cases[1:] {
|
||||
if c.expectedStackItem != nil {
|
||||
expected := stackitem.NewArray(c.expectedStackItem)
|
||||
actual := c.condition.ToStackItem()
|
||||
assert.Equal(t, expected, actual, i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestWitnessConditionZeroDeser(t *testing.T) {
|
||||
|
|
|
@ -3,8 +3,10 @@ package transaction
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=WitnessAction -linecomment
|
||||
|
@ -84,3 +86,11 @@ func (w *WitnessRule) UnmarshalJSON(data []byte) error {
|
|||
w.Condition = cond
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToStackItem implements Convertible interface.
|
||||
func (w *WitnessRule) ToStackItem() stackitem.Item {
|
||||
return stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewBigInteger(big.NewInt(int64(w.Action))),
|
||||
w.Condition.ToStackItem(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -54,3 +55,21 @@ func TestWitnessRuleBadJSON(t *testing.T) {
|
|||
require.Errorf(t, err, "case %d, json %s", i, cases[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestWitnessRule_ToStackItem(t *testing.T) {
|
||||
var b bool
|
||||
for _, act := range []WitnessAction{WitnessDeny, WitnessAllow} {
|
||||
expected := stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.Make(int64(act)),
|
||||
stackitem.Make([]stackitem.Item{
|
||||
stackitem.Make(WitnessBoolean),
|
||||
stackitem.Make(b),
|
||||
}),
|
||||
})
|
||||
actual := (&WitnessRule{
|
||||
Action: act,
|
||||
Condition: (*ConditionBoolean)(&b),
|
||||
}).ToStackItem()
|
||||
require.Equal(t, expected, actual, act)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue