From d70caf1da12f35dad549b239bec4bb650a16f609 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 8 Jun 2022 18:12:41 +0300 Subject: [PATCH] core: move GetScriptContainer to runtime It also brings ToStackItem to Block and Transaction, previously this was avoided to separate block and transaction packages from VM. But turns out `transaction` depends on `stackitem` already, so this makes little sense (but can be shuffled in another way if needed). Context.Container is still a hash.Hashable because we have a number of occasions (header or MPT root verification) where there is no ToStackItem implementation possible. Maybe they can go with `nil` Container, but I don't want to have this risk for now. --- pkg/core/block/block.go | 17 ++++++++++++++ pkg/core/interop/runtime/engine.go | 15 ++++++++++++ pkg/core/interop_system.go | 19 --------------- pkg/core/interops.go | 2 +- pkg/core/native/ledger.go | 36 +++-------------------------- pkg/core/transaction/transaction.go | 16 +++++++++++++ 6 files changed, 52 insertions(+), 53 deletions(-) diff --git a/pkg/core/block/block.go b/pkg/core/block/block.go index c9c50c70f..bdf3e0e57 100644 --- a/pkg/core/block/block.go +++ b/pkg/core/block/block.go @@ -4,11 +4,13 @@ import ( "encoding/json" "errors" "math" + "math/big" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "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" ) const ( @@ -211,3 +213,18 @@ func (b *Block) GetExpectedBlockSizeWithoutTransactions(txCount int) int { } return size } + +// ToStackItem converts Block to stackitem.Item. +func (b *Block) ToStackItem() stackitem.Item { + return stackitem.NewArray([]stackitem.Item{ + stackitem.NewByteArray(b.Hash().BytesBE()), + stackitem.NewBigInteger(big.NewInt(int64(b.Version))), + stackitem.NewByteArray(b.PrevHash.BytesBE()), + stackitem.NewByteArray(b.MerkleRoot.BytesBE()), + stackitem.NewBigInteger(big.NewInt(int64(b.Timestamp))), + stackitem.NewBigInteger(new(big.Int).SetUint64(b.Nonce)), + stackitem.NewBigInteger(big.NewInt(int64(b.Index))), + stackitem.NewByteArray(b.NextConsensus.BytesBE()), + stackitem.NewBigInteger(big.NewInt(int64(len(b.Transactions)))), + }) +} diff --git a/pkg/core/interop/runtime/engine.go b/pkg/core/interop/runtime/engine.go index ee7de946b..1223d878a 100644 --- a/pkg/core/interop/runtime/engine.go +++ b/pkg/core/interop/runtime/engine.go @@ -10,6 +10,10 @@ import ( "go.uber.org/zap" ) +type itemable interface { + ToStackItem() stackitem.Item +} + const ( // MaxEventNameLen is the maximum length of a name for event. MaxEventNameLen = 32 @@ -37,6 +41,17 @@ func GetEntryScriptHash(ic *interop.Context) error { return ic.VM.PushContextScriptHash(ic.VM.Istack().Len() - 1) } +// GetScriptContainer returns transaction or block that contains the script +// being run. +func GetScriptContainer(ic *interop.Context) error { + c, ok := ic.Container.(itemable) + if !ok { + return errors.New("unknown script container") + } + ic.VM.Estack().PushItem(c.ToStackItem()) + return nil +} + // Platform returns the name of the platform. func Platform(ic *interop.Context) error { ic.VM.Estack().PushItem(stackitem.NewByteArray([]byte("NEO"))) diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index c7c9731a2..b483fb16b 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -5,12 +5,9 @@ import ( "errors" "fmt" - "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/interop" istorage "github.com/nspcc-dev/neo-go/pkg/core/interop/storage" - "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/storage" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -26,22 +23,6 @@ type StorageContext struct { ReadOnly bool } -// engineGetScriptContainer returns transaction or block that contains the script -// being run. -func engineGetScriptContainer(ic *interop.Context) error { - var item stackitem.Item - switch t := ic.Container.(type) { - case *transaction.Transaction: - item = native.TransactionToStackItem(t) - case *block.Block: - item = native.BlockToStackItem(t) - default: - return errors.New("unknown script container") - } - ic.VM.Estack().PushItem(item) - return nil -} - // storageDelete deletes stored key-value pair. func storageDelete(ic *interop.Context) error { stcInterface := ic.VM.Estack().Pop().Value() diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 7de730dff..50c8ee723 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -54,7 +54,7 @@ var systemInterops = []interop.Function{ {Name: interopnames.SystemRuntimeGetNetwork, Func: runtime.GetNetwork, Price: 1 << 3}, {Name: interopnames.SystemRuntimeGetNotifications, Func: runtime.GetNotifications, Price: 1 << 12, ParamCount: 1}, {Name: interopnames.SystemRuntimeGetRandom, Func: runtime.GetRandom, Price: 0}, - {Name: interopnames.SystemRuntimeGetScriptContainer, Func: engineGetScriptContainer, Price: 1 << 3}, + {Name: interopnames.SystemRuntimeGetScriptContainer, Func: runtime.GetScriptContainer, Price: 1 << 3}, {Name: interopnames.SystemRuntimeGetTime, Func: runtime.GetTime, Price: 1 << 3, RequiredFlags: callflag.ReadStates}, {Name: interopnames.SystemRuntimeGetTrigger, Func: runtime.GetTrigger, Price: 1 << 3}, {Name: interopnames.SystemRuntimeLog, Func: runtime.Log, Price: 1 << 15, RequiredFlags: callflag.AllowNotify, diff --git a/pkg/core/native/ledger.go b/pkg/core/native/ledger.go index c3962c311..e75f476eb 100644 --- a/pkg/core/native/ledger.go +++ b/pkg/core/native/ledger.go @@ -5,7 +5,6 @@ import ( "math" "math/big" - "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" @@ -117,7 +116,7 @@ func (l *Ledger) getBlock(ic *interop.Context, params []stackitem.Item) stackite if err != nil || !isTraceableBlock(ic, block.Index) { return stackitem.Null{} } - return BlockToStackItem(block) + return block.ToStackItem() } // getTransaction returns transaction to the SC. @@ -126,7 +125,7 @@ func (l *Ledger) getTransaction(ic *interop.Context, params []stackitem.Item) st if err != nil || !isTraceableBlock(ic, h) { return stackitem.Null{} } - return TransactionToStackItem(tx) + return tx.ToStackItem() } // getTransactionHeight returns transaction height to the SC. @@ -150,7 +149,7 @@ func (l *Ledger) getTransactionFromBlock(ic *interop.Context, params []stackitem if index >= uint32(len(block.Transactions)) { panic("wrong transaction index") } - return TransactionToStackItem(block.Transactions[index]) + return block.Transactions[index].ToStackItem() } // getTransactionSigners returns transaction signers to the SC. @@ -228,35 +227,6 @@ func getTransactionAndHeight(d *dao.Simple, item stackitem.Item) (*transaction.T return d.GetTransaction(hash) } -// BlockToStackItem converts block.Block to stackitem.Item. -func BlockToStackItem(b *block.Block) stackitem.Item { - return stackitem.NewArray([]stackitem.Item{ - stackitem.NewByteArray(b.Hash().BytesBE()), - stackitem.NewBigInteger(big.NewInt(int64(b.Version))), - stackitem.NewByteArray(b.PrevHash.BytesBE()), - stackitem.NewByteArray(b.MerkleRoot.BytesBE()), - stackitem.NewBigInteger(big.NewInt(int64(b.Timestamp))), - stackitem.NewBigInteger(new(big.Int).SetUint64(b.Nonce)), - stackitem.NewBigInteger(big.NewInt(int64(b.Index))), - stackitem.NewByteArray(b.NextConsensus.BytesBE()), - stackitem.NewBigInteger(big.NewInt(int64(len(b.Transactions)))), - }) -} - -// TransactionToStackItem converts transaction.Transaction to stackitem.Item. -func TransactionToStackItem(t *transaction.Transaction) stackitem.Item { - return stackitem.NewArray([]stackitem.Item{ - stackitem.NewByteArray(t.Hash().BytesBE()), - stackitem.NewBigInteger(big.NewInt(int64(t.Version))), - stackitem.NewBigInteger(big.NewInt(int64(t.Nonce))), - stackitem.NewByteArray(t.Sender().BytesBE()), - stackitem.NewBigInteger(big.NewInt(int64(t.SystemFee))), - stackitem.NewBigInteger(big.NewInt(int64(t.NetworkFee))), - stackitem.NewBigInteger(big.NewInt(int64(t.ValidUntilBlock))), - stackitem.NewByteArray(t.Script), - }) -} - // SignersToStackItem converts transaction.Signers to stackitem.Item. func SignersToStackItem(signers []transaction.Signer) stackitem.Item { res := make([]stackitem.Item, len(signers)) diff --git a/pkg/core/transaction/transaction.go b/pkg/core/transaction/transaction.go index eea2807ea..57047f8fe 100644 --- a/pkg/core/transaction/transaction.go +++ b/pkg/core/transaction/transaction.go @@ -6,12 +6,14 @@ import ( "errors" "fmt" "math" + "math/big" "math/rand" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "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" ) const ( @@ -451,3 +453,17 @@ func (t *Transaction) HasSigner(hash util.Uint160) bool { } return false } + +// ToStackItem converts Transaction to stackitem.Item. +func (t *Transaction) ToStackItem() stackitem.Item { + return stackitem.NewArray([]stackitem.Item{ + stackitem.NewByteArray(t.Hash().BytesBE()), + stackitem.NewBigInteger(big.NewInt(int64(t.Version))), + stackitem.NewBigInteger(big.NewInt(int64(t.Nonce))), + stackitem.NewByteArray(t.Sender().BytesBE()), + stackitem.NewBigInteger(big.NewInt(int64(t.SystemFee))), + stackitem.NewBigInteger(big.NewInt(int64(t.NetworkFee))), + stackitem.NewBigInteger(big.NewInt(int64(t.ValidUntilBlock))), + stackitem.NewByteArray(t.Script), + }) +}