From 7d46404e2db9aa0a836bf9f55a18cb29e9252b7c Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 26 Feb 2020 16:44:54 +0300 Subject: [PATCH] smartcontract: turn trigger types into Type 1) Turn trigger types from byte constants into Type 2) Add auto-generated stringer for future purposes --- pkg/core/blockchain.go | 2 +- pkg/core/interops.go | 5 ++- pkg/core/state/notification_event.go | 7 +-- pkg/smartcontract/trigger/trigger_type.go | 15 ++++--- .../trigger/trigger_type_string.go | 37 ++++++++++++++++ .../trigger/trigger_type_test.go | 43 +++++++++++++++++++ 6 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 pkg/smartcontract/trigger/trigger_type_string.go create mode 100644 pkg/smartcontract/trigger/trigger_type_test.go diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index a75021378..9d2ee4f8a 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1688,6 +1688,6 @@ func (bc *Blockchain) secondsPerBlock() int { return bc.config.SecondsPerBlock } -func (bc *Blockchain) newInteropContext(trigger byte, s storage.Store, block *block.Block, tx *transaction.Transaction) *interopContext { +func (bc *Blockchain) newInteropContext(trigger trigger.Type, s storage.Store, block *block.Block, tx *transaction.Transaction) *interopContext { return newInteropContext(trigger, bc, s, block, tx, bc.log) } diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 15ee9b994..8ec6e7a66 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -14,13 +14,14 @@ import ( "github.com/CityOfZion/neo-go/pkg/core/state" "github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/transaction" + "github.com/CityOfZion/neo-go/pkg/smartcontract/trigger" "github.com/CityOfZion/neo-go/pkg/vm" "go.uber.org/zap" ) type interopContext struct { bc Blockchainer - trigger byte + trigger trigger.Type block *block.Block tx *transaction.Transaction dao *cachedDao @@ -28,7 +29,7 @@ type interopContext struct { log *zap.Logger } -func newInteropContext(trigger byte, bc Blockchainer, s storage.Store, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *interopContext { +func newInteropContext(trigger trigger.Type, bc Blockchainer, s storage.Store, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *interopContext { dao := newCachedDao(s) nes := make([]state.NotificationEvent, 0) return &interopContext{bc, trigger, block, tx, dao, nes, log} diff --git a/pkg/core/state/notification_event.go b/pkg/core/state/notification_event.go index b0ea8973e..8da4a7d58 100644 --- a/pkg/core/state/notification_event.go +++ b/pkg/core/state/notification_event.go @@ -2,6 +2,7 @@ package state import ( "github.com/CityOfZion/neo-go/pkg/io" + "github.com/CityOfZion/neo-go/pkg/smartcontract/trigger" "github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/vm" ) @@ -17,7 +18,7 @@ type NotificationEvent struct { // all resulting notifications, state, stack and other metadata. type AppExecResult struct { TxHash util.Uint256 - Trigger byte + Trigger trigger.Type VMState string GasConsumed util.Fixed8 Stack string // JSON @@ -39,7 +40,7 @@ func (ne *NotificationEvent) DecodeBinary(r *io.BinReader) { // EncodeBinary implements the Serializable interface. func (aer *AppExecResult) EncodeBinary(w *io.BinWriter) { w.WriteBytes(aer.TxHash[:]) - w.WriteB(aer.Trigger) + w.WriteB(byte(aer.Trigger)) w.WriteString(aer.VMState) aer.GasConsumed.EncodeBinary(w) w.WriteString(aer.Stack) @@ -49,7 +50,7 @@ func (aer *AppExecResult) EncodeBinary(w *io.BinWriter) { // DecodeBinary implements the Serializable interface. func (aer *AppExecResult) DecodeBinary(r *io.BinReader) { r.ReadBytes(aer.TxHash[:]) - aer.Trigger = r.ReadB() + aer.Trigger = trigger.Type(r.ReadB()) aer.VMState = r.ReadString() aer.GasConsumed.DecodeBinary(r) aer.Stack = r.ReadString() diff --git a/pkg/smartcontract/trigger/trigger_type.go b/pkg/smartcontract/trigger/trigger_type.go index 6b5630a1e..80f499b13 100644 --- a/pkg/smartcontract/trigger/trigger_type.go +++ b/pkg/smartcontract/trigger/trigger_type.go @@ -1,13 +1,18 @@ package trigger -// Trigger typed used in C# reference node: https://github.com/neo-project/neo/blob/c64748ecbac3baeb8045b16af0d518398a6ced24/neo/SmartContract/TriggerType.cs#L3 +//go:generate stringer -type=Type + +// Type represents trigger type used in C# reference node: https://github.com/neo-project/neo/blob/c64748ecbac3baeb8045b16af0d518398a6ced24/neo/SmartContract/TriggerType.cs#L3 +type Type byte + +// Viable list of supported trigger type constants. const ( // The verification trigger indicates that the contract is being invoked as a verification function. // The verification function can accept multiple parameters, and should return a boolean value that indicates the validity of the transaction or block. // The entry point of the contract will be invoked if the contract is triggered by Verification: // main(...); // The entry point of the contract must be able to handle this type of invocation. - Verification = 0x00 + Verification Type = 0x00 // The verificationR trigger indicates that the contract is being invoked as a verification function because it is specified as a target of an output of the transaction. // The verification function accepts no parameter, and should return a boolean value that indicates the validity of the transaction. @@ -16,14 +21,14 @@ const ( // The receiving function should have the following signature: // public bool receiving() // The receiving function will be invoked automatically when a contract is receiving assets from a transfer. - VerificationR = 0x01 + VerificationR Type = 0x01 // The application trigger indicates that the contract is being invoked as an application function. // The application function can accept multiple parameters, change the states of the blockchain, and return any type of value. // The contract can have any form of entry point, but we recommend that all contracts should have the following entry point: // public byte[] main(string operation, params object[] args) // The functions can be invoked by creating an InvocationTransaction. - Application = 0x10 + Application Type = 0x10 // The ApplicationR trigger indicates that the default function received of the contract is being invoked because it is specified as a target of an output of the transaction. // The received function accepts no parameter, changes the states of the blockchain, and returns any type of value. @@ -32,5 +37,5 @@ const ( // The received function should have the following signature: // public byte[] received() // The received function will be invoked automatically when a contract is receiving assets from a transfer. - ApplicationR = 0x11 + ApplicationR Type = 0x11 ) diff --git a/pkg/smartcontract/trigger/trigger_type_string.go b/pkg/smartcontract/trigger/trigger_type_string.go new file mode 100644 index 000000000..298846f94 --- /dev/null +++ b/pkg/smartcontract/trigger/trigger_type_string.go @@ -0,0 +1,37 @@ +// Code generated by "stringer -type=Type"; DO NOT EDIT. + +package trigger + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Verification-0] + _ = x[VerificationR-1] + _ = x[Application-16] + _ = x[ApplicationR-17] +} + +const ( + _Type_name_0 = "VerificationVerificationR" + _Type_name_1 = "ApplicationApplicationR" +) + +var ( + _Type_index_0 = [...]uint8{0, 12, 25} + _Type_index_1 = [...]uint8{0, 11, 23} +) + +func (i Type) String() string { + switch { + case i <= 1: + return _Type_name_0[_Type_index_0[i]:_Type_index_0[i+1]] + case 16 <= i && i <= 17: + i -= 16 + return _Type_name_1[_Type_index_1[i]:_Type_index_1[i+1]] + default: + return "Type(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/pkg/smartcontract/trigger/trigger_type_test.go b/pkg/smartcontract/trigger/trigger_type_test.go new file mode 100644 index 000000000..211b7436d --- /dev/null +++ b/pkg/smartcontract/trigger/trigger_type_test.go @@ -0,0 +1,43 @@ +package trigger + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestStringer(t *testing.T) { + tests := map[Type]string{ + Application: "Application", + ApplicationR: "ApplicationR", + Verification: "Verification", + VerificationR: "VerificationR", + } + for o, s := range tests { + assert.Equal(t, s, o.String()) + } +} + +func TestEncodeBynary(t *testing.T) { + tests := map[Type]byte{ + Verification: 0x00, + VerificationR: 0x01, + Application: 0x10, + ApplicationR: 0x11, + } + for o, b := range tests { + assert.Equal(t, b, byte(o)) + } +} + +func TestDecodeBynary(t *testing.T) { + tests := map[Type]byte{ + Verification: 0x00, + VerificationR: 0x01, + Application: 0x10, + ApplicationR: 0x11, + } + for o, b := range tests { + assert.Equal(t, o, Type(b)) + } +}