From 665a49d0a097ed9fc811023075a60cceb83b6b01 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 9 Jun 2020 13:18:32 +0300 Subject: [PATCH] core: update System.Blockchain.GetBlock interop closes #1025 Now we put on stack stackitem.Array instead of Interop, so we're able to use all available block properties without extra interop getters. Removed Neo.Blockchain.GetBlock interop as we don't need it anymore. --- pkg/compiler/codegen.go | 2 +- pkg/compiler/syscall.go | 2 +- pkg/core/block/block.go | 17 ++++++++++++++ pkg/core/interop_system.go | 6 ++--- pkg/core/interops.go | 3 +-- pkg/interop/blockchain/blockchain.go | 35 ++++++++++++++++++++++++---- 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 584a3b036b..b157825689 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -1052,7 +1052,7 @@ func (c *codegen) convertSyscall(expr *ast.CallExpr, api, name string) { } emit.Syscall(c.prog.BinWriter, api) switch name { - case "GetTransaction", "GetTransactionFromBlock": + case "GetTransaction", "GetTransactionFromBlock", "GetBlock": c.emitConvert(stackitem.StructT) } diff --git a/pkg/compiler/syscall.go b/pkg/compiler/syscall.go index 0c4135b59f..0ea6e11580 100644 --- a/pkg/compiler/syscall.go +++ b/pkg/compiler/syscall.go @@ -36,7 +36,7 @@ var syscalls = map[string]map[string]string{ }, "blockchain": { "GetAccount": "Neo.Blockchain.GetAccount", - "GetBlock": "Neo.Blockchain.GetBlock", + "GetBlock": "System.Blockchain.GetBlock", "GetContract": "Neo.Blockchain.GetContract", "GetHeader": "Neo.Blockchain.GetHeader", "GetHeight": "Neo.Blockchain.GetHeight", diff --git a/pkg/core/block/block.go b/pkg/core/block/block.go index 54d88fa316..7f2a1e8c96 100644 --- a/pkg/core/block/block.go +++ b/pkg/core/block/block.go @@ -3,12 +3,14 @@ package block import ( "encoding/json" "errors" + "math/big" "github.com/Workiva/go-datastructures/queue" "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" ) // Block represents one block in the chain. @@ -235,3 +237,18 @@ func (b *Block) UnmarshalJSON(data []byte) error { _ = b.ConsensusData.Hash() return nil } + +// ToStackItem converts Block to stackitem.Array +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(big.NewInt(int64(b.Index))), + stackitem.NewByteArray(b.NextConsensus.BytesBE()), + stackitem.NewBigInteger(big.NewInt(int64(len(b.Transactions)))), + }) + +} diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index 28d4c07909..ff436ca157 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -59,10 +59,10 @@ func bcGetBlock(ic *interop.Context, v *vm.VM) error { return err } block, err := ic.Chain.GetBlock(hash) - if err != nil { - v.Estack().PushVal([]byte{}) + if err != nil || !isTraceableBlock(ic, block.Index) { + v.Estack().PushVal(stackitem.Null{}) } else { - v.Estack().PushVal(stackitem.NewInterop(block)) + v.Estack().PushVal(block.ToStackItem()) } return nil } diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 068534d19f..97bc2a6afd 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -64,7 +64,7 @@ func getInteropFromSlice(ic *interop.Context, slice []interop.Function) func(uin var systemInterops = []interop.Function{ {Name: "System.Block.GetTransactionCount", Func: blockGetTransactionCount, Price: 1}, {Name: "System.Block.GetTransactions", Func: blockGetTransactions, Price: 1}, - {Name: "System.Blockchain.GetBlock", Func: bcGetBlock, Price: 200}, + {Name: "System.Blockchain.GetBlock", Func: bcGetBlock, Price: 250}, {Name: "System.Blockchain.GetContract", Func: bcGetContract, Price: 100}, {Name: "System.Blockchain.GetHeader", Func: bcGetHeader, Price: 100}, {Name: "System.Blockchain.GetHeight", Func: bcGetHeight, Price: 1}, @@ -107,7 +107,6 @@ var neoInterops = []interop.Function{ {Name: "Neo.Block.GetTransactionCount", Func: blockGetTransactionCount, Price: 1}, {Name: "Neo.Block.GetTransactions", Func: blockGetTransactions, Price: 1}, {Name: "Neo.Blockchain.GetAccount", Func: bcGetAccount, Price: 100}, - {Name: "Neo.Blockchain.GetBlock", Func: bcGetBlock, Price: 200}, {Name: "Neo.Blockchain.GetContract", Func: bcGetContract, Price: 100}, {Name: "Neo.Blockchain.GetHeader", Func: bcGetHeader, Price: 100}, {Name: "Neo.Blockchain.GetHeight", Func: bcGetHeight, Price: 1}, diff --git a/pkg/interop/blockchain/blockchain.go b/pkg/interop/blockchain/blockchain.go index 04452f6da0..9ff76eb4b4 100644 --- a/pkg/interop/blockchain/blockchain.go +++ b/pkg/interop/blockchain/blockchain.go @@ -5,7 +5,6 @@ package blockchain import ( "github.com/nspcc-dev/neo-go/pkg/interop/account" - "github.com/nspcc-dev/neo-go/pkg/interop/block" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/header" ) @@ -35,6 +34,32 @@ type Transaction struct { Scrypt []byte } +// Block represents a NEO block, it's an opaque data structure that you can get +// block-related data from. It's similar to the Block class in the Neo .net +// framework. To use it you need to get it via GetBlock function call. +type Block struct { + // Hash represents the hash (256 bit BE value in a 32 byte slice) of the + // given block. + Hash []byte + // Version of the block. + Version int + // PrevHash represents the hash (256 bit BE value in a 32 byte slice) of the + // previous block. + PrevHash []byte + // MerkleRoot represents the root hash (256 bit BE value in a 32 byte slice) + // of a transaction list. + MerkleRoot []byte + // Timestamp represents millisecond-precision block timestamp. + Timestamp int + // Index represents the height of the block. + Index int + // NextConsensus representes contract address of the next miner (160 bit BE + // value in a 20 byte slice). + NextConsensus []byte + // TransactionsLength represents the length of block's transactions array. + TransactionsLength int +} + // GetHeight returns current block height (index of the last accepted block). // Note that when transaction is being run as a part of new block this block is // considered as not yet accepted (persisted) and thus you'll get an index of @@ -53,10 +78,10 @@ func GetHeader(heightOrHash interface{}) header.Header { } // GetBlock returns block found by the given hash or index (with the same -// encoding as for GetHeader). Refer to the `block` package for possible uses -// of returned structure. This function uses `Neo.Blockchain.GetBlock` syscall. -func GetBlock(heightOrHash interface{}) block.Block { - return block.Block{} +// encoding as for GetHeader). This function uses `System.Blockchain.GetBlock` +// syscall. +func GetBlock(heightOrHash interface{}) Block { + return Block{} } // GetTransaction returns transaction found by the given (256 bit in BE format