diff --git a/pkg/config/ledger_config.go b/pkg/config/ledger_config.go index 529a0d0176..f62f0e43fd 100644 --- a/pkg/config/ledger_config.go +++ b/pkg/config/ledger_config.go @@ -19,6 +19,8 @@ type Ledger struct { // SkipBlockVerification allows to disable verification of received // blocks (including cryptographic checks). SkipBlockVerification bool `yaml:"SkipBlockVerification"` + // SaveInvocations enables contract smart contract invocation data saving. + SaveInvocations bool `yaml:"SaveInvocations"` } // Blockchain is a set of settings for core.Blockchain to use, it includes protocol diff --git a/pkg/core/dao/dao_test.go b/pkg/core/dao/dao_test.go index f57b4d3649..acc88c9ed7 100644 --- a/pkg/core/dao/dao_test.go +++ b/pkg/core/dao/dao_test.go @@ -196,6 +196,8 @@ func TestStoreAsTransaction(t *testing.T) { Arguments: stackitem.NewArray([]stackitem.Item{ stackitem.NewBool(false), }), + ArgumentsCount: 1, + IsValid: true, }}, }, } diff --git a/pkg/core/interop/contract/call.go b/pkg/core/interop/contract/call.go index 6c6bdc64a4..bc91010fc3 100644 --- a/pkg/core/interop/contract/call.go +++ b/pkg/core/interop/contract/call.go @@ -70,11 +70,23 @@ func Call(ic *interop.Context) error { } hasReturn := md.ReturnType != smartcontract.VoidType - ic.InvocationCalls = append(ic.InvocationCalls, state.ContractInvocation{ - Hash: u, - Method: method, - Arguments: stackitem.NewArray(args), - }) + if ic.Chain.GetConfig().Ledger.SaveInvocations { + arr := stackitem.NewArray(args) + arrCount := len(args) + valid := true + if _, err = ic.DAO.GetItemCtx().Serialize(arr, false); err != nil { + arr = stackitem.NewArray([]stackitem.Item{}) + valid = false + } + + ic.InvocationCalls = append(ic.InvocationCalls, state.ContractInvocation{ + Hash: u, + Method: method, + Arguments: arr, + ArgumentsCount: uint32(arrCount), + IsValid: valid, + }) + } return callInternal(ic, cs, method, fs, hasReturn, args, true) } diff --git a/pkg/core/state/notification_event.go b/pkg/core/state/notification_event.go index 9fdd38b2e8..17619de68e 100644 --- a/pkg/core/state/notification_event.go +++ b/pkg/core/state/notification_event.go @@ -21,9 +21,11 @@ type NotificationEvent struct { } type ContractInvocation struct { - Hash util.Uint160 `json:"contract_hash"` - Method string `json:"method"` - Arguments *stackitem.Array `json:"arguments"` + Hash util.Uint160 `json:"contract_hash"` + Method string `json:"method"` + Arguments *stackitem.Array `json:"arguments"` + ArgumentsCount uint32 `json:"arguments_count"` + IsValid bool `json:"is_valid"` } func (ci *ContractInvocation) DecodeBinary(r *io.BinReader) { @@ -39,6 +41,8 @@ func (ci *ContractInvocation) DecodeBinary(r *io.BinReader) { return } ci.Arguments = stackitem.NewArray(arr) + ci.ArgumentsCount = r.ReadU32LE() + ci.IsValid = r.ReadBool() } func (ci *ContractInvocation) EncodeBinaryWithContext(w *io.BinWriter, sc *stackitem.SerializationContext) { @@ -50,6 +54,8 @@ func (ci *ContractInvocation) EncodeBinaryWithContext(w *io.BinWriter, sc *stack return } w.WriteBytes(b) + w.WriteU32LE(ci.ArgumentsCount) + w.WriteBool(ci.IsValid) } // MarshalJSON implements the json.Marshaler interface. @@ -59,9 +65,11 @@ func (ci ContractInvocation) MarshalJSON() ([]byte, error) { item = []byte(fmt.Sprintf(`"error: %v"`, err)) } return json.Marshal(ContractInvocationAux{ - Hash: ci.Hash, - Method: ci.Method, - Arguments: item, + Hash: ci.Hash, + Method: ci.Method, + Arguments: item, + ArgumentsCount: ci.ArgumentsCount, + IsValid: ci.IsValid, }) } @@ -81,6 +89,8 @@ func (ci *ContractInvocation) UnmarshalJSON(data []byte) error { ci.Arguments = params.(*stackitem.Array) ci.Method = aux.Method ci.Hash = aux.Hash + ci.ArgumentsCount = aux.ArgumentsCount + ci.IsValid = aux.IsValid return nil } @@ -286,9 +296,11 @@ type Execution struct { } type ContractInvocationAux struct { - Hash util.Uint160 `json:"contract_hash"` - Method string `json:"method"` - Arguments json.RawMessage `json:"arguments"` + Hash util.Uint160 `json:"contract_hash"` + Method string `json:"method"` + Arguments json.RawMessage `json:"arguments"` + ArgumentsCount uint32 `json:"arguments_count"` + IsValid bool `json:"is_valid"` } // executionAux represents an auxiliary struct for Execution JSON marshalling.