core: use raw stack items in application logs

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2020-07-31 15:48:35 +03:00
parent 9cba25616d
commit e5d538ed21
7 changed files with 41 additions and 78 deletions

View file

@ -591,7 +591,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
Trigger: trigger.System, Trigger: trigger.System,
VMState: v.State(), VMState: v.State(),
GasConsumed: v.GasConsumed(), GasConsumed: v.GasConsumed(),
Stack: v.Estack().ToContractParameters(), Stack: v.Estack().ToArray(),
Events: systemInterop.Notifications, Events: systemInterop.Notifications,
} }
appExecResults = append(appExecResults, aer) appExecResults = append(appExecResults, aer)
@ -632,7 +632,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
Trigger: trigger.Application, Trigger: trigger.Application,
VMState: v.State(), VMState: v.State(),
GasConsumed: v.GasConsumed(), GasConsumed: v.GasConsumed(),
Stack: v.Estack().ToContractParameters(), Stack: v.Estack().ToArray(),
Events: systemInterop.Notifications, Events: systemInterop.Notifications,
} }
appExecResults = append(appExecResults, aer) appExecResults = append(appExecResults, aer)

View file

@ -11,8 +11,8 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/internal/random" "github.com/nspcc-dev/neo-go/pkg/internal/random"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -103,7 +103,7 @@ func TestPutGetAppExecResult(t *testing.T) {
appExecResult := &state.AppExecResult{ appExecResult := &state.AppExecResult{
TxHash: hash, TxHash: hash,
Events: []state.NotificationEvent{}, Events: []state.NotificationEvent{},
Stack: []smartcontract.Parameter{}, Stack: []stackitem.Item{},
} }
err := dao.PutAppExecResult(appExecResult) err := dao.PutAppExecResult(appExecResult)
require.NoError(t, err) require.NoError(t, err)

View file

@ -131,8 +131,7 @@ func TestNativeContract_Invoke(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, vm.HaltState, res.VMState) require.Equal(t, vm.HaltState, res.VMState)
require.Equal(t, 1, len(res.Stack)) require.Equal(t, 1, len(res.Stack))
require.Equal(t, smartcontract.IntegerType, res.Stack[0].Type) require.Equal(t, big.NewInt(42), res.Stack[0].Value())
require.EqualValues(t, 42, res.Stack[0].Value)
res, err = chain.GetAppExecResult(tx2.Hash()) res, err = chain.GetAppExecResult(tx2.Hash())
require.NoError(t, err) require.NoError(t, err)

View file

@ -10,10 +10,10 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -29,20 +29,14 @@ func TestMaxTransactionsPerBlock(t *testing.T) {
t.Run("get, contract method", func(t *testing.T) { t.Run("get, contract method", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getMaxTransactionsPerBlock") res, err := invokeNativePolicyMethod(chain, "getMaxTransactionsPerBlock")
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBigInteger(big.NewInt(512)))
Type: smartcontract.IntegerType,
Value: 512,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
}) })
t.Run("set", func(t *testing.T) { t.Run("set", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "setMaxTransactionsPerBlock", bigint.ToBytes(big.NewInt(1024))) res, err := invokeNativePolicyMethod(chain, "setMaxTransactionsPerBlock", bigint.ToBytes(big.NewInt(1024)))
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(true))
Type: smartcontract.BoolType,
Value: true,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
n := chain.contracts.Policy.GetMaxTransactionsPerBlockInternal(chain.dao) n := chain.contracts.Policy.GetMaxTransactionsPerBlockInternal(chain.dao)
require.Equal(t, 1024, int(n)) require.Equal(t, 1024, int(n))
@ -56,27 +50,18 @@ func TestMaxBlockSize(t *testing.T) {
t.Run("get", func(t *testing.T) { t.Run("get", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getMaxBlockSize") res, err := invokeNativePolicyMethod(chain, "getMaxBlockSize")
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBigInteger(big.NewInt(1024*256)))
Type: smartcontract.IntegerType,
Value: 1024 * 256,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
}) })
t.Run("set", func(t *testing.T) { t.Run("set", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "setMaxBlockSize", bigint.ToBytes(big.NewInt(102400))) res, err := invokeNativePolicyMethod(chain, "setMaxBlockSize", bigint.ToBytes(big.NewInt(102400)))
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(true))
Type: smartcontract.BoolType,
Value: true,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
res, err = invokeNativePolicyMethod(chain, "getMaxBlockSize") res, err = invokeNativePolicyMethod(chain, "getMaxBlockSize")
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBigInteger(big.NewInt(102400)))
Type: smartcontract.IntegerType,
Value: 102400,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
}) })
} }
@ -93,20 +78,14 @@ func TestFeePerByte(t *testing.T) {
t.Run("get, contract method", func(t *testing.T) { t.Run("get, contract method", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getFeePerByte") res, err := invokeNativePolicyMethod(chain, "getFeePerByte")
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBigInteger(big.NewInt(1000)))
Type: smartcontract.IntegerType,
Value: 1000,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
}) })
t.Run("set", func(t *testing.T) { t.Run("set", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "setFeePerByte", bigint.ToBytes(big.NewInt(1024))) res, err := invokeNativePolicyMethod(chain, "setFeePerByte", bigint.ToBytes(big.NewInt(1024)))
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(true))
Type: smartcontract.BoolType,
Value: true,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
n := chain.contracts.Policy.GetFeePerByteInternal(chain.dao) n := chain.contracts.Policy.GetFeePerByteInternal(chain.dao)
require.Equal(t, 1024, int(n)) require.Equal(t, 1024, int(n))
@ -127,20 +106,14 @@ func TestBlockedAccounts(t *testing.T) {
t.Run("get, contract method", func(t *testing.T) { t.Run("get, contract method", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getBlockedAccounts") res, err := invokeNativePolicyMethod(chain, "getBlockedAccounts")
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewArray([]stackitem.Item{}))
Type: smartcontract.ArrayType,
Value: []smartcontract.Parameter{},
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
}) })
t.Run("block-unblock account", func(t *testing.T) { t.Run("block-unblock account", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE()) res, err := invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE())
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(true))
Type: smartcontract.BoolType,
Value: true,
})
accounts, err := chain.contracts.Policy.GetBlockedAccountsInternal(chain.dao) accounts, err := chain.contracts.Policy.GetBlockedAccountsInternal(chain.dao)
require.NoError(t, err) require.NoError(t, err)
@ -148,10 +121,7 @@ func TestBlockedAccounts(t *testing.T) {
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE()) res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE())
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(true))
Type: smartcontract.BoolType,
Value: true,
})
accounts, err = chain.contracts.Policy.GetBlockedAccountsInternal(chain.dao) accounts, err = chain.contracts.Policy.GetBlockedAccountsInternal(chain.dao)
require.NoError(t, err) require.NoError(t, err)
@ -163,35 +133,23 @@ func TestBlockedAccounts(t *testing.T) {
// block // block
res, err := invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE()) res, err := invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE())
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(true))
Type: smartcontract.BoolType,
Value: true,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
// double-block should fail // double-block should fail
res, err = invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE()) res, err = invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE())
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(false))
Type: smartcontract.BoolType,
Value: false,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
// unblock // unblock
res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE()) res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE())
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(true))
Type: smartcontract.BoolType,
Value: true,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
// unblock the same account should fail as we don't have it blocked // unblock the same account should fail as we don't have it blocked
res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE()) res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE())
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(false))
Type: smartcontract.BoolType,
Value: false,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
}) })
@ -205,10 +163,7 @@ func TestBlockedAccounts(t *testing.T) {
for _, acc := range accounts { for _, acc := range accounts {
res, err := invokeNativePolicyMethod(chain, "blockAccount", acc.BytesBE()) res, err := invokeNativePolicyMethod(chain, "blockAccount", acc.BytesBE())
require.NoError(t, err) require.NoError(t, err)
checkResult(t, res, smartcontract.Parameter{ checkResult(t, res, stackitem.NewBool(true))
Type: smartcontract.BoolType,
Value: true,
})
require.NoError(t, chain.persist()) require.NoError(t, chain.persist())
} }
@ -253,9 +208,8 @@ func invokeNativePolicyMethod(chain *Blockchain, method string, args ...interfac
return res, nil return res, nil
} }
func checkResult(t *testing.T, result *state.AppExecResult, expected smartcontract.Parameter) { func checkResult(t *testing.T, result *state.AppExecResult, expected stackitem.Item) {
require.Equal(t, vm.HaltState, result.VMState) require.Equal(t, vm.HaltState, result.VMState)
require.Equal(t, 1, len(result.Stack)) require.Equal(t, 1, len(result.Stack))
require.Equal(t, expected.Type, result.Stack[0].Type) require.Equal(t, expected, result.Stack[0])
require.EqualValues(t, expected.Value, result.Stack[0].Value)
} }

View file

@ -4,7 +4,6 @@ import (
"errors" "errors"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
@ -26,7 +25,7 @@ type AppExecResult struct {
Trigger trigger.Type Trigger trigger.Type
VMState vm.State VMState vm.State
GasConsumed int64 GasConsumed int64
Stack []smartcontract.Parameter Stack []stackitem.Item
Events []NotificationEvent Events []NotificationEvent
} }
@ -59,7 +58,7 @@ func (aer *AppExecResult) EncodeBinary(w *io.BinWriter) {
w.WriteB(byte(aer.Trigger)) w.WriteB(byte(aer.Trigger))
w.WriteB(byte(aer.VMState)) w.WriteB(byte(aer.VMState))
w.WriteU64LE(uint64(aer.GasConsumed)) w.WriteU64LE(uint64(aer.GasConsumed))
w.WriteArray(aer.Stack) stackitem.EncodeBinaryStackItem(stackitem.NewArray(aer.Stack), w)
w.WriteArray(aer.Events) w.WriteArray(aer.Events)
} }
@ -69,6 +68,14 @@ func (aer *AppExecResult) DecodeBinary(r *io.BinReader) {
aer.Trigger = trigger.Type(r.ReadB()) aer.Trigger = trigger.Type(r.ReadB())
aer.VMState = vm.State(r.ReadB()) aer.VMState = vm.State(r.ReadB())
aer.GasConsumed = int64(r.ReadU64LE()) aer.GasConsumed = int64(r.ReadU64LE())
r.ReadArray(&aer.Stack) item := stackitem.DecodeBinaryStackItem(r)
if r.Err == nil {
arr, ok := item.Value().([]stackitem.Item)
if !ok {
r.Err = errors.New("array expected")
return
}
aer.Stack = arr
}
r.ReadArray(&aer.Events) r.ReadArray(&aer.Events)
} }

View file

@ -5,7 +5,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/internal/random" "github.com/nspcc-dev/neo-go/pkg/internal/random"
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes" "github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
) )
@ -26,7 +25,7 @@ func TestEncodeDecodeAppExecResult(t *testing.T) {
Trigger: 1, Trigger: 1,
VMState: vm.HaltState, VMState: vm.HaltState,
GasConsumed: 10, GasConsumed: 10,
Stack: []smartcontract.Parameter{}, Stack: []stackitem.Item{},
Events: []NotificationEvent{}, Events: []NotificationEvent{},
} }

View file

@ -43,13 +43,17 @@ func NewApplicationLog(appExecRes *state.AppExecResult) ApplicationLog {
for _, e := range appExecRes.Events { for _, e := range appExecRes.Events {
events = append(events, StateEventToResultNotification(e)) events = append(events, StateEventToResultNotification(e))
} }
st := make([]smartcontract.Parameter, len(appExecRes.Stack))
seen := make(map[stackitem.Item]bool)
for i := range appExecRes.Stack {
st[i] = smartcontract.ParameterFromStackItem(appExecRes.Stack[i], seen)
}
return ApplicationLog{ return ApplicationLog{
TxHash: appExecRes.TxHash, TxHash: appExecRes.TxHash,
Trigger: appExecRes.Trigger.String(), Trigger: appExecRes.Trigger.String(),
VMState: appExecRes.VMState.String(), VMState: appExecRes.VMState.String(),
GasConsumed: appExecRes.GasConsumed, GasConsumed: appExecRes.GasConsumed,
Stack: appExecRes.Stack, Stack: st,
Events: events, Events: events,
} }
} }