From 64cfa1da0f4b8f5bb51668140f726de37a313c3c Mon Sep 17 00:00:00 2001 From: Tugay Emin Date: Mon, 20 Nov 2023 08:40:19 +0200 Subject: [PATCH 1/8] refactor error resolving --- api/block_builder/module.go | 16 +- api/block_builder/module_test.go | 8 +- api/tagged_transaction_queue/module.go | 18 +- api/tagged_transaction_queue/module_test.go | 4 +- execution/extrinsic/unsigned_validator.go | 11 +- .../extrinsic/unsigned_validator_test.go | 6 +- execution/types/checked_extrinsic.go | 16 +- execution/types/checked_extrinsic_test.go | 42 ++-- execution/types/unchecked_extrinsic.go | 8 +- execution/types/unchecked_extrinsic_test.go | 8 +- frame/aura/module.go | 8 +- frame/aura/module_test.go | 2 +- frame/balances/call_force_free.go | 10 +- frame/balances/call_force_free_test.go | 4 +- frame/balances/call_force_transfer.go | 4 +- frame/balances/call_force_transfer_test.go | 6 +- frame/balances/call_set_balance.go | 32 +-- frame/balances/call_set_balance_test.go | 10 +- frame/balances/call_transfer.go | 29 +-- frame/balances/call_transfer_all.go | 4 +- frame/balances/call_transfer_all_test.go | 4 +- frame/balances/call_transfer_keep_alive.go | 4 +- .../balances/call_transfer_keep_alive_test.go | 4 +- frame/balances/call_transfer_test.go | 22 +- frame/balances/mock_transfer_test.go | 6 +- frame/balances/module.go | 30 ++- frame/balances/module_test.go | 16 +- frame/balances/types.go | 2 +- frame/executive/executive.go | 33 +-- frame/executive/executive_test.go | 22 +- frame/grandpa/module.go | 8 +- frame/grandpa/module_test.go | 2 +- frame/support/transactional.go | 44 ++-- frame/support/transactional_test.go | 12 +- frame/system/call_remark.go | 4 +- frame/system/call_remark_test.go | 2 +- frame/system/events.go | 6 +- frame/system/extensions/check_genesis.go | 16 +- frame/system/extensions/check_mortality.go | 28 +-- .../system/extensions/check_mortality_test.go | 2 +- .../extensions/check_non_zero_sender.go | 16 +- .../extensions/check_non_zero_sender_test.go | 2 +- frame/system/extensions/check_nonce.go | 33 ++- frame/system/extensions/check_nonce_test.go | 4 +- frame/system/extensions/check_spec_version.go | 12 +- frame/system/extensions/check_tx_version.go | 12 +- frame/system/extensions/check_weight.go | 56 ++--- frame/system/extensions/check_weight_test.go | 2 +- frame/system/module.go | 16 +- frame/system/module_test.go | 6 +- frame/testable/call.go | 2 +- frame/testable/module.go | 8 +- frame/timestamp/call_set.go | 4 +- frame/timestamp/call_set_test.go | 2 +- frame/timestamp/module.go | 4 +- .../extensions/charge_transaction.go | 16 +- .../extensions/charge_transaction_payment.go | 22 +- .../charge_transaction_payment_test.go | 2 +- .../extensions/charge_transaction_test.go | 2 +- frame/transaction_payment/module.go | 8 +- frame/transaction_payment/module_test.go | 2 +- hooks/on_charge_transaction.go | 4 +- mocks/account_id_lookup.go | 4 +- mocks/aura.go | 8 +- mocks/checked_extrinsic.go | 12 +- mocks/currency_adapter.go | 8 +- mocks/executive.go | 8 +- mocks/grandpa.go | 8 +- mocks/io_transactional.go | 7 +- mocks/module.go | 8 +- mocks/on_charge_transaction.go | 8 +- mocks/signed_extra.go | 30 +-- mocks/system.go | 8 +- mocks/tx_payment_module.go | 8 +- mocks/unchecked_extrinsic.go | 6 +- mocks/unsigned_validator.go | 8 +- primitives/types/apply_extrinsic_result.go | 8 +- .../types/apply_extrinsic_result_test.go | 4 +- primitives/types/arithmetic_error.go | 39 +++- primitives/types/arithmetic_error_test.go | 19 +- primitives/types/checked_extrinsic.go | 4 +- primitives/types/currency_adapter.go | 4 +- primitives/types/dispatch_errors.go | 192 +++++++++++------- primitives/types/dispatch_errors_test.go | 6 +- primitives/types/dispatch_outcome.go | 8 +- primitives/types/dispatch_result_test.go | 2 +- .../dispatch_result_with_post_info_test.go | 8 +- primitives/types/errors.go | 4 +- primitives/types/extra.go | 24 +-- primitives/types/extra_test.go | 2 +- .../types/extrinsic_signature_payload.go | 2 +- .../types/extrinsic_signature_payload_test.go | 2 +- primitives/types/invalid_transaction.go | 33 +++ primitives/types/lookup.go | 11 +- primitives/types/lookup_test.go | 2 +- primitives/types/module.go | 4 +- primitives/types/signed_extension.go | 12 +- primitives/types/testextra_test.go | 14 +- primitives/types/token_error.go | 63 ++++-- primitives/types/token_error_test.go | 63 ++---- .../types/transaction_validity_error.go | 33 ++- .../types/transaction_validity_error_test.go | 38 ++-- .../types/transaction_validity_result.go | 8 +- .../types/transaction_validity_result_test.go | 6 +- primitives/types/transactional_error.go | 33 ++- primitives/types/transactional_error_test.go | 23 +-- primitives/types/unchecked_extrinsic.go | 2 +- primitives/types/unknown_transaction.go | 17 ++ primitives/types/unsigned_validator.go | 4 +- runtime/runtime_test.go | 32 +-- runtime/validate_transaction_test.go | 3 +- 111 files changed, 823 insertions(+), 785 deletions(-) diff --git a/api/block_builder/module.go b/api/block_builder/module.go index 86564080..cde868d0 100644 --- a/api/block_builder/module.go +++ b/api/block_builder/module.go @@ -69,16 +69,14 @@ func (m Module) ApplyExtrinsic(dataPtr int32, dataLen int32) int64 { ok, errApplyExtr := m.executive.ApplyExtrinsic(uxt) var applyExtrinsicResult primitives.ApplyExtrinsicResult - if errApplyExtr != nil { - applyExtrinsicResult, err = primitives.NewApplyExtrinsicResult(errApplyExtr) - if err != nil { - log.Critical(err.Error()) - } - } else { + switch errApplyExtr.(type) { + case primitives.TransactionValidityError: + applyExtrinsicResult, err = primitives.NewApplyExtrinsicResult(errApplyExtr.(primitives.TransactionValidityError)) + case nil: applyExtrinsicResult, err = primitives.NewApplyExtrinsicResult(ok) - if err != nil { - log.Critical(err.Error()) - } + } + if err != nil { + log.Critical(err.Error()) } buffer.Reset() diff --git a/api/block_builder/module_test.go b/api/block_builder/module_test.go index 41cf4a53..ece55e1f 100644 --- a/api/block_builder/module_test.go +++ b/api/block_builder/module_test.go @@ -80,15 +80,15 @@ func Test_Module_ApplyExtrinsic_Fails(t *testing.T) { bufferUxt := bytes.NewBuffer(bUxt) outcome, err := primitives.NewDispatchOutcome(sc.Empty{}) assert.Nil(t, err) - validityError, err := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) - assert.Nil(t, err) - applyExtrinsicResultValidityErr, err := primitives.NewApplyExtrinsicResult(validityError) + txErr, ok := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()).(primitives.TransactionValidityError) + assert.True(t, ok) + applyExtrinsicResultValidityErr, err := primitives.NewApplyExtrinsicResult(txErr) assert.Nil(t, err) bExtrinsicResult := applyExtrinsicResultValidityErr.Bytes() mockMemoryUtils.On("GetWasmMemorySlice", dataPtr, dataLen).Return(bUxt) mockRuntimeDecoder.On("DecodeUncheckedExtrinsic", bufferUxt).Return(uxt, nil) - mockExecutive.On("ApplyExtrinsic", uxt).Return(outcome, validityError) + mockExecutive.On("ApplyExtrinsic", uxt).Return(outcome, txErr) mockMemoryUtils.On("BytesToOffsetAndSize", bExtrinsicResult).Return(ptrAndSize) result := target.ApplyExtrinsic(dataPtr, dataLen) diff --git a/api/tagged_transaction_queue/module.go b/api/tagged_transaction_queue/module.go index d2d98fba..19632c0a 100644 --- a/api/tagged_transaction_queue/module.go +++ b/api/tagged_transaction_queue/module.go @@ -70,18 +70,16 @@ func (m Module) ValidateTransaction(dataPtr int32, dataLen int32) int64 { } ok, errTx := m.executive.ValidateTransaction(txSource, tx, blockHash) - var res primitives.TransactionValidityResult - if errTx != nil { - res, err = primitives.NewTransactionValidityResult(errTx) - if err != nil { - log.Critical(err.Error()) - } - } else { + switch errTx.(type) { + case primitives.TransactionValidityError: + res, err = primitives.NewTransactionValidityResult(errTx.(primitives.TransactionValidityError)) + case nil: res, err = primitives.NewTransactionValidityResult(ok) - if err != nil { - log.Critical(err.Error()) - } + default: + } + if err != nil { + log.Critical(err.Error()) } return m.memUtils.BytesToOffsetAndSize(res.Bytes()) diff --git a/api/tagged_transaction_queue/module_test.go b/api/tagged_transaction_queue/module_test.go index e37fa20b..5b630de5 100644 --- a/api/tagged_transaction_queue/module_test.go +++ b/api/tagged_transaction_queue/module_test.go @@ -24,9 +24,9 @@ var ( )} validTx = primitives.DefaultValidTransaction() - txValidityError, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) + txValidityError = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) validitySuccessResult, _ = primitives.NewTransactionValidityResult(validTx) - validityFailResult, _ = primitives.NewTransactionValidityResult(txValidityError) + validityFailResult, _ = primitives.NewTransactionValidityResult(txValidityError.(primitives.TransactionValidityError)) ) var ( diff --git a/execution/extrinsic/unsigned_validator.go b/execution/extrinsic/unsigned_validator.go index 3c080030..b1e4887e 100644 --- a/execution/extrinsic/unsigned_validator.go +++ b/execution/extrinsic/unsigned_validator.go @@ -2,7 +2,6 @@ package extrinsic import ( sc "github.com/LimeChain/goscale" - "github.com/LimeChain/gosemble/primitives/log" primitives "github.com/LimeChain/gosemble/primitives/types" ) @@ -18,7 +17,7 @@ func NewUnsignedValidatorForChecked(extrinsic RuntimeExtrinsic) primitives.Unsig // PreDispatch validates the dispatch call before execution. // Inherent call is accepted for being dispatched -func (v UnsignedValidatorForChecked) PreDispatch(call primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (v UnsignedValidatorForChecked) PreDispatch(call primitives.Call) (sc.Empty, error) { module, ok := v.runtimeExtrinsic.Module(call.ModuleIndex()) if !ok { return sc.Empty{}, nil @@ -29,14 +28,10 @@ func (v UnsignedValidatorForChecked) PreDispatch(call primitives.Call) (sc.Empty // ValidateUnsigned returns the validity of the dispatch call. // Inherent call is not validated as unsigned -func (v UnsignedValidatorForChecked) ValidateUnsigned(txSource primitives.TransactionSource, call primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (v UnsignedValidatorForChecked) ValidateUnsigned(txSource primitives.TransactionSource, call primitives.Call) (primitives.ValidTransaction, error) { module, ok := v.runtimeExtrinsic.Module(call.ModuleIndex()) if !ok { - unknownTransactionNoUnsignedValidator, err := primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - if err != nil { - log.Critical(err.Error()) - } - return primitives.ValidTransaction{}, unknownTransactionNoUnsignedValidator + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) } return module.ValidateUnsigned(txSource, call) diff --git a/execution/extrinsic/unsigned_validator_test.go b/execution/extrinsic/unsigned_validator_test.go index ea8377af..996d210d 100644 --- a/execution/extrinsic/unsigned_validator_test.go +++ b/execution/extrinsic/unsigned_validator_test.go @@ -16,9 +16,9 @@ var ( ) var ( - expectedInvalidTransactionStaleErr, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) - expectedUnknownTransactionNoUnsignedValidatorErr, _ = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - expectInvalidTransactionPaymentErr, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) + expectedInvalidTransactionStaleErr = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) + expectedUnknownTransactionNoUnsignedValidatorErr = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) + expectInvalidTransactionPaymentErr = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) ) var ( diff --git a/execution/types/checked_extrinsic.go b/execution/types/checked_extrinsic.go index e10c2260..74d8ac24 100644 --- a/execution/types/checked_extrinsic.go +++ b/execution/types/checked_extrinsic.go @@ -16,7 +16,7 @@ type checkedExtrinsic struct { signer sc.Option[primitives.AccountId[primitives.PublicKey]] function primitives.Call extra primitives.SignedExtra - transactional support.Transactional[primitives.PostDispatchInfo, primitives.DispatchError] + transactional support.Transactional[primitives.PostDispatchInfo] } func NewCheckedExtrinsic(signer sc.Option[primitives.AccountId[primitives.PublicKey]], function primitives.Call, extra primitives.SignedExtra) primitives.CheckedExtrinsic { @@ -24,7 +24,7 @@ func NewCheckedExtrinsic(signer sc.Option[primitives.AccountId[primitives.Public signer: signer, function: function, extra: extra, - transactional: support.NewTransactional[primitives.PostDispatchInfo, primitives.DispatchError](), + transactional: support.NewTransactional[primitives.PostDispatchInfo](), } } @@ -32,7 +32,7 @@ func (c checkedExtrinsic) Function() primitives.Call { return c.function } -func (c checkedExtrinsic) Apply(validator primitives.UnsignedValidator, info *primitives.DispatchInfo, length sc.Compact) (primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo], primitives.TransactionValidityError) { +func (c checkedExtrinsic) Apply(validator primitives.UnsignedValidator, info *primitives.DispatchInfo, length sc.Compact) (primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo], error) { var ( maybeWho sc.Option[primitives.AccountId[primitives.PublicKey]] maybePre sc.Option[sc.Sequence[primitives.Pre]] @@ -70,7 +70,7 @@ func (c checkedExtrinsic) Apply(validator primitives.UnsignedValidator, info *pr var resWithInfo primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo] dispatchInfo, err := c.transactional.WithStorageLayer( - func() (primitives.PostDispatchInfo, primitives.DispatchError) { + func() (primitives.PostDispatchInfo, error) { return c.dispatch(maybeWho) }, ) @@ -79,7 +79,7 @@ func (c checkedExtrinsic) Apply(validator primitives.UnsignedValidator, info *pr resWithInfo.HasError = true resWithInfo.Err = primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ PostInfo: dispatchInfo, - Error: err, + Err: err, } } else { resWithInfo.Ok = dispatchInfo @@ -100,7 +100,7 @@ func (c checkedExtrinsic) Apply(validator primitives.UnsignedValidator, info *pr return resWithInfo, c.extra.PostDispatch(maybePre, info, &postInfo, length, &dispatchResult) } -func (c checkedExtrinsic) Validate(validator primitives.UnsignedValidator, source primitives.TransactionSource, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (c checkedExtrinsic) Validate(validator primitives.UnsignedValidator, source primitives.TransactionSource, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { if c.signer.HasValue { id := c.signer.Value return c.extra.Validate(id, c.function, info, length) @@ -119,11 +119,11 @@ func (c checkedExtrinsic) Validate(validator primitives.UnsignedValidator, sourc return valid.CombineWith(unsignedValidation), nil } -func (c checkedExtrinsic) dispatch(maybeWho sc.Option[primitives.AccountId[primitives.PublicKey]]) (primitives.PostDispatchInfo, primitives.DispatchError) { +func (c checkedExtrinsic) dispatch(maybeWho sc.Option[primitives.AccountId[primitives.PublicKey]]) (primitives.PostDispatchInfo, error) { resWithInfo := c.function.Dispatch(primitives.RawOriginFrom(maybeWho), c.function.Args()) if resWithInfo.HasError { - return resWithInfo.Err.PostInfo, resWithInfo.Err.Error + return resWithInfo.Err.PostInfo, resWithInfo.Err.Err } return resWithInfo.Ok, nil diff --git a/execution/types/checked_extrinsic_test.go b/execution/types/checked_extrinsic_test.go index 09fc0dc5..fd094420 100644 --- a/execution/types/checked_extrinsic_test.go +++ b/execution/types/checked_extrinsic_test.go @@ -31,7 +31,7 @@ var ( ActualWeight: sc.NewOption[types.Weight](nil), PaysFee: types.PaysNo, }, - Error: types.NewDispatchErrorCorruption(), + Err: types.NewDispatchErrorCorruption(), } pre = sc.Sequence[types.Pre]{sc.NewVaryingData(sc.U32(1)), sc.NewVaryingData(sc.U32(7))} optionPre = sc.NewOption[sc.Sequence[types.Pre]](pre) @@ -39,16 +39,16 @@ var ( ) var ( - expectedInvalidTransactionStaleErr, _ = types.NewTransactionValidityError(types.NewInvalidTransactionStale()) - expectedInvalidTransactionPaymentErr, _ = types.NewTransactionValidityError(types.NewInvalidTransactionPayment()) - expectedUnknownTransactionNoUnsignedValidatorErr, _ = types.NewTransactionValidityError(types.NewUnknownTransactionNoUnsignedValidator()) + expectedInvalidTransactionStaleErr = types.NewTransactionValidityError(types.NewInvalidTransactionStale()) + expectedInvalidTransactionPaymentErr = types.NewTransactionValidityError(types.NewInvalidTransactionPayment()) + expectedUnknownTransactionNoUnsignedValidatorErr = types.NewTransactionValidityError(types.NewUnknownTransactionNoUnsignedValidator()) ) var ( - mockTransactional *mocks.IoTransactional[types.PostDispatchInfo, types.DispatchError] + mockTransactional *mocks.IoTransactional[types.PostDispatchInfo] mockUnsignedValidator *mocks.UnsignedValidator - mockWithStorageLayer = mock.AnythingOfType("func() (types.PostDispatchInfo, goscale.VaryingData)") + mockWithStorageLayer = mock.AnythingOfType("func() (types.PostDispatchInfo, error)") ) func Test_CheckedExtrinsic_Function(t *testing.T) { @@ -72,7 +72,7 @@ func Test_CheckedExtrinsic_Apply_Signed_Success(t *testing.T) { mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(postDispatchInfo, nil) mockSignedExtra. On("PostDispatch", optionPre, dispatchInfo, &postDispatchInfo, length, &dispatchResult). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) result, err := target.Apply(mockUnsignedValidator, dispatchInfo, length) @@ -116,10 +116,10 @@ func Test_CheckedExtrinsic_Apply_Signed_WithStorageLayerErr(t *testing.T) { mockSignedExtra. On("PreDispatch", signerOption.Value, mockCall, dispatchInfo, length). Return(pre, nil) - mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(errPostDispatchInfo.PostInfo, errPostDispatchInfo.Error) + mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(errPostDispatchInfo.PostInfo, errPostDispatchInfo.Err) mockSignedExtra. On("PostDispatch", optionPre, dispatchInfo, &errPostDispatchInfo.PostInfo, length, &dispatchResult). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) result, err := target.Apply(mockUnsignedValidator, dispatchInfo, length) @@ -146,7 +146,7 @@ func Test_CheckedExtrinsic_Apply_Signed_WithStorageLayerErr_PostDispatchErr(t *t mockSignedExtra. On("PreDispatch", signerOption.Value, mockCall, dispatchInfo, length). Return(pre, nil) - mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(errPostDispatchInfo.PostInfo, errPostDispatchInfo.Error) + mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(errPostDispatchInfo.PostInfo, errPostDispatchInfo.Err) mockSignedExtra. On("PostDispatch", optionPre, dispatchInfo, &errPostDispatchInfo.PostInfo, length, &dispatchResult). Return(expectedInvalidTransactionStaleErr) @@ -201,12 +201,12 @@ func Test_CheckedExtrinsic_Apply_Unsigned_Success(t *testing.T) { mockSignedExtra. On("PreDispatchUnsigned", mockCall, dispatchInfo, length). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) mockUnsignedValidator.On("PreDispatch", mockCall).Return(sc.Empty{}, nil) mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(postDispatchInfo, nil) mockSignedExtra. On("PostDispatch", emptyOptionPre, dispatchInfo, &postDispatchInfo, length, &dispatchResult). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) result, err := target.Apply(mockUnsignedValidator, dispatchInfo, length) @@ -246,7 +246,7 @@ func Test_CheckedExtrinsic_Apply_Unsigned_PreDispatch_Fails(t *testing.T) { mockSignedExtra. On("PreDispatchUnsigned", mockCall, dispatchInfo, length). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) mockUnsignedValidator.On("PreDispatch", mockCall).Return(sc.Empty{}, expectedInvalidTransactionStaleErr) result, err := target.Apply(mockUnsignedValidator, dispatchInfo, length) @@ -271,12 +271,12 @@ func Test_CheckedExtrinsic_Apply_Unsigned_WithStorageLayerErr(t *testing.T) { mockSignedExtra. On("PreDispatchUnsigned", mockCall, dispatchInfo, length). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) mockUnsignedValidator.On("PreDispatch", mockCall).Return(sc.Empty{}, nil) - mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(errPostDispatchInfo.PostInfo, errPostDispatchInfo.Error) + mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(errPostDispatchInfo.PostInfo, errPostDispatchInfo.Err) mockSignedExtra. On("PostDispatch", emptyOptionPre, dispatchInfo, &errPostDispatchInfo.PostInfo, length, &dispatchResult). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) result, err := target.Apply(mockUnsignedValidator, dispatchInfo, length) @@ -303,9 +303,9 @@ func Test_CheckedExtrinsic_Apply_Unsigned_WithStorageLayerErr_PostDispatch_Fails mockSignedExtra. On("PreDispatchUnsigned", mockCall, dispatchInfo, length). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) mockUnsignedValidator.On("PreDispatch", mockCall).Return(sc.Empty{}, nil) - mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(errPostDispatchInfo.PostInfo, errPostDispatchInfo.Error) + mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(errPostDispatchInfo.PostInfo, errPostDispatchInfo.Err) mockSignedExtra. On("PostDispatch", emptyOptionPre, dispatchInfo, &errPostDispatchInfo.PostInfo, length, &dispatchResult). Return(expectedInvalidTransactionStaleErr) @@ -334,7 +334,7 @@ func Test_CheckedExtrinsic_Apply_Unsigned_PostDispatch_Fails(t *testing.T) { mockSignedExtra. On("PreDispatchUnsigned", mockCall, dispatchInfo, length). - Return(types.TransactionValidityError(nil)) + Return(error(nil)) mockUnsignedValidator.On("PreDispatch", mockCall).Return(sc.Empty{}, nil) mockTransactional.On("WithStorageLayer", mockWithStorageLayer).Return(postDispatchInfo, nil) mockSignedExtra. @@ -461,7 +461,7 @@ func Test_CheckedExtrinsic_dispatch_Fails(t *testing.T) { res, err := target.dispatch(signerOption) - assert.Equal(t, errPostDispatchInfo.Error, err) + assert.Equal(t, errPostDispatchInfo.Err, err) assert.Equal(t, errPostDispatchInfo.PostInfo, res) mockCall.AssertCalled(t, "Args") mockCall.AssertCalled(t, "Dispatch", types.RawOriginFrom(signerOption), args) @@ -470,7 +470,7 @@ func Test_CheckedExtrinsic_dispatch_Fails(t *testing.T) { func setupCheckedExtrinsic(signer sc.Option[types.AccountId[types.PublicKey]]) checkedExtrinsic { mockCall = new(mocks.Call) mockSignedExtra = new(mocks.SignedExtra) - mockTransactional = new(mocks.IoTransactional[types.PostDispatchInfo, types.DispatchError]) + mockTransactional = new(mocks.IoTransactional[types.PostDispatchInfo]) mockUnsignedValidator = new(mocks.UnsignedValidator) target := NewCheckedExtrinsic(signer, mockCall, mockSignedExtra).(checkedExtrinsic) diff --git a/execution/types/unchecked_extrinsic.go b/execution/types/unchecked_extrinsic.go index b28fcb1c..978ce170 100644 --- a/execution/types/unchecked_extrinsic.go +++ b/execution/types/unchecked_extrinsic.go @@ -21,7 +21,7 @@ const ( ) type PayloadInitializer = func(call primitives.Call, extra primitives.SignedExtra) ( - primitives.SignedPayload, primitives.TransactionValidityError, + primitives.SignedPayload, error, ) type uncheckedExtrinsic struct { @@ -107,7 +107,7 @@ func (uxt uncheckedExtrinsic) IsSigned() bool { return bool(uxt.signature.HasValue) } -func (uxt uncheckedExtrinsic) Check() (primitives.CheckedExtrinsic, primitives.TransactionValidityError) { +func (uxt uncheckedExtrinsic) Check() (primitives.CheckedExtrinsic, error) { if uxt.signature.HasValue { signer, signature, extra := uxt.signature.Value.Signer, uxt.signature.Value.Signature, uxt.signature.Value.Extra @@ -122,9 +122,7 @@ func (uxt uncheckedExtrinsic) Check() (primitives.CheckedExtrinsic, primitives.T } if !uxt.verify(signature, uxt.usingEncoded(rawPayload), signerAddress) { - // https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionBadProof, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadProof()) - return nil, invalidTransactionBadProof + return nil, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadProof()) } return NewCheckedExtrinsic(sc.NewOption[primitives.AccountId[primitives.PublicKey]](signerAddress), uxt.function, extra), nil diff --git a/execution/types/unchecked_extrinsic_test.go b/execution/types/unchecked_extrinsic_test.go index 8e624043..4a2cb2b6 100644 --- a/execution/types/unchecked_extrinsic_test.go +++ b/execution/types/unchecked_extrinsic_test.go @@ -17,13 +17,13 @@ const ( ) var ( - unknownTransactionCannotLookupError, _ = types.NewTransactionValidityError( + unknownTransactionCannotLookupError = types.NewTransactionValidityError( types.NewUnknownTransactionCannotLookup(), ) - invalidTransactionAncientBirthBlockError, _ = types.NewTransactionValidityError( + invalidTransactionAncientBirthBlockError = types.NewTransactionValidityError( types.NewInvalidTransactionAncientBirthBlock(), ) - invalidTransactionBadProofError, _ = types.NewTransactionValidityError( + invalidTransactionBadProofError = types.NewTransactionValidityError( types.NewInvalidTransactionBadProof(), ) @@ -110,7 +110,7 @@ func newTestSignedExtrinsic( crypto io.Crypto, hashing io.Hashing) uncheckedExtrinsic { - initializer := func(call types.Call, extra types.SignedExtra) (types.SignedPayload, types.TransactionValidityError) { + initializer := func(call types.Call, extra types.SignedExtra) (types.SignedPayload, error) { return signedPayload, nil } diff --git a/frame/aura/module.go b/frame/aura/module.go index 2bda5d84..10fc24fe 100644 --- a/frame/aura/module.go +++ b/frame/aura/module.go @@ -64,14 +64,12 @@ func (m Module) Functions() map[sc.U8]primitives.Call { return map[sc.U8]primitives.Call{} } -func (m Module) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m Module) PreDispatch(_ primitives.Call) (sc.Empty, error) { return sc.Empty{}, nil } -func (m Module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - unknownTransactionNoUnsignedValidator, _ := primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - return primitives.ValidTransaction{}, unknownTransactionNoUnsignedValidator +func (m Module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, error) { + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) } func (m Module) KeyType() primitives.PublicKeyType { diff --git a/frame/aura/module_test.go b/frame/aura/module_test.go index 5798d328..4bf10f62 100644 --- a/frame/aura/module_test.go +++ b/frame/aura/module_test.go @@ -22,7 +22,7 @@ const ( ) var ( - unknownTransactionNoUnsignedValidator, _ = types.NewTransactionValidityError(types.NewUnknownTransactionNoUnsignedValidator()) + unknownTransactionNoUnsignedValidator = types.NewTransactionValidityError(types.NewUnknownTransactionNoUnsignedValidator()) ) var ( diff --git a/frame/balances/call_force_free.go b/frame/balances/call_force_free.go index ea9d6ac8..950bc0d9 100644 --- a/frame/balances/call_force_free.go +++ b/frame/balances/call_force_free.go @@ -98,7 +98,7 @@ func (c callForceFree[T]) Dispatch(origin types.RuntimeOrigin, args sc.VaryingDa return types.DispatchResultWithPostInfo[types.PostDispatchInfo]{ HasError: true, Err: types.DispatchErrorWithPostInfo[types.PostDispatchInfo]{ - Error: err, + Err: err, }, } } @@ -112,7 +112,7 @@ func (c callForceFree[T]) Dispatch(origin types.RuntimeOrigin, args sc.VaryingDa // forceFree frees some balance from a user by force. // Can only be called by ROOT. // Consider Substrate fn force_unreserve -func (c callForceFree[T]) forceFree(origin types.RawOrigin, who types.MultiAddress, amount sc.U128) types.DispatchError { +func (c callForceFree[T]) forceFree(origin types.RawOrigin, who types.MultiAddress, amount sc.U128) error { if !origin.IsRootOrigin() { return types.NewDispatchErrorBadOrigin() } @@ -123,10 +123,8 @@ func (c callForceFree[T]) forceFree(origin types.RawOrigin, who types.MultiAddre return types.NewDispatchErrorCannotLookup() } - // TODO: handle err - c.force(target, amount) - - return nil + _, err = c.force(target, amount) + return err } // forceFree frees funds, returning the amount that has not been freed. diff --git a/frame/balances/call_force_free_test.go b/frame/balances/call_force_free_test.go index d7c394ea..0726af9a 100644 --- a/frame/balances/call_force_free_test.go +++ b/frame/balances/call_force_free_test.go @@ -168,7 +168,7 @@ func Test_Call_ForceFree_Dispatch_InvalidOrigin(t *testing.T) { expected := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } @@ -184,7 +184,7 @@ func Test_Call_ForceFree_Dispatch_InvalidLookup(t *testing.T) { expected := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorCannotLookup(), + Err: primitives.NewDispatchErrorCannotLookup(), }, } target := setupCallForceFree() diff --git a/frame/balances/call_force_transfer.go b/frame/balances/call_force_transfer.go index 06441841..d0cf2056 100644 --- a/frame/balances/call_force_transfer.go +++ b/frame/balances/call_force_transfer.go @@ -102,7 +102,7 @@ func (c callForceTransfer[T]) Dispatch(origin types.RuntimeOrigin, args sc.Varyi return types.DispatchResultWithPostInfo[types.PostDispatchInfo]{ HasError: true, Err: types.DispatchErrorWithPostInfo[types.PostDispatchInfo]{ - Error: err, + Err: err, }, } } @@ -115,7 +115,7 @@ func (c callForceTransfer[T]) Dispatch(origin types.RuntimeOrigin, args sc.Varyi // forceTransfer transfers liquid free balance from `source` to `dest`. // Can only be called by ROOT. -func (c callForceTransfer[T]) forceTransfer(origin types.RawOrigin, source types.MultiAddress, dest types.MultiAddress, value sc.U128) types.DispatchError { +func (c callForceTransfer[T]) forceTransfer(origin types.RawOrigin, source types.MultiAddress, dest types.MultiAddress, value sc.U128) error { if !origin.IsRootOrigin() { return types.NewDispatchErrorBadOrigin() } diff --git a/frame/balances/call_force_transfer_test.go b/frame/balances/call_force_transfer_test.go index 9d7ec5dd..b2691838 100644 --- a/frame/balances/call_force_transfer_test.go +++ b/frame/balances/call_force_transfer_test.go @@ -141,7 +141,7 @@ func Test_Call_ForceTransfer_Dispatch_InvalidBadOrigin(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } @@ -159,7 +159,7 @@ func Test_Call_ForceTransfer_Dispatch_CannotLookup_Source(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorCannotLookup(), + Err: primitives.NewDispatchErrorCannotLookup(), }, } @@ -178,7 +178,7 @@ func Test_Call_ForceTransfer_Dispatch_CannotLookup_Dest(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorCannotLookup(), + Err: primitives.NewDispatchErrorCannotLookup(), }, } diff --git a/frame/balances/call_set_balance.go b/frame/balances/call_set_balance.go index b7d26809..715f739a 100644 --- a/frame/balances/call_set_balance.go +++ b/frame/balances/call_set_balance.go @@ -112,7 +112,7 @@ func (c callSetBalance[T]) Dispatch(origin types.RuntimeOrigin, args sc.VaryingD return types.DispatchResultWithPostInfo[types.PostDispatchInfo]{ HasError: true, Err: types.DispatchErrorWithPostInfo[types.PostDispatchInfo]{ - Error: err, + Err: err, }, } } @@ -127,7 +127,7 @@ func (c callSetBalance[T]) Dispatch(origin types.RuntimeOrigin, args sc.VaryingD // Changes free and reserve balance of `who`, // including the total issuance. // Can only be called by ROOT. -func (c callSetBalance[T]) setBalance(origin types.RawOrigin, who types.MultiAddress, newFree sc.U128, newReserved sc.U128) types.DispatchError { +func (c callSetBalance[T]) setBalance(origin types.RawOrigin, who types.MultiAddress, newFree sc.U128, newReserved sc.U128) error { if !origin.IsRootOrigin() { return types.NewDispatchErrorBadOrigin() } @@ -151,7 +151,7 @@ func (c callSetBalance[T]) setBalance(origin types.RawOrigin, who types.MultiAdd }, ) if result.HasError { - return result.Value.(types.DispatchError) + return result.Value.(error) } parsedResult := result.Value.(sc.VaryingData) @@ -159,23 +159,25 @@ func (c callSetBalance[T]) setBalance(origin types.RawOrigin, who types.MultiAdd oldReserved := parsedResult[1].(types.Balance) if newFree.Gt(oldFree) { - // TODO: handle err - newPositiveImbalance(newFree.Sub(oldFree), c.issuance). - Drop() + if err := newPositiveImbalance(newFree.Sub(oldFree), c.issuance).Drop(); err != nil { + return err + } + } else if newFree.Lt(oldFree) { - // TODO: handle err - newNegativeImbalance(oldFree.Sub(newFree), c.issuance). - Drop() + if err := newNegativeImbalance(oldFree.Sub(newFree), c.issuance).Drop(); err != nil { + return err + } } if newReserved.Gt(oldReserved) { - // TODO: handle err - newPositiveImbalance(newReserved.Sub(oldReserved), c.issuance). - Drop() + if err := newPositiveImbalance(newReserved.Sub(oldReserved), c.issuance).Drop(); err != nil { + return err + } } else if newReserved.Lt(oldReserved) { - // TODO: handle err - newNegativeImbalance(oldReserved.Sub(newReserved), c.issuance). - Drop() + if err := newNegativeImbalance(oldReserved.Sub(newReserved), c.issuance).Drop(); err != nil { + return err + } + } whoAccountId, errAccId := who.AsAccountId() diff --git a/frame/balances/call_set_balance_test.go b/frame/balances/call_set_balance_test.go index 1b36c4f5..2f944dd6 100644 --- a/frame/balances/call_set_balance_test.go +++ b/frame/balances/call_set_balance_test.go @@ -154,7 +154,7 @@ func Test_Call_SetBalance_Dispatch_BadOrigin(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } @@ -174,7 +174,7 @@ func Test_Call_SetBalance_Dispatch_CannotLookup(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorCannotLookup(), + Err: primitives.NewDispatchErrorCannotLookup(), }, } @@ -215,7 +215,7 @@ func Test_Call_SetBalance_setBalance_Success(t *testing.T) { result := target.setBalance(primitives.NewRawOriginRoot(), targetAddress, newFree, newReserved) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) mockMutator.AssertCalled(t, "tryMutateAccount", targetAddressAccId, @@ -254,7 +254,7 @@ func Test_Call_SetBalance_setBalance_Success_LessThanExistentialDeposit(t *testi result := target.setBalance(primitives.NewRawOriginRoot(), targetAddress, newFree, newReserved) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) mockStorageTotalIssuance.AssertNotCalled(t, "Get") mockStorageTotalIssuance.AssertNotCalled(t, "Put", mock.Anything) mockMutator.AssertCalled(t, @@ -292,7 +292,7 @@ func Test_Call_SetBalance_setBalance_Success_NegativeImbalance(t *testing.T) { result := target.setBalance(primitives.NewRawOriginRoot(), targetAddress, newFree, newReserved) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) mockMutator.AssertCalled(t, "tryMutateAccount", targetAddressAccId, diff --git a/frame/balances/call_transfer.go b/frame/balances/call_transfer.go index 5f127d55..88a197e8 100644 --- a/frame/balances/call_transfer.go +++ b/frame/balances/call_transfer.go @@ -99,7 +99,7 @@ func (c callTransfer[T]) Dispatch(origin types.RuntimeOrigin, args sc.VaryingDat return types.DispatchResultWithPostInfo[types.PostDispatchInfo]{ HasError: true, Err: types.DispatchErrorWithPostInfo[types.PostDispatchInfo]{ - Error: err, + Err: err, }, } } @@ -129,7 +129,7 @@ func newTransfer(moduleId sc.U8, storedMap primitives.StoredMap, constants *cons // transfer transfers liquid free balance from `source` to `dest`. // Increases the free balance of `dest` and decreases the free balance of `origin` transactor. // Must be signed by the transactor. -func (t transfer) transfer(origin types.RawOrigin, dest types.MultiAddress, value sc.U128) types.DispatchError { +func (t transfer) transfer(origin types.RawOrigin, dest types.MultiAddress, value sc.U128) error { if !origin.IsSignedOrigin() { return types.NewDispatchErrorBadOrigin() } @@ -149,7 +149,7 @@ func (t transfer) transfer(origin types.RawOrigin, dest types.MultiAddress, valu // trans transfers `value` free balance from `from` to `to`. // Does not do anything if value is 0 or `from` and `to` are the same. -func (t transfer) trans(from types.AccountId[types.PublicKey], to types.AccountId[types.PublicKey], value sc.U128, existenceRequirement types.ExistenceRequirement) types.DispatchError { +func (t transfer) trans(from types.AccountId[types.PublicKey], to types.AccountId[types.PublicKey], value sc.U128, existenceRequirement types.ExistenceRequirement) error { if value.Eq(constants.Zero) || reflect.DeepEqual(from, to) { return nil } @@ -160,7 +160,7 @@ func (t transfer) trans(from types.AccountId[types.PublicKey], to types.AccountI }) }) if result.HasError { - return result.Value.(types.DispatchError) + return result.Value.(error) } t.storedMap.DepositEvent(newEventTransfer(t.moduleId, from, to, value)) @@ -181,7 +181,7 @@ func (t transfer) sanityChecks(from types.AccountId[types.PublicKey], fromAccoun HasError: true, Value: types.NewDispatchErrorModule(types.CustomModuleError{ Index: t.moduleId, - Error: sc.U32(ErrorInsufficientBalance), + Err: sc.U32(ErrorInsufficientBalance), Message: sc.NewOption[sc.Str](nil), }), } @@ -202,18 +202,23 @@ func (t transfer) sanityChecks(from types.AccountId[types.PublicKey], fromAccoun HasError: true, Value: types.NewDispatchErrorModule(types.CustomModuleError{ Index: t.moduleId, - Error: sc.U32(ErrorExistentialDeposit), + Err: sc.U32(ErrorExistentialDeposit), Message: sc.NewOption[sc.Str](nil), }), } } - e := t.accountMutator.ensureCanWithdraw(from, value, types.ReasonsAll, fromAccount.Free) - if e != nil { - return sc.Result[sc.Encodable]{ - HasError: true, - Value: e, + err = t.accountMutator.ensureCanWithdraw(from, value, types.ReasonsAll, fromAccount.Free) + if err != nil { + errRes := sc.Result[sc.Encodable]{HasError: true} + switch dispatchErr := err.(type) { + case primitives.DispatchError: + errRes.Value = dispatchErr + default: + errRes.Value = sc.Empty{} } + + return errRes } canDecProviders, err := t.storedMap.CanDecProviders(from) @@ -231,7 +236,7 @@ func (t transfer) sanityChecks(from types.AccountId[types.PublicKey], fromAccoun HasError: true, Value: types.NewDispatchErrorModule(types.CustomModuleError{ Index: t.moduleId, - Error: sc.U32(ErrorKeepAlive), + Err: sc.U32(ErrorKeepAlive), Message: sc.NewOption[sc.Str](nil), }), } diff --git a/frame/balances/call_transfer_all.go b/frame/balances/call_transfer_all.go index 6a1b3032..61a48b24 100644 --- a/frame/balances/call_transfer_all.go +++ b/frame/balances/call_transfer_all.go @@ -95,7 +95,7 @@ func (c callTransferAll[T]) Dispatch(origin types.RuntimeOrigin, args sc.Varying return types.DispatchResultWithPostInfo[types.PostDispatchInfo]{ HasError: true, Err: types.DispatchErrorWithPostInfo[types.PostDispatchInfo]{ - Error: err, + Err: err, }, } } @@ -112,7 +112,7 @@ func (c callTransferAll[T]) Dispatch(origin types.RuntimeOrigin, args sc.Varying // the funds the account has, causing the sender account to be killed (false), or // transfer everything except at least the existential deposit, which will guarantee to // keep the sender account alive (true). -func (c callTransferAll[T]) transferAll(origin types.RawOrigin, dest types.MultiAddress, keepAlive bool) types.DispatchError { +func (c callTransferAll[T]) transferAll(origin types.RawOrigin, dest types.MultiAddress, keepAlive bool) error { if !origin.IsSignedOrigin() { return types.NewDispatchErrorBadOrigin() } diff --git a/frame/balances/call_transfer_all_test.go b/frame/balances/call_transfer_all_test.go index a85b9a95..df646db8 100644 --- a/frame/balances/call_transfer_all_test.go +++ b/frame/balances/call_transfer_all_test.go @@ -153,7 +153,7 @@ func Test_Call_TransferAll_Dispatch_BadOrigin(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } @@ -174,7 +174,7 @@ func Test_Call_TransferAll_Dispatch_CannotLookup(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorCannotLookup(), + Err: primitives.NewDispatchErrorCannotLookup(), }, } diff --git a/frame/balances/call_transfer_keep_alive.go b/frame/balances/call_transfer_keep_alive.go index b66a2457..bcb5a127 100644 --- a/frame/balances/call_transfer_keep_alive.go +++ b/frame/balances/call_transfer_keep_alive.go @@ -96,7 +96,7 @@ func (c callTransferKeepAlive[T]) Dispatch(origin types.RuntimeOrigin, args sc.V return types.DispatchResultWithPostInfo[types.PostDispatchInfo]{ HasError: true, Err: types.DispatchErrorWithPostInfo[types.PostDispatchInfo]{ - Error: err, + Err: err, }, } } @@ -108,7 +108,7 @@ func (c callTransferKeepAlive[T]) Dispatch(origin types.RuntimeOrigin, args sc.V } // transferKeepAlive is similar to transfer, but includes a check that the origin transactor will not be "killed". -func (c callTransferKeepAlive[T]) transferKeepAlive(origin types.RawOrigin, dest types.MultiAddress, value sc.U128) types.DispatchError { +func (c callTransferKeepAlive[T]) transferKeepAlive(origin types.RawOrigin, dest types.MultiAddress, value sc.U128) error { if !origin.IsSignedOrigin() { return types.NewDispatchErrorBadOrigin() } diff --git a/frame/balances/call_transfer_keep_alive_test.go b/frame/balances/call_transfer_keep_alive_test.go index 3f280a89..4269c578 100644 --- a/frame/balances/call_transfer_keep_alive_test.go +++ b/frame/balances/call_transfer_keep_alive_test.go @@ -146,7 +146,7 @@ func Test_Call_TransferKeepAlive_Dispatch_BadOrigin(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } @@ -165,7 +165,7 @@ func Test_Call_TransferKeepAlive_Dispatch_CannotLookup(t *testing.T) { expect := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorCannotLookup(), + Err: primitives.NewDispatchErrorCannotLookup(), }, } diff --git a/frame/balances/call_transfer_test.go b/frame/balances/call_transfer_test.go index c7d71f17..089b0b01 100644 --- a/frame/balances/call_transfer_test.go +++ b/frame/balances/call_transfer_test.go @@ -132,7 +132,7 @@ func Test_Call_Transfer_Dispatch_BadOrigin(t *testing.T) { expected := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } @@ -146,7 +146,7 @@ func Test_Call_Transfer_Dispatch_CannotLookup(t *testing.T) { expected := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorCannotLookup(), + Err: primitives.NewDispatchErrorCannotLookup(), }, } @@ -181,7 +181,7 @@ func Test_transfer_Success(t *testing.T) { result := target.transfer(primitives.NewRawOriginSigned(fromAddressId), fromAddress, targetValue) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) } func Test_transfer_InvalidOrigin(t *testing.T) { @@ -225,7 +225,7 @@ func Test_transfer_trans_Success(t *testing.T) { result := target.trans(fromAddressId, toAddressId, targetValue, primitives.ExistenceRequirementKeepAlive) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) mockMutator.AssertCalled(t, "tryMutateAccountWithDust", toAddressId, @@ -248,7 +248,7 @@ func Test_transfer_trans_ZeroValue(t *testing.T) { result := target.trans(fromAddressId, toAddressId, sc.NewU128(0), primitives.ExistenceRequirementAllowDeath) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) mockMutator.AssertNotCalled(t, "tryMutateAccountWithDust", mock.Anything, mock.Anything) mockStoredMap.AssertNotCalled(t, "DepositEvent", mock.Anything) } @@ -261,7 +261,7 @@ func Test_transfer_trans_EqualFromTo(t *testing.T) { result := target.trans(fromAddressId, fromAddressId, targetValue, primitives.ExistenceRequirementAllowDeath) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) mockMutator.AssertNotCalled(t, "tryMutateAccountWithDust", mock.Anything, mock.Anything) mockStoredMap.AssertNotCalled(t, "DepositEvent", mock.Anything) } @@ -304,7 +304,7 @@ func Test_transfer_sanityChecks_Success(t *testing.T) { targetAddressId, err := targetAddress.AsAccountId() assert.Nil(t, err) - mockMutator.On("ensureCanWithdraw", targetAddressId, targetValue, primitives.ReasonsAll, sc.NewU128(0)).Return(sc.VaryingData(nil)) + mockMutator.On("ensureCanWithdraw", targetAddressId, targetValue, primitives.ReasonsAll, sc.NewU128(0)).Return(nil) mockStoredMap.On("CanDecProviders", targetAddressId).Return(true, nil) result := target.sanityChecks(targetAddressId, fromAccountData, toAccountData, targetValue, primitives.ExistenceRequirementAllowDeath) @@ -322,7 +322,7 @@ func Test_transfer_sanityChecks_InsufficientBalance(t *testing.T) { HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: moduleId, - Error: sc.U32(ErrorInsufficientBalance), + Err: sc.U32(ErrorInsufficientBalance), Message: sc.NewOption[sc.Str](nil), }), } @@ -365,7 +365,7 @@ func Test_transfer_sanityChecks_ExistentialDeposit(t *testing.T) { HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: moduleId, - Error: sc.U32(ErrorExistentialDeposit), + Err: sc.U32(ErrorExistentialDeposit), Message: sc.NewOption[sc.Str](nil), }), } @@ -410,7 +410,7 @@ func Test_transfer_sanityChecks_KeepAlive(t *testing.T) { HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: moduleId, - Error: sc.U32(ErrorKeepAlive), + Err: sc.U32(ErrorKeepAlive), Message: sc.NewOption[sc.Str](nil), }), } @@ -418,7 +418,7 @@ func Test_transfer_sanityChecks_KeepAlive(t *testing.T) { targetAddressId, err := targetAddress.AsAccountId() assert.Nil(t, err) - mockMutator.On("ensureCanWithdraw", targetAddressId, targetValue, primitives.ReasonsAll, sc.NewU128(0)).Return(sc.VaryingData(nil)) + mockMutator.On("ensureCanWithdraw", targetAddressId, targetValue, primitives.ReasonsAll, sc.NewU128(0)).Return(nil) mockStoredMap.On("CanDecProviders", targetAddressId).Return(false, nil) result := target.sanityChecks(targetAddressId, fromAccountData, toAccountData, targetValue, primitives.ExistenceRequirementAllowDeath) diff --git a/frame/balances/mock_transfer_test.go b/frame/balances/mock_transfer_test.go index 87efc58e..b2d64ec6 100644 --- a/frame/balances/mock_transfer_test.go +++ b/frame/balances/mock_transfer_test.go @@ -10,10 +10,10 @@ type mockAccountMutator struct { mock.Mock } -func (m *mockAccountMutator) ensureCanWithdraw(who types.AccountId[types.PublicKey], amount sc.U128, reasons types.Reasons, newBalance sc.U128) types.DispatchError { +func (m *mockAccountMutator) ensureCanWithdraw(who types.AccountId[types.PublicKey], amount sc.U128, reasons types.Reasons, newBalance sc.U128) error { args := m.Called(who, amount, reasons, newBalance) - - return args[0].(types.DispatchError) + err, _ := args[0].(error) + return err } func (m *mockAccountMutator) tryMutateAccountWithDust(who types.AccountId[types.PublicKey], f func(who *types.AccountData, bool bool) sc.Result[sc.Encodable]) sc.Result[sc.Encodable] { diff --git a/frame/balances/module.go b/frame/balances/module.go index 471b900d..47e7520d 100644 --- a/frame/balances/module.go +++ b/frame/balances/module.go @@ -69,19 +69,17 @@ func (m Module) Functions() map[sc.U8]primitives.Call { return m.functions } -func (m Module) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m Module) PreDispatch(_ primitives.Call) (sc.Empty, error) { return sc.Empty{}, nil } -func (m Module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - unknownTransactionNoUnsignedValidator, _ := primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - return primitives.ValidTransaction{}, unknownTransactionNoUnsignedValidator +func (m Module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, error) { + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) } // DepositIntoExisting deposits `value` into the free balance of an existing target account `who`. // If `value` is 0, it does nothing. -func (m Module) DepositIntoExisting(who primitives.AccountId[primitives.PublicKey], value sc.U128) (primitives.Balance, primitives.DispatchError) { +func (m Module) DepositIntoExisting(who primitives.AccountId[primitives.PublicKey], value sc.U128) (primitives.Balance, error) { if value.Eq(constants.Zero) { return sc.NewU128(0), nil } @@ -94,7 +92,7 @@ func (m Module) DepositIntoExisting(who primitives.AccountId[primitives.PublicKe ) if result.HasError { - return sc.NewU128(0), result.Value.(primitives.DispatchError) + return sc.NewU128(0), result.Value.(error) } return result.Value.(primitives.Balance), nil @@ -102,7 +100,7 @@ func (m Module) DepositIntoExisting(who primitives.AccountId[primitives.PublicKe // Withdraw withdraws `value` free balance from `who`, respecting existence requirements. // Does not do anything if value is 0. -func (m Module) Withdraw(who primitives.AccountId[primitives.PublicKey], value sc.U128, reasons sc.U8, liveness primitives.ExistenceRequirement) (primitives.Balance, primitives.DispatchError) { +func (m Module) Withdraw(who primitives.AccountId[primitives.PublicKey], value sc.U128, reasons sc.U8, liveness primitives.ExistenceRequirement) (primitives.Balance, error) { if value.Eq(constants.Zero) { return sc.NewU128(0), nil } @@ -119,7 +117,7 @@ func (m Module) Withdraw(who primitives.AccountId[primitives.PublicKey], value s } // ensureCanWithdraw checks that an account can withdraw from their balance given any existing withdraw restrictions. -func (m Module) ensureCanWithdraw(who primitives.AccountId[primitives.PublicKey], amount sc.U128, reasons primitives.Reasons, newBalance sc.U128) primitives.DispatchError { +func (m Module) ensureCanWithdraw(who primitives.AccountId[primitives.PublicKey], amount sc.U128, reasons primitives.Reasons, newBalance sc.U128) error { if amount.Eq(constants.Zero) { return nil } @@ -132,7 +130,7 @@ func (m Module) ensureCanWithdraw(who primitives.AccountId[primitives.PublicKey] if minBalance.Gt(newBalance) { return primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: m.Index, - Error: sc.U32(ErrorLiquidityRestrictions), + Err: sc.U32(ErrorLiquidityRestrictions), Message: sc.NewOption[sc.Str](nil), }) } @@ -242,7 +240,7 @@ func (m Module) withdraw(who primitives.AccountId[primitives.PublicKey], value s HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: m.Index, - Error: sc.U32(ErrorInsufficientBalance), + Err: sc.U32(ErrorInsufficientBalance), Message: sc.NewOption[sc.Str](nil), }), } @@ -258,17 +256,17 @@ func (m Module) withdraw(who primitives.AccountId[primitives.PublicKey], value s HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: m.Index, - Error: sc.U32(ErrorKeepAlive), + Err: sc.U32(ErrorKeepAlive), Message: sc.NewOption[sc.Str](nil), }), } } - e := m.ensureCanWithdraw(who, value, primitives.Reasons(reasons), newFreeAccount) - if e != nil { + err = m.ensureCanWithdraw(who, value, primitives.Reasons(reasons), newFreeAccount) + if err != nil { return sc.Result[sc.Encodable]{ HasError: true, - Value: e, + Value: err.(primitives.DispatchError), // todo } } @@ -287,7 +285,7 @@ func (m Module) deposit(who primitives.AccountId[primitives.PublicKey], account HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: m.Index, - Error: sc.U32(ErrorDeadAccount), + Err: sc.U32(ErrorDeadAccount), Message: sc.NewOption[sc.Str](nil), }), } diff --git a/frame/balances/module_test.go b/frame/balances/module_test.go index 46f7a541..279fb7ef 100644 --- a/frame/balances/module_test.go +++ b/frame/balances/module_test.go @@ -13,7 +13,7 @@ import ( ) var ( - unknownTransactionNoUnsignedValidator, _ = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) + unknownTransactionNoUnsignedValidator = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) ) var ( @@ -178,7 +178,7 @@ func Test_Module_ensureCanWithdraw_Success(t *testing.T) { result := target.ensureCanWithdraw(fromAddressId, targetValue, primitives.ReasonsFee, sc.NewU128(5)) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) mockStoredMap.AssertCalled(t, "Get", fromAddressId) } @@ -190,7 +190,7 @@ func Test_Module_ensureCanWithdraw_ZeroAmount(t *testing.T) { result := target.ensureCanWithdraw(fromAddressId, sc.NewU128(0), primitives.ReasonsFee, sc.NewU128(5)) - assert.Equal(t, sc.VaryingData(nil), result) + assert.Nil(t, result) mockStoredMap.AssertNotCalled(t, "Get", fromAddressId) } @@ -198,7 +198,7 @@ func Test_Module_ensureCanWithdraw_LiquidityRestrictions(t *testing.T) { target := setupModule() expected := primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: moduleId, - Error: sc.U32(ErrorLiquidityRestrictions), + Err: sc.U32(ErrorLiquidityRestrictions), Message: sc.NewOption[sc.Str](nil), }) frozenAccountInfo := primitives.AccountInfo{ @@ -452,7 +452,7 @@ func Test_Module_withdraw_InsufficientBalance(t *testing.T) { HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: moduleId, - Error: sc.U32(ErrorInsufficientBalance), + Err: sc.U32(ErrorInsufficientBalance), Message: sc.NewOption[sc.Str](nil), }), } @@ -475,7 +475,7 @@ func Test_Module_withdraw_KeepAlive(t *testing.T) { HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: moduleId, - Error: sc.U32(ErrorKeepAlive), + Err: sc.U32(ErrorKeepAlive), Message: sc.NewOption[sc.Str](nil), }), } @@ -497,7 +497,7 @@ func Test_Module_withdraw_CannotWithdraw(t *testing.T) { HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: moduleId, - Error: sc.U32(ErrorLiquidityRestrictions), + Err: sc.U32(ErrorLiquidityRestrictions), Message: sc.NewOption[sc.Str](nil), }), } @@ -547,7 +547,7 @@ func Test_Module_deposit_DeadAccount(t *testing.T) { HasError: true, Value: primitives.NewDispatchErrorModule(primitives.CustomModuleError{ Index: moduleId, - Error: sc.U32(ErrorDeadAccount), + Err: sc.U32(ErrorDeadAccount), Message: sc.NewOption[sc.Str](nil), }), } diff --git a/frame/balances/types.go b/frame/balances/types.go index 8b0a270c..4ec69848 100644 --- a/frame/balances/types.go +++ b/frame/balances/types.go @@ -9,7 +9,7 @@ import ( ) type accountMutator interface { - ensureCanWithdraw(who types.AccountId[types.PublicKey], amount sc.U128, reasons types.Reasons, newBalance sc.U128) types.DispatchError + ensureCanWithdraw(who types.AccountId[types.PublicKey], amount sc.U128, reasons types.Reasons, newBalance sc.U128) error tryMutateAccountWithDust(who types.AccountId[types.PublicKey], f func(who *types.AccountData, bool bool) sc.Result[sc.Encodable]) sc.Result[sc.Encodable] tryMutateAccount(who types.AccountId[types.PublicKey], f func(who *types.AccountData, bool bool) sc.Result[sc.Encodable]) sc.Result[sc.Encodable] } diff --git a/frame/executive/executive.go b/frame/executive/executive.go index 74c70732..f017facd 100644 --- a/frame/executive/executive.go +++ b/frame/executive/executive.go @@ -16,9 +16,9 @@ import ( type Module interface { InitializeBlock(header primitives.Header) error ExecuteBlock(block primitives.Block) error - ApplyExtrinsic(uxt primitives.UncheckedExtrinsic) (primitives.DispatchOutcome, primitives.TransactionValidityError) + ApplyExtrinsic(uxt primitives.UncheckedExtrinsic) (primitives.DispatchOutcome, error) FinalizeBlock() (primitives.Header, error) - ValidateTransaction(source primitives.TransactionSource, uxt primitives.UncheckedExtrinsic, blockHash primitives.Blake2bHash) (primitives.ValidTransaction, primitives.TransactionValidityError) + ValidateTransaction(source primitives.TransactionSource, uxt primitives.UncheckedExtrinsic, blockHash primitives.Blake2bHash) (primitives.ValidTransaction, error) OffchainWorker(header primitives.Header) error } @@ -99,7 +99,7 @@ func (m module) ExecuteBlock(block primitives.Block) error { // // This doesn't attempt to validate anything regarding the block, but it builds a list of uxt // hashes. -func (m module) ApplyExtrinsic(uxt primitives.UncheckedExtrinsic) (primitives.DispatchOutcome, primitives.TransactionValidityError) { +func (m module) ApplyExtrinsic(uxt primitives.UncheckedExtrinsic) (primitives.DispatchOutcome, error) { encoded := uxt.Bytes() encodedLen := sc.ToCompact(len(encoded)) @@ -133,9 +133,7 @@ func (m module) ApplyExtrinsic(uxt primitives.UncheckedExtrinsic) (primitives.Di // The entire block should be discarded if an inherent fails to apply. Otherwise // it may open an attack vector. if res.HasError && isMandatoryDispatch(dispatchInfo) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionBadMandatory, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadMandatory()) - return primitives.DispatchOutcome{}, invalidTransactionBadMandatory + return primitives.DispatchOutcome{}, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadMandatory()) } noteErr := m.system.NoteAppliedExtrinsic(&res, dispatchInfo) @@ -144,14 +142,10 @@ func (m module) ApplyExtrinsic(uxt primitives.UncheckedExtrinsic) (primitives.Di } if res.HasError { - // TODO https://github.com/LimeChain/gosemble/issues/271 - dispatchOutcome, _ := primitives.NewDispatchOutcome(res.Err.Error) - return dispatchOutcome, nil + return primitives.NewDispatchOutcome(res.Err.Err.(primitives.DispatchError)) + } else { + return primitives.NewDispatchOutcome(nil) } - - // TODO https://github.com/LimeChain/gosemble/issues/271 - dispatchOutcome, _ := primitives.NewDispatchOutcome(nil) - return dispatchOutcome, nil } func (m module) FinalizeBlock() (primitives.Header, error) { @@ -178,13 +172,11 @@ func (m module) FinalizeBlock() (primitives.Header, error) { // not. // // Changes made to storage should be discarded. -func (m module) ValidateTransaction(source primitives.TransactionSource, uxt primitives.UncheckedExtrinsic, blockHash primitives.Blake2bHash) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (m module) ValidateTransaction(source primitives.TransactionSource, uxt primitives.UncheckedExtrinsic, blockHash primitives.Blake2bHash) (primitives.ValidTransaction, error) { log.Trace("validate_transaction") currentBlockNumber, err := m.system.StorageBlockNumber() if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return primitives.ValidTransaction{}, transactionValidityError + return primitives.ValidTransaction{}, err } m.system.Initialize(currentBlockNumber+1, blockHash, primitives.Digest{}) @@ -200,11 +192,8 @@ func (m module) ValidateTransaction(source primitives.TransactionSource, uxt pri log.Trace("dispatch_info") dispatchInfo := primitives.GetDispatchInfo(checked.Function()) - if isMandatoryDispatch(dispatchInfo) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionMandatoryValidation, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionMandatoryValidation()) - return primitives.ValidTransaction{}, invalidTransactionMandatoryValidation + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionMandatoryValidation()) } log.Trace("validate") @@ -261,7 +250,7 @@ func (m module) executeExtrinsicsWithBookKeeping(block primitives.Block) { for _, ext := range block.Extrinsics() { _, err := m.ApplyExtrinsic(ext) if err != nil { - log.Critical(string(err[0].Bytes())) + log.Critical(err.Error()) } } diff --git a/frame/executive/executive_test.go b/frame/executive/executive_test.go index 19ccbf0c..752bc3c1 100644 --- a/frame/executive/executive_test.go +++ b/frame/executive/executive_test.go @@ -59,7 +59,7 @@ var ( dispatchResultWithPostInfo = &primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } @@ -89,21 +89,19 @@ var ( ) var ( - transactionValidityError primitives.TransactionValidityError - - unknownTransactionCannotLookupError, _ = primitives.NewTransactionValidityError( + unknownTransactionCannotLookupError = primitives.NewTransactionValidityError( primitives.NewUnknownTransactionCannotLookup(), ) - invalidTransactionExhaustsResourcesError, _ = primitives.NewTransactionValidityError( + invalidTransactionExhaustsResourcesError = primitives.NewTransactionValidityError( primitives.NewInvalidTransactionExhaustsResources(), ) - invalidTransactionBadMandatory, _ = primitives.NewTransactionValidityError( + invalidTransactionBadMandatory = primitives.NewTransactionValidityError( primitives.NewInvalidTransactionBadMandatory(), ) - invalidTransactionMandatoryValidation, _ = primitives.NewTransactionValidityError( + invalidTransactionMandatoryValidation = primitives.NewTransactionValidityError( primitives.NewInvalidTransactionMandatoryValidation(), ) @@ -388,16 +386,16 @@ func Test_Executive_ApplyExtrinsic_Success(t *testing.T) { mockCall.On("ClassifyDispatch", baseWeight).Return(dispatchInfo.Class) mockCall.On("PaysFee", baseWeight).Return(dispatchInfo.PaysFee) mockCheckedExtrinsic.On("Apply", unsignedValidator, &dispatchInfo, encodedExtrinsicLen). - Return(*dispatchResultWithPostInfo, transactionValidityError) + Return(*dispatchResultWithPostInfo, nil) mockSystemModule.On("NoteAppliedExtrinsic", dispatchResultWithPostInfo, dispatchInfo) outcome, err := target.ApplyExtrinsic(mockUncheckedExtrinsic) mockSystemModule.AssertCalled(t, "NoteExtrinsic", mockUncheckedExtrinsic.Bytes()) mockSystemModule.AssertCalled(t, "NoteAppliedExtrinsic", dispatchResultWithPostInfo, dispatchInfo) - dispatchOutcomeWithPostInfo, _ := primitives.NewDispatchOutcome(dispatchResultWithPostInfo.Err.Error) + dispatchOutcomeWithPostInfo, _ := primitives.NewDispatchOutcome(dispatchResultWithPostInfo.Err.Err.(primitives.DispatchError)) assert.Equal(t, dispatchOutcomeWithPostInfo, outcome) - assert.Equal(t, transactionValidityError, err) + assert.NoError(t, err) } func Test_Executive_FinalizeBlock(t *testing.T) { @@ -493,7 +491,7 @@ func Test_Executive_ValidateTransaction(t *testing.T) { mockSystemModule.On("StorageBlockNumber").Return(blockNumber, nil) mockSystemModule.On("Initialize", blockNumber+1, header.ParentHash, defaultDigest) mockUncheckedExtrinsic.On("Bytes").Return(encodedExtrinsic) - mockUncheckedExtrinsic.On("Check").Return(mockCheckedExtrinsic, transactionValidityError) + mockUncheckedExtrinsic.On("Check").Return(mockCheckedExtrinsic, nil) mockCheckedExtrinsic.On("Function").Return(mockCall) mockCall.On("BaseWeight").Return(baseWeight) mockCall.On("WeighData", baseWeight).Return(dispatchInfo.Weight) @@ -515,7 +513,7 @@ func Test_Executive_ValidateTransaction(t *testing.T) { mockCall.AssertCalled(t, "PaysFee", baseWeight) mockCheckedExtrinsic.AssertCalled(t, "Validate", unsignedValidator, txSource, &dispatchInfo, encodedExtrinsicLen) assert.Equal(t, defaultValidTransaction, outcome) - assert.Equal(t, transactionValidityError, err) + assert.Nil(t, err) } func Test_Executive_OffchainWorker(t *testing.T) { diff --git a/frame/grandpa/module.go b/frame/grandpa/module.go index d7454d26..962dfe09 100644 --- a/frame/grandpa/module.go +++ b/frame/grandpa/module.go @@ -72,14 +72,12 @@ func (m Module[T]) Functions() map[sc.U8]primitives.Call { return map[sc.U8]primitives.Call{} } -func (m Module[T]) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m Module[T]) PreDispatch(_ primitives.Call) (sc.Empty, error) { return sc.Empty{}, nil } -func (m Module[T]) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - unknownTransactionNoUnsignedValidator, _ := primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - return primitives.ValidTransaction{}, unknownTransactionNoUnsignedValidator +func (m Module[T]) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, error) { + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) } func (m Module[T]) Authorities() (sc.Sequence[primitives.Authority], error) { diff --git a/frame/grandpa/module_test.go b/frame/grandpa/module_test.go index 955db0c5..8a4388f7 100644 --- a/frame/grandpa/module_test.go +++ b/frame/grandpa/module_test.go @@ -15,7 +15,7 @@ import ( const moduleId = sc.U8(3) var ( - unknownTransactionNoUnsignedValidator, _ = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) + unknownTransactionNoUnsignedValidator = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) ) var ( diff --git a/frame/support/transactional.go b/frame/support/transactional.go index a9447ac0..5fb7e93e 100644 --- a/frame/support/transactional.go +++ b/frame/support/transactional.go @@ -22,42 +22,42 @@ var ( errInvalidTransactionOutcome = "invalid transaction outcome" ) -type Transactional[T sc.Encodable, E types.DispatchError] interface { - WithStorageLayer(fn func() (T, types.DispatchError)) (T, E) +type Transactional[T sc.Encodable] interface { + WithStorageLayer(fn func() (T, error)) (T, error) } -type transactional[T sc.Encodable, E types.DispatchError] struct { +type transactional[T sc.Encodable] struct { storage StorageValue[sc.U32] transactionBroker io.TransactionBroker } -func NewTransactional[T sc.Encodable, E types.DispatchError]() Transactional[T, E] { +func NewTransactional[T sc.Encodable]() Transactional[T] { storageVal := NewSimpleStorageValue(keyTransactionLevel, sc.DecodeU32) - return transactional[T, E]{ + return transactional[T]{ storage: storageVal, transactionBroker: io.NewTransactionBroker(), } } // GetTransactionLevel returns the current number of nested transactional layers. -func (t transactional[T, E]) GetTransactionLevel() (Layer, error) { +func (t transactional[T]) GetTransactionLevel() (Layer, error) { return t.storage.Get() } // SetTransactionLevel Set the current number of nested transactional layers. -func (t transactional[T, E]) SetTransactionLevel(level Layer) { +func (t transactional[T]) SetTransactionLevel(level Layer) { t.storage.Put(level) } // KillTransactionLevel kill the transactional layers storage. -func (t transactional[T, E]) KillTransactionLevel() { +func (t transactional[T]) KillTransactionLevel() { t.storage.Clear() } // IncTransactionLevel increments the transaction level. Returns an error if levels go past the limit. // // Returns a guard that when dropped decrements the transaction level automatically. -func (t transactional[T, E]) IncTransactionLevel() error { +func (t transactional[T]) IncTransactionLevel() error { existingLevels, err := t.GetTransactionLevel() if err != nil { return err @@ -70,7 +70,7 @@ func (t transactional[T, E]) IncTransactionLevel() error { return nil } -func (t transactional[T, E]) DecTransactionLevel() error { +func (t transactional[T]) DecTransactionLevel() error { existingLevels, err := t.GetTransactionLevel() if err != nil { return err @@ -96,19 +96,17 @@ func (t transactional[T, E]) DecTransactionLevel() error { // error. // // Commits happen to the parent transaction. -func (t transactional[T, E]) WithTransaction(fn func() types.TransactionOutcome) (ok T, err E) { +func (t transactional[T]) WithTransaction(fn func() types.TransactionOutcome) (T, error) { // This needs to happen before `start_transaction` below. // Otherwise we may rollback the increase, then decrease as the guard goes out of scope // and then end in some bad state. - e := t.IncTransactionLevel() - if e != nil { - return ok, E(types.NewDispatchErrorTransactional(types.NewTransactionalErrorLimitReached())) + if err := t.IncTransactionLevel(); err != nil { + return *new(T), types.NewDispatchErrorTransactional(types.NewTransactionalErrorLimitReached()) } t.transactionBroker.Start() res := fn() - switch res[0] { case types.TransactionOutcomeCommit: t.transactionBroker.Commit() @@ -117,10 +115,10 @@ func (t transactional[T, E]) WithTransaction(fn func() types.TransactionOutcome) case types.TransactionOutcomeRollback: t.transactionBroker.Rollback() t.DecTransactionLevel() - return ok, res[1].(E) + return *new(T), res[1].(error) default: log.Critical(errInvalidTransactionOutcome) - return ok, nil + return *new(T), nil } } @@ -129,15 +127,17 @@ func (t transactional[T, E]) WithTransaction(fn func() types.TransactionOutcome) // This is the same as `with_transaction`, but assuming that any function returning an `Err` should // rollback, and any function returning `Ok` should commit. This provides a cleaner API to the // developer who wants this behavior. -func (t transactional[T, E]) WithStorageLayer(fn func() (T, types.DispatchError)) (T, E) { +func (t transactional[T]) WithStorageLayer(fn func() (T, error)) (T, error) { return t.WithTransaction( func() types.TransactionOutcome { ok, err := fn() - - if err != nil { - return types.NewTransactionOutcomeRollback(err) - } else { + switch dispatchErr := err.(type) { + case nil: return types.NewTransactionOutcomeCommit(ok) + case types.DispatchError: + return types.NewTransactionOutcomeRollback(dispatchErr) + default: + return types.NewTransactionOutcomeRollback(sc.Empty{}) } }, ) diff --git a/frame/support/transactional_test.go b/frame/support/transactional_test.go index 092cc4d2..b4e1c86b 100644 --- a/frame/support/transactional_test.go +++ b/frame/support/transactional_test.go @@ -193,6 +193,7 @@ func Test_Transactional_WithTransaction_InvalidTransactionOutcome(t *testing.T) mockStorageValue.AssertCalled(t, "Put", transactionLevel+1) mockTransactionBroker.AssertCalled(t, "Start") mockTransactionBroker.AssertNotCalled(t, "Rollback") + mockTransactionBroker.AssertNotCalled(t, "Commit") } func Test_Transactional_WithStorageLayer_Commit(t *testing.T) { @@ -206,7 +207,7 @@ func Test_Transactional_WithStorageLayer_Commit(t *testing.T) { mockStorageValue.On("Get").Return(transactionLevel+1, nil).Once() mockStorageValue.On("Put", transactionLevel).Once() - res, err := target.WithStorageLayer(func() (sc.U32, primitives.DispatchError) { + res, err := target.WithStorageLayer(func() (sc.U32, error) { return expect, nil }) @@ -231,12 +232,13 @@ func Test_Transactional_WithStorageLayer_Rollback(t *testing.T) { mockStorageValue.On("Get").Return(transactionLevel+1, nil).Once() mockStorageValue.On("Put", transactionLevel).Once() - res, err := target.WithStorageLayer(func() (sc.U32, primitives.DispatchError) { + res, err := target.WithStorageLayer(func() (sc.U32, error) { return sc.U32(0), expect }) assert.Equal(t, sc.U32(0), res) - assert.Equal(t, expect, err) + dispatchErr, _ := err.(primitives.DispatchError) + assert.Equal(t, expect, dispatchErr) mockStorageValue.AssertNumberOfCalls(t, "Get", 2) mockStorageValue.AssertNumberOfCalls(t, "Put", 2) @@ -246,11 +248,11 @@ func Test_Transactional_WithStorageLayer_Rollback(t *testing.T) { mockStorageValue.AssertCalled(t, "Put", transactionLevel) } -func setupTransactional() transactional[sc.U32, primitives.DispatchError] { +func setupTransactional() transactional[sc.U32] { mockStorageValue = new(mocks.StorageValue[sc.U32]) mockTransactionBroker = new(mocks.IoTransactionBroker) - target := NewTransactional[sc.U32, primitives.DispatchError]().(transactional[sc.U32, primitives.DispatchError]) + target := NewTransactional[sc.U32]().(transactional[sc.U32]) target.storage = mockStorageValue target.transactionBroker = mockTransactionBroker diff --git a/frame/system/call_remark.go b/frame/system/call_remark.go index c9c0e2e1..4ccea57b 100644 --- a/frame/system/call_remark.go +++ b/frame/system/call_remark.go @@ -96,7 +96,7 @@ func remark(origin primitives.RuntimeOrigin) primitives.DispatchResultWithPostIn return primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: err, + Err: err, }, } } @@ -111,7 +111,7 @@ func remark(origin primitives.RuntimeOrigin) primitives.DispatchResultWithPostIn // Returns an empty Option if the origin is `Root`. // Returns an Option with the signer if the origin is signed. // Returns a `BadOrigin` error if neither of the above. -func EnsureSignedOrRoot(origin primitives.RawOrigin) (sc.Option[primitives.AccountId[primitives.PublicKey]], primitives.DispatchError) { +func EnsureSignedOrRoot(origin primitives.RawOrigin) (sc.Option[primitives.AccountId[primitives.PublicKey]], error) { if origin.IsRootOrigin() { return sc.NewOption[primitives.AccountId[primitives.PublicKey]](nil), nil } else if origin.IsSignedOrigin() { diff --git a/frame/system/call_remark_test.go b/frame/system/call_remark_test.go index 3882bf4f..f2f3b1e5 100644 --- a/frame/system/call_remark_test.go +++ b/frame/system/call_remark_test.go @@ -154,7 +154,7 @@ func Test_Call_Remark_Dispatch_Fail(t *testing.T) { expected := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } diff --git a/frame/system/events.go b/frame/system/events.go index 35d184d2..eaf62bd4 100644 --- a/frame/system/events.go +++ b/frame/system/events.go @@ -70,9 +70,9 @@ func DecodeEvent[T types.PublicKey](moduleIndex sc.U8, buffer *bytes.Buffer) (ty } return newEventExtrinsicSuccess(moduleIndex, dispatchInfo), nil case EventExtrinsicFailed: - dispatchErr, err := types.DecodeDispatchError(buffer) - if err != nil { - return types.Event{}, err + dispatchErr, ok := types.DecodeDispatchError(buffer).(types.DispatchError) + if !ok { + return types.Event{}, dispatchErr } dispatchInfo, err := types.DecodeDispatchInfo(buffer) if err != nil { diff --git a/frame/system/extensions/check_genesis.go b/frame/system/extensions/check_genesis.go index 77e24a2f..60f45c97 100644 --- a/frame/system/extensions/check_genesis.go +++ b/frame/system/extensions/check_genesis.go @@ -27,36 +27,34 @@ func (cg CheckGenesis) Bytes() []byte { return sc.EncodedBytes(cg) } -func (cg CheckGenesis) AdditionalSigned() (primitives.AdditionalSigned, primitives.TransactionValidityError) { +func (cg CheckGenesis) AdditionalSigned() (primitives.AdditionalSigned, error) { hash, err := cg.module.StorageBlockHash(0) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return nil, transactionValidityError + return nil, err } return sc.NewVaryingData(primitives.H256(hash)), nil } -func (_ CheckGenesis) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (_ CheckGenesis) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (cg CheckGenesis) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (cg CheckGenesis) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (cg CheckGenesis) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, primitives.TransactionValidityError) { +func (cg CheckGenesis) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, error) { _, err := cg.Validate(who, call, info, length) return primitives.Pre{}, err } -func (cg CheckGenesis) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (cg CheckGenesis) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) error { _, err := cg.ValidateUnsigned(call, info, length) return err } -func (cg CheckGenesis) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) primitives.TransactionValidityError { +func (cg CheckGenesis) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) error { return nil } diff --git a/frame/system/extensions/check_mortality.go b/frame/system/extensions/check_mortality.go index e2ea6c59..0a7d569c 100644 --- a/frame/system/extensions/check_mortality.go +++ b/frame/system/extensions/check_mortality.go @@ -36,37 +36,29 @@ func (cm CheckMortality) Bytes() []byte { return sc.EncodedBytes(cm) } -func (cm CheckMortality) AdditionalSigned() (primitives.AdditionalSigned, primitives.TransactionValidityError) { +func (cm CheckMortality) AdditionalSigned() (primitives.AdditionalSigned, error) { current, err := cm.systemModule.StorageBlockNumber() if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return nil, transactionValidityError + return nil, err } n := cm.era.Birth(current) if !cm.systemModule.StorageBlockHashExists(n) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionAncientBirthBlock, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionAncientBirthBlock()) - return nil, invalidTransactionAncientBirthBlock + return nil, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionAncientBirthBlock()) } blockHash, err := cm.systemModule.StorageBlockHash(n) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return nil, transactionValidityError + return nil, err } hash, err := primitives.NewH256(blockHash.FixedSequence...) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return nil, transactionValidityError + return nil, err } return sc.NewVaryingData(hash), nil } -func (cm CheckMortality) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (cm CheckMortality) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, error) { currentBlockNum, err := cm.systemModule.StorageBlockNumber() if err != nil { log.Critical(err.Error()) @@ -80,21 +72,21 @@ func (cm CheckMortality) Validate(_who primitives.AccountId[primitives.PublicKey return ok, nil } -func (cm CheckMortality) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (cm CheckMortality) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (cm CheckMortality) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, primitives.TransactionValidityError) { +func (cm CheckMortality) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, error) { _, err := cm.Validate(who, call, info, length) return primitives.Pre{}, err } -func (cm CheckMortality) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (cm CheckMortality) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) error { _, err := cm.ValidateUnsigned(call, info, length) return err } -func (cm CheckMortality) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) primitives.TransactionValidityError { +func (cm CheckMortality) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) error { return nil } diff --git a/frame/system/extensions/check_mortality_test.go b/frame/system/extensions/check_mortality_test.go index 35ac7aa9..4b9a35d9 100644 --- a/frame/system/extensions/check_mortality_test.go +++ b/frame/system/extensions/check_mortality_test.go @@ -15,7 +15,7 @@ import ( ) var ( - invalidTransactionAncientBirthBlock, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionAncientBirthBlock()) + invalidTransactionAncientBirthBlock = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionAncientBirthBlock()) ) func Test_CheckMortality_Encode(t *testing.T) { diff --git a/frame/system/extensions/check_non_zero_sender.go b/frame/system/extensions/check_non_zero_sender.go index 68e1b2ad..1300b171 100644 --- a/frame/system/extensions/check_non_zero_sender.go +++ b/frame/system/extensions/check_non_zero_sender.go @@ -16,7 +16,7 @@ func NewCheckNonZeroAddress() primitives.SignedExtension { return &CheckNonZeroAddress{} } -func (c CheckNonZeroAddress) AdditionalSigned() (primitives.AdditionalSigned, primitives.TransactionValidityError) { +func (c CheckNonZeroAddress) AdditionalSigned() (primitives.AdditionalSigned, error) { return primitives.AdditionalSigned{}, nil } @@ -30,31 +30,29 @@ func (c CheckNonZeroAddress) Bytes() []byte { return sc.EncodedBytes(c) } -func (c CheckNonZeroAddress) Validate(who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (c CheckNonZeroAddress) Validate(who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, error) { if reflect.DeepEqual(who, constants.ZeroAddressAccountId) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionBadSigner, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadSigner()) - return primitives.ValidTransaction{}, invalidTransactionBadSigner + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadSigner()) } return primitives.DefaultValidTransaction(), nil } -func (c CheckNonZeroAddress) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (c CheckNonZeroAddress) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (c CheckNonZeroAddress) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, primitives.TransactionValidityError) { +func (c CheckNonZeroAddress) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, error) { _, err := c.Validate(who, call, info, length) return primitives.Pre{}, err } -func (c CheckNonZeroAddress) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (c CheckNonZeroAddress) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) error { _, err := c.ValidateUnsigned(call, info, length) return err } -func (c CheckNonZeroAddress) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) primitives.TransactionValidityError { +func (c CheckNonZeroAddress) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) error { return nil } diff --git a/frame/system/extensions/check_non_zero_sender_test.go b/frame/system/extensions/check_non_zero_sender_test.go index 5ad6ef84..e6114bb9 100644 --- a/frame/system/extensions/check_non_zero_sender_test.go +++ b/frame/system/extensions/check_non_zero_sender_test.go @@ -12,7 +12,7 @@ import ( ) var ( - invalidTransactionBadSigner, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadSigner()) + invalidTransactionBadSigner = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadSigner()) ) func Test_CheckNonZeroAddress_AdditionalSigned(t *testing.T) { diff --git a/frame/system/extensions/check_nonce.go b/frame/system/extensions/check_nonce.go index 79139f9e..bf54d350 100644 --- a/frame/system/extensions/check_nonce.go +++ b/frame/system/extensions/check_nonce.go @@ -36,22 +36,18 @@ func (cn CheckNonce) Bytes() []byte { return sc.EncodedBytes(cn) } -func (cn CheckNonce) AdditionalSigned() (primitives.AdditionalSigned, primitives.TransactionValidityError) { +func (cn CheckNonce) AdditionalSigned() (primitives.AdditionalSigned, error) { return sc.NewVaryingData(), nil } -func (cn CheckNonce) Validate(who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (cn CheckNonce) Validate(who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, error) { account, err := cn.systemModule.StorageAccount(who) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return primitives.ValidTransaction{}, transactionValidityError + return primitives.ValidTransaction{}, err } if cn.nonce < account.Nonce { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionStale, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) - return primitives.ValidTransaction{}, invalidTransactionStale + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) } encoded := who.Bytes() @@ -76,27 +72,24 @@ func (cn CheckNonce) Validate(who primitives.AccountId[primitives.PublicKey], _c }, nil } -func (cn CheckNonce) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (cn CheckNonce) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (cn CheckNonce) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, primitives.TransactionValidityError) { +func (cn CheckNonce) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, error) { account, err := cn.systemModule.StorageAccount(who) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return primitives.Pre{}, transactionValidityError + return primitives.Pre{}, err } if cn.nonce != account.Nonce { - var transactionValidityError primitives.TransactionValidityError + var txErr sc.Encodable if cn.nonce < account.Nonce { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) + txErr = primitives.NewInvalidTransactionStale() } else { - transactionValidityError, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionFuture()) + txErr = primitives.NewInvalidTransactionFuture() } - return primitives.Pre{}, transactionValidityError + return primitives.Pre{}, primitives.NewTransactionValidityError(txErr) } account.Nonce = account.Nonce + 1 @@ -105,12 +98,12 @@ func (cn CheckNonce) PreDispatch(who primitives.AccountId[primitives.PublicKey], return primitives.Pre{}, nil } -func (cn CheckNonce) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (cn CheckNonce) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) error { _, err := cn.ValidateUnsigned(call, info, length) return err } -func (cn CheckNonce) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) primitives.TransactionValidityError { +func (cn CheckNonce) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) error { return nil } diff --git a/frame/system/extensions/check_nonce_test.go b/frame/system/extensions/check_nonce_test.go index 19e48237..74151135 100644 --- a/frame/system/extensions/check_nonce_test.go +++ b/frame/system/extensions/check_nonce_test.go @@ -15,8 +15,8 @@ import ( ) var ( - invalidTransactionStale, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) - invalidTransactionFuture, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionFuture()) + invalidTransactionStale = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) + invalidTransactionFuture = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionFuture()) ) var ( diff --git a/frame/system/extensions/check_spec_version.go b/frame/system/extensions/check_spec_version.go index a67f5bfd..9421e711 100644 --- a/frame/system/extensions/check_spec_version.go +++ b/frame/system/extensions/check_spec_version.go @@ -27,29 +27,29 @@ func (csv CheckSpecVersion) Bytes() []byte { return sc.EncodedBytes(csv) } -func (csv CheckSpecVersion) AdditionalSigned() (primitives.AdditionalSigned, primitives.TransactionValidityError) { +func (csv CheckSpecVersion) AdditionalSigned() (primitives.AdditionalSigned, error) { return sc.NewVaryingData(csv.systemModule.Version().SpecVersion), nil } -func (_ CheckSpecVersion) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (_ CheckSpecVersion) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (csv CheckSpecVersion) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (csv CheckSpecVersion) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (csv CheckSpecVersion) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, primitives.TransactionValidityError) { +func (csv CheckSpecVersion) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, error) { _, err := csv.Validate(who, call, info, length) return primitives.Pre{}, err } -func (csv CheckSpecVersion) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (csv CheckSpecVersion) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) error { _, err := csv.ValidateUnsigned(call, info, length) return err } -func (csv CheckSpecVersion) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) primitives.TransactionValidityError { +func (csv CheckSpecVersion) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) error { return nil } diff --git a/frame/system/extensions/check_tx_version.go b/frame/system/extensions/check_tx_version.go index 6c656c73..2048cd0f 100644 --- a/frame/system/extensions/check_tx_version.go +++ b/frame/system/extensions/check_tx_version.go @@ -27,29 +27,29 @@ func (ctv CheckTxVersion) Bytes() []byte { return sc.EncodedBytes(ctv) } -func (ctv CheckTxVersion) AdditionalSigned() (primitives.AdditionalSigned, primitives.TransactionValidityError) { +func (ctv CheckTxVersion) AdditionalSigned() (primitives.AdditionalSigned, error) { return sc.NewVaryingData(ctv.systemModule.Version().TransactionVersion), nil } -func (_ CheckTxVersion) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (_ CheckTxVersion) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, _info *primitives.DispatchInfo, _length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (ctv CheckTxVersion) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (ctv CheckTxVersion) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (ctv CheckTxVersion) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, primitives.TransactionValidityError) { +func (ctv CheckTxVersion) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, error) { _, err := ctv.Validate(who, call, info, length) return primitives.Pre{}, err } -func (ctv CheckTxVersion) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (ctv CheckTxVersion) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) error { _, err := ctv.ValidateUnsigned(call, info, length) return err } -func (ctv CheckTxVersion) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) primitives.TransactionValidityError { +func (ctv CheckTxVersion) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) error { return nil } diff --git a/frame/system/extensions/check_weight.go b/frame/system/extensions/check_weight.go index 2421997f..b85bddb1 100644 --- a/frame/system/extensions/check_weight.go +++ b/frame/system/extensions/check_weight.go @@ -32,34 +32,32 @@ func (cw CheckWeight) Bytes() []byte { return sc.EncodedBytes(cw) } -func (cw CheckWeight) AdditionalSigned() (primitives.AdditionalSigned, primitives.TransactionValidityError) { +func (cw CheckWeight) AdditionalSigned() (primitives.AdditionalSigned, error) { return primitives.AdditionalSigned{}, nil } -func (cw CheckWeight) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (cw CheckWeight) Validate(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return cw.doValidate(info, length) } -func (cw CheckWeight) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (cw CheckWeight) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return cw.doValidate(info, length) } -func (cw CheckWeight) PreDispatch(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, primitives.TransactionValidityError) { +func (cw CheckWeight) PreDispatch(_who primitives.AccountId[primitives.PublicKey], _call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, error) { return primitives.Pre{}, cw.doPreDispatch(info, length) } -func (cw CheckWeight) PreDispatchUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (cw CheckWeight) PreDispatchUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) error { return cw.doPreDispatch(info, length) } -func (cw CheckWeight) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) primitives.TransactionValidityError { +func (cw CheckWeight) PostDispatch(_pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, _length sc.Compact, _result *primitives.DispatchResult) error { unspent := postInfo.CalcUnspent(info) if unspent.AnyGt(primitives.WeightZero()) { currentWeight, err := cw.systemModule.StorageBlockWeight() if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return transactionValidityError + return err } err = currentWeight.Reduce(unspent, info.Class) if err != nil { @@ -73,7 +71,7 @@ func (cw CheckWeight) PostDispatch(_pre sc.Option[primitives.Pre], info *primiti // Do the validate checks. This can be applied to both signed and unsigned. // // It only checks that the block weight and length limit will not exceed. -func (cw CheckWeight) doValidate(info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (cw CheckWeight) doValidate(info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { // ignore the next length. If they return `Ok`, then it is below the limit. _, err := cw.checkBlockLength(info, length) if err != nil { @@ -91,7 +89,7 @@ func (cw CheckWeight) doValidate(info *primitives.DispatchInfo, length sc.Compac return primitives.DefaultValidTransaction(), nil } -func (cw CheckWeight) doPreDispatch(info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (cw CheckWeight) doPreDispatch(info *primitives.DispatchInfo, length sc.Compact) error { nextLength, err := cw.checkBlockLength(info, length) if err != nil { return err @@ -116,22 +114,18 @@ func (cw CheckWeight) doPreDispatch(info *primitives.DispatchInfo, length sc.Com // Checks if the current extrinsic can fit into the block with respect to block length limits. // // Upon successes, it returns the new block length as a `Result`. -func (cw CheckWeight) checkBlockLength(info *primitives.DispatchInfo, length sc.Compact) (sc.U32, primitives.TransactionValidityError) { +func (cw CheckWeight) checkBlockLength(info *primitives.DispatchInfo, length sc.Compact) (sc.U32, error) { lengthLimit := cw.systemModule.BlockLength() currentLen, err := cw.systemModule.StorageAllExtrinsicsLen() if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return 0, transactionValidityError + return 0, err } addedLen := sc.U32(length.ToBigInt().Uint64()) nextLen := sc.SaturatingAddU32(currentLen, addedLen) if nextLen > maxLimit(lengthLimit, info) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionExhaustsResources, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) - return sc.U32(0), invalidTransactionExhaustsResources + return sc.U32(0), primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) } return nextLen, nil @@ -140,20 +134,18 @@ func (cw CheckWeight) checkBlockLength(info *primitives.DispatchInfo, length sc. // Checks if the current extrinsic can fit into the block with respect to block weight limits. // // Upon successes, it returns the new block weight as a `Result`. -func (cw CheckWeight) checkBlockWeight(info *primitives.DispatchInfo) (primitives.ConsumedWeight, primitives.TransactionValidityError) { +func (cw CheckWeight) checkBlockWeight(info *primitives.DispatchInfo) (primitives.ConsumedWeight, error) { maximumWeight := cw.systemModule.BlockWeights() allWeight, err := cw.systemModule.StorageBlockWeight() if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return primitives.ConsumedWeight{}, transactionValidityError + return primitives.ConsumedWeight{}, err } return cw.calculateConsumedWeight(maximumWeight, allWeight, info) } // Checks if the current extrinsic does not exceed the maximum weight a single extrinsic // with given `DispatchClass` can have. -func (cw CheckWeight) checkExtrinsicWeight(info *primitives.DispatchInfo) primitives.TransactionValidityError { +func (cw CheckWeight) checkExtrinsicWeight(info *primitives.DispatchInfo) error { dispatchClass, err := cw.systemModule.BlockWeights().Get(info.Class) if err != nil { log.Critical(err.Error()) @@ -163,16 +155,14 @@ func (cw CheckWeight) checkExtrinsicWeight(info *primitives.DispatchInfo) primit if max.HasValue { if info.Weight.AnyGt(max.Value) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionExhaustsResources, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) - return invalidTransactionExhaustsResources + return primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) } } return nil } -func (cw CheckWeight) calculateConsumedWeight(maximumWeight primitives.BlockWeights, allConsumedWeight primitives.ConsumedWeight, info *primitives.DispatchInfo) (primitives.ConsumedWeight, primitives.TransactionValidityError) { +func (cw CheckWeight) calculateConsumedWeight(maximumWeight primitives.BlockWeights, allConsumedWeight primitives.ConsumedWeight, info *primitives.DispatchInfo) (primitives.ConsumedWeight, error) { limitPerClass, err := maximumWeight.Get(info.Class) if err != nil { log.Critical(err.Error()) @@ -186,9 +176,7 @@ func (cw CheckWeight) calculateConsumedWeight(maximumWeight primitives.BlockWeig } else { err := allConsumedWeight.CheckedAccrue(extrinsicWeight, info.Class) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionExhaustsResources, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) - return primitives.ConsumedWeight{}, invalidTransactionExhaustsResources + return primitives.ConsumedWeight{}, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) } } @@ -201,9 +189,7 @@ func (cw CheckWeight) calculateConsumedWeight(maximumWeight primitives.BlockWeig if limitPerClass.MaxTotal.HasValue { max := limitPerClass.MaxTotal.Value if consumedPerClass.AnyGt(max) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionExhaustsResources, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) - return primitives.ConsumedWeight{}, invalidTransactionExhaustsResources + return primitives.ConsumedWeight{}, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) } } @@ -218,9 +204,7 @@ func (cw CheckWeight) calculateConsumedWeight(maximumWeight primitives.BlockWeig if limitPerClass.Reserved.HasValue { reserved := limitPerClass.Reserved.Value if consumedPerClass.AnyGt(reserved) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionExhaustsResources, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) - return primitives.ConsumedWeight{}, invalidTransactionExhaustsResources + return primitives.ConsumedWeight{}, primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) } } } diff --git a/frame/system/extensions/check_weight_test.go b/frame/system/extensions/check_weight_test.go index 6e347dff..6d1efddf 100644 --- a/frame/system/extensions/check_weight_test.go +++ b/frame/system/extensions/check_weight_test.go @@ -51,7 +51,7 @@ var ( ) var ( - invalidTransactionExhaustsResources, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) + invalidTransactionExhaustsResources = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) ) func Test_CheckWeight_AdditionalSigned(t *testing.T) { diff --git a/frame/system/module.go b/frame/system/module.go index c8758a8d..dbea1a4d 100644 --- a/frame/system/module.go +++ b/frame/system/module.go @@ -110,14 +110,12 @@ func (m module) Functions() map[sc.U8]primitives.Call { return m.functions } -func (m module) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m module) PreDispatch(_ primitives.Call) (sc.Empty, error) { return sc.Empty{}, nil } -func (m module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - unknownTransactionNoUnsignedValidator, _ := primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - return primitives.ValidTransaction{}, unknownTransactionNoUnsignedValidator +func (m module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, error) { + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) } func (m module) BlockHashCount() sc.U64 { @@ -274,7 +272,7 @@ func (m module) NoteAppliedExtrinsic(r *primitives.DispatchResultWithPostInfo[pr } log.Trace("Extrinsic failed at block(" + strconv.Itoa(int(blockNum)) + "): {}") - m.DepositEvent(newEventExtrinsicFailed(m.Index, r.Err.Error, info)) + m.DepositEvent(newEventExtrinsicFailed(m.Index, r.Err.Err.(primitives.DispatchError), info)) } else { m.DepositEvent(newEventExtrinsicSuccess(m.Index, info)) } @@ -419,10 +417,10 @@ func (m module) TryMutateExists(who primitives.AccountId[primitives.PublicKey], } } else if wasProviding && !isProviding { status, err := m.decProviders(who) - if err != nil { + if dispatchErr, ok := err.(primitives.DispatchError); ok { return sc.Result[sc.Encodable]{ HasError: true, - Value: err, + Value: dispatchErr, }, nil } if status == primitives.DecRefStatusExists { @@ -509,7 +507,7 @@ func (m module) incrementProviders(who primitives.AccountId[primitives.PublicKey } } -func (m module) decProviders(who primitives.AccountId[primitives.PublicKey]) (primitives.DecRefStatus, primitives.DispatchError) { +func (m module) decProviders(who primitives.AccountId[primitives.PublicKey]) (primitives.DecRefStatus, error) { result, err := m.storage.Account.TryMutateExists(who, func(maybeAccount *sc.Option[primitives.AccountInfo]) sc.Result[sc.Encodable] { return m.decrementProviders(who, maybeAccount) }) diff --git a/frame/system/module_test.go b/frame/system/module_test.go index 29d65c3e..bd38fd61 100644 --- a/frame/system/module_test.go +++ b/frame/system/module_test.go @@ -88,7 +88,7 @@ var ( ) var ( - unknownTransactionNoUnsignedValidator, _ = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) + unknownTransactionNoUnsignedValidator = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) ) var ( @@ -476,7 +476,7 @@ func Test_Module_NoteAppliedExtrinsic_ExtrinsicFailed(t *testing.T) { Ok: primitives.PostDispatchInfo{}, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ PostInfo: primitives.PostDispatchInfo{}, - Error: primitives.NewDispatchErrorCorruption(), + Err: primitives.NewDispatchErrorCorruption(), }, } dispatchInfo := primitives.DispatchInfo{ @@ -490,7 +490,7 @@ func Test_Module_NoteAppliedExtrinsic_ExtrinsicFailed(t *testing.T) { } expectEventRecord := primitives.EventRecord{ Phase: primitives.NewExtrinsicPhaseInitialization(), - Event: newEventExtrinsicFailed(moduleId, extrinsicResult.Err.Error, expectDispatchInfo), + Event: newEventExtrinsicFailed(moduleId, extrinsicResult.Err.Err.(primitives.DispatchError), expectDispatchInfo), Topics: []primitives.H256{}, } diff --git a/frame/testable/call.go b/frame/testable/call.go index a9b3d9c9..f981c432 100644 --- a/frame/testable/call.go +++ b/frame/testable/call.go @@ -74,7 +74,7 @@ func (_ callTest) Dispatch(origin primitives.RuntimeOrigin, _ sc.VaryingData) pr storage.Set([]byte("testvalue"), []byte{1}) transactional := support.NewTransactional[primitives.PostDispatchInfo]() - transactional.WithStorageLayer(func() (primitives.PostDispatchInfo, primitives.DispatchError) { + transactional.WithStorageLayer(func() (primitives.PostDispatchInfo, error) { storage.Set([]byte("testvalue"), []byte{2}) return primitives.PostDispatchInfo{}, primitives.NewDispatchErrorOther("revert") }) diff --git a/frame/testable/module.go b/frame/testable/module.go index 47df1caf..3e9cc7e4 100644 --- a/frame/testable/module.go +++ b/frame/testable/module.go @@ -40,14 +40,12 @@ func (m Module) Functions() map[sc.U8]primitives.Call { return m.functions } -func (m Module) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m Module) PreDispatch(_ primitives.Call) (sc.Empty, error) { return sc.Empty{}, nil } -func (m Module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - unknownTransactionNoUnsignedValidator, _ := primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - return primitives.ValidTransaction{}, unknownTransactionNoUnsignedValidator +func (m Module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, error) { + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) } func (m Module) Metadata() (sc.Sequence[primitives.MetadataType], primitives.MetadataModule) { diff --git a/frame/timestamp/call_set.go b/frame/timestamp/call_set.go index c32b42ba..3665ff5c 100644 --- a/frame/timestamp/call_set.go +++ b/frame/timestamp/call_set.go @@ -127,7 +127,7 @@ func (c callSet) set(origin primitives.RuntimeOrigin, now sc.U64) primitives.Dis return primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } } @@ -142,7 +142,7 @@ func (c callSet) set(origin primitives.RuntimeOrigin, now sc.U64) primitives.Dis return primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorOther(sc.Str(err.Error())), + Err: primitives.NewDispatchErrorOther(sc.Str(err.Error())), }, } } diff --git a/frame/timestamp/call_set_test.go b/frame/timestamp/call_set_test.go index 66c86edd..6f9ceb72 100644 --- a/frame/timestamp/call_set_test.go +++ b/frame/timestamp/call_set_test.go @@ -202,7 +202,7 @@ func Test_Call_Set_Dispatch_InvalidOrigin(t *testing.T) { expected := primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]{ HasError: true, Err: primitives.DispatchErrorWithPostInfo[primitives.PostDispatchInfo]{ - Error: primitives.NewDispatchErrorBadOrigin(), + Err: primitives.NewDispatchErrorBadOrigin(), }, } diff --git a/frame/timestamp/module.go b/frame/timestamp/module.go index 9d42dcf6..0b456f80 100644 --- a/frame/timestamp/module.go +++ b/frame/timestamp/module.go @@ -62,11 +62,11 @@ func (m Module) Functions() map[sc.U8]primitives.Call { return m.functions } -func (m Module) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m Module) PreDispatch(_ primitives.Call) (sc.Empty, error) { return sc.Empty{}, nil } -func (m Module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (m Module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } diff --git a/frame/transaction_payment/extensions/charge_transaction.go b/frame/transaction_payment/extensions/charge_transaction.go index 6b52193a..8e875cba 100644 --- a/frame/transaction_payment/extensions/charge_transaction.go +++ b/frame/transaction_payment/extensions/charge_transaction.go @@ -14,7 +14,7 @@ func newChargeTransaction(currencyAdapter primitives.CurrencyAdapter) chargeTran return chargeTransaction{currencyAdapter: currencyAdapter} } -func (ct chargeTransaction) WithdrawFee(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, fee primitives.Balance, tip primitives.Balance) (sc.Option[primitives.Balance], primitives.TransactionValidityError) { +func (ct chargeTransaction) WithdrawFee(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, fee primitives.Balance, tip primitives.Balance) (sc.Option[primitives.Balance], error) { if fee.Eq(constants.Zero) { return sc.NewOption[primitives.Balance](nil), nil } @@ -28,30 +28,24 @@ func (ct chargeTransaction) WithdrawFee(who primitives.AccountId[primitives.Publ imbalance, err := ct.currencyAdapter.Withdraw(who, fee, sc.U8(withdrawReasons), primitives.ExistenceRequirementKeepAlive) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) - return sc.NewOption[primitives.Balance](nil), transactionValidityError + return sc.NewOption[primitives.Balance](nil), primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) } return sc.NewOption[primitives.Balance](imbalance), nil } -func (ct chargeTransaction) CorrectAndDepositFee(who primitives.AccountId[primitives.PublicKey], correctedFee primitives.Balance, tip primitives.Balance, alreadyWithdrawn sc.Option[primitives.Balance]) primitives.TransactionValidityError { +func (ct chargeTransaction) CorrectAndDepositFee(who primitives.AccountId[primitives.PublicKey], correctedFee primitives.Balance, tip primitives.Balance, alreadyWithdrawn sc.Option[primitives.Balance]) error { if alreadyWithdrawn.HasValue { alreadyPaidNegativeImbalance := alreadyWithdrawn.Value refundAmount := sc.SaturatingSubU128(alreadyPaidNegativeImbalance, correctedFee) refundPositiveImbalance, err := ct.currencyAdapter.DepositIntoExisting(who, refundAmount) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionPayment, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) - return invalidTransactionPayment + return primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) } if alreadyPaidNegativeImbalance.Lt(refundPositiveImbalance) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - invalidTransactionPayment, _ := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) - return invalidTransactionPayment + return primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) } } return nil diff --git a/frame/transaction_payment/extensions/charge_transaction_payment.go b/frame/transaction_payment/extensions/charge_transaction_payment.go index ecee7e47..338501a0 100644 --- a/frame/transaction_payment/extensions/charge_transaction_payment.go +++ b/frame/transaction_payment/extensions/charge_transaction_payment.go @@ -45,11 +45,11 @@ func (ctp ChargeTransactionPayment) Bytes() []byte { return sc.EncodedBytes(ctp) } -func (ctp ChargeTransactionPayment) AdditionalSigned() (primitives.AdditionalSigned, primitives.TransactionValidityError) { +func (ctp ChargeTransactionPayment) AdditionalSigned() (primitives.AdditionalSigned, error) { return sc.NewVaryingData(), nil } -func (ctp ChargeTransactionPayment) Validate(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (ctp ChargeTransactionPayment) Validate(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { finalFee, _, err := ctp.withdrawFee(who, call, info, length) if err != nil { return primitives.ValidTransaction{}, err @@ -62,11 +62,11 @@ func (ctp ChargeTransactionPayment) Validate(who primitives.AccountId[primitives return validTransaction, nil } -func (ctp ChargeTransactionPayment) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (ctp ChargeTransactionPayment) ValidateUnsigned(_call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { return primitives.DefaultValidTransaction(), nil } -func (ctp ChargeTransactionPayment) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, primitives.TransactionValidityError) { +func (ctp ChargeTransactionPayment) PreDispatch(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Pre, error) { _, imbalance, err := ctp.withdrawFee(who, call, info, length) if err != nil { return primitives.Pre{}, err @@ -74,7 +74,7 @@ func (ctp ChargeTransactionPayment) PreDispatch(who primitives.AccountId[primiti return sc.NewVaryingData(ctp.fee, who, imbalance), nil } -func (ctp ChargeTransactionPayment) PostDispatch(pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, length sc.Compact, result *primitives.DispatchResult) primitives.TransactionValidityError { +func (ctp ChargeTransactionPayment) PostDispatch(pre sc.Option[primitives.Pre], info *primitives.DispatchInfo, postInfo *primitives.PostDispatchInfo, length sc.Compact, result *primitives.DispatchResult) error { if pre.HasValue { preValue := pre.Value @@ -84,9 +84,7 @@ func (ctp ChargeTransactionPayment) PostDispatch(pre sc.Option[primitives.Pre], actualFee, err := ctp.txPaymentModule.ComputeActualFee(sc.U32(length.ToBigInt().Uint64()), *info, *postInfo, tip) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return transactionValidityError + return err } errFee := ctp.onChargeTransaction.CorrectAndDepositFee(who, actualFee, tip, imbalance) @@ -106,7 +104,7 @@ func (ctp ChargeTransactionPayment) PostDispatch(pre sc.Option[primitives.Pre], return nil } -func (ctp ChargeTransactionPayment) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) primitives.TransactionValidityError { +func (ctp ChargeTransactionPayment) PreDispatchUnsigned(call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) error { _, err := ctp.ValidateUnsigned(call, info, length) return err } @@ -199,13 +197,11 @@ func (ctp ChargeTransactionPayment) getPriority(info *primitives.DispatchInfo, l return 0 } -func (ctp ChargeTransactionPayment) withdrawFee(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Balance, sc.Option[primitives.Balance], primitives.TransactionValidityError) { +func (ctp ChargeTransactionPayment) withdrawFee(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, length sc.Compact) (primitives.Balance, sc.Option[primitives.Balance], error) { tip := ctp.fee fee, err := ctp.txPaymentModule.ComputeFee(sc.U32(length.ToBigInt().Uint64()), *info, tip) if err != nil { - // TODO https://github.com/LimeChain/gosemble/issues/271 - transactionValidityError, _ := primitives.NewTransactionValidityError(sc.Str(err.Error())) - return primitives.Balance{}, sc.NewOption[primitives.Balance](nil), transactionValidityError + return primitives.Balance{}, sc.NewOption[primitives.Balance](nil), err } imbalance, errWithdraw := ctp.onChargeTransaction.WithdrawFee(who, call, info, fee, tip) diff --git a/frame/transaction_payment/extensions/charge_transaction_payment_test.go b/frame/transaction_payment/extensions/charge_transaction_payment_test.go index aa86144d..9800c4be 100644 --- a/frame/transaction_payment/extensions/charge_transaction_payment_test.go +++ b/frame/transaction_payment/extensions/charge_transaction_payment_test.go @@ -56,7 +56,7 @@ var ( }, } - invalidTransactionPaymentError, _ = types.NewTransactionValidityError(types.NewInvalidTransactionPayment()) + invalidTransactionPaymentError = types.NewTransactionValidityError(types.NewInvalidTransactionPayment()) ) var ( diff --git a/frame/transaction_payment/extensions/charge_transaction_test.go b/frame/transaction_payment/extensions/charge_transaction_test.go index 364364e5..6aaac938 100644 --- a/frame/transaction_payment/extensions/charge_transaction_test.go +++ b/frame/transaction_payment/extensions/charge_transaction_test.go @@ -25,7 +25,7 @@ var ( alreadyWithdrawn = sc.NewOption[sc.U128](sc.NewU128(11)) refundAmount = sc.NewU128(1) - expectedError, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) + expectedError = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionPayment()) ) func Test_ChargeTransaction_WithdrawFee_Success(t *testing.T) { diff --git a/frame/transaction_payment/module.go b/frame/transaction_payment/module.go index be875678..3385bd77 100644 --- a/frame/transaction_payment/module.go +++ b/frame/transaction_payment/module.go @@ -47,14 +47,12 @@ func (m module) Functions() map[sc.U8]primitives.Call { return map[sc.U8]primitives.Call{} } -func (m module) PreDispatch(_ primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m module) PreDispatch(_ primitives.Call) (sc.Empty, error) { return sc.Empty{}, nil } -func (m module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - unknownTransactionNoUnsignedValidator, _ := primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - return primitives.ValidTransaction{}, unknownTransactionNoUnsignedValidator +func (m module) ValidateUnsigned(_ primitives.TransactionSource, _ primitives.Call) (primitives.ValidTransaction, error) { + return primitives.ValidTransaction{}, primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) } func (m module) Metadata() (sc.Sequence[primitives.MetadataType], primitives.MetadataModule) { diff --git a/frame/transaction_payment/module_test.go b/frame/transaction_payment/module_test.go index 9eac7ea5..28026766 100644 --- a/frame/transaction_payment/module_test.go +++ b/frame/transaction_payment/module_test.go @@ -41,7 +41,7 @@ var ( ) var ( - noUnsignedValidatorError, _ = types.NewTransactionValidityError( + noUnsignedValidatorError = types.NewTransactionValidityError( types.NewUnknownTransactionNoUnsignedValidator(), ) diff --git a/hooks/on_charge_transaction.go b/hooks/on_charge_transaction.go index 7acc9fec..df3279f3 100644 --- a/hooks/on_charge_transaction.go +++ b/hooks/on_charge_transaction.go @@ -6,6 +6,6 @@ import ( ) type OnChargeTransaction interface { - CorrectAndDepositFee(who primitives.AccountId[primitives.PublicKey], correctedFee primitives.Balance, tip primitives.Balance, alreadyWithdrawn sc.Option[primitives.Balance]) primitives.TransactionValidityError - WithdrawFee(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, fee primitives.Balance, tip primitives.Balance) (sc.Option[primitives.Balance], primitives.TransactionValidityError) + CorrectAndDepositFee(who primitives.AccountId[primitives.PublicKey], correctedFee primitives.Balance, tip primitives.Balance, alreadyWithdrawn sc.Option[primitives.Balance]) error + WithdrawFee(who primitives.AccountId[primitives.PublicKey], call primitives.Call, info *primitives.DispatchInfo, fee primitives.Balance, tip primitives.Balance) (sc.Option[primitives.Balance], error) } diff --git a/mocks/account_id_lookup.go b/mocks/account_id_lookup.go index 5e106a6c..488da2fb 100644 --- a/mocks/account_id_lookup.go +++ b/mocks/account_id_lookup.go @@ -9,12 +9,12 @@ type AccountIdLookup struct { mock.Mock } -func (l *AccountIdLookup) Lookup(a types.MultiAddress) (types.Address32, types.TransactionValidityError) { +func (l *AccountIdLookup) Lookup(a types.MultiAddress) (types.Address32, error) { args := l.Called(a) if args.Get(1) == nil { return args.Get(0).(types.Address32), nil } - return args.Get(0).(types.Address32), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(types.Address32), args.Get(1).(error) } diff --git a/mocks/aura.go b/mocks/aura.go index eae351a5..c9549ff8 100644 --- a/mocks/aura.go +++ b/mocks/aura.go @@ -21,14 +21,14 @@ func (m *AuraModule) Functions() map[sc.U8]primitives.Call { return args.Get(0).(map[sc.U8]primitives.Call) } -func (m *AuraModule) PreDispatch(call primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m *AuraModule) PreDispatch(call primitives.Call) (sc.Empty, error) { args := m.Called(call) - return args.Get(0).(sc.Empty), args.Get(1).(primitives.TransactionValidityError) + return args.Get(0).(sc.Empty), args.Get(1).(error) } -func (m *AuraModule) ValidateUnsigned(txSource primitives.TransactionSource, call primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (m *AuraModule) ValidateUnsigned(txSource primitives.TransactionSource, call primitives.Call) (primitives.ValidTransaction, error) { args := m.Called(txSource, call) - return args.Get(0).(primitives.ValidTransaction), args.Get(1).(primitives.TransactionValidityError) + return args.Get(0).(primitives.ValidTransaction), args.Get(1).(error) } func (m *AuraModule) KeyType() primitives.PublicKeyType { diff --git a/mocks/checked_extrinsic.go b/mocks/checked_extrinsic.go index 7d7ba065..ab852284 100644 --- a/mocks/checked_extrinsic.go +++ b/mocks/checked_extrinsic.go @@ -10,18 +10,18 @@ type CheckedExtrinsic struct { mock.Mock } -func (c *CheckedExtrinsic) Apply(validator primitives.UnsignedValidator, info *primitives.DispatchInfo, length sc.Compact) (primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo], primitives.TransactionValidityError) { +func (c *CheckedExtrinsic) Apply(validator primitives.UnsignedValidator, info *primitives.DispatchInfo, length sc.Compact) (primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo], error) { args := c.Called(validator, info, length) var arg0 primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo] - var arg1 primitives.TransactionValidityError + var arg1 error if args.Get(0) != nil { arg0 = args.Get(0).(primitives.DispatchResultWithPostInfo[primitives.PostDispatchInfo]) } if args.Get(1) != nil { - arg1 = args.Get(1).(primitives.TransactionValidityError) + arg1 = args.Get(1).(error) } return arg0, arg1 @@ -32,18 +32,18 @@ func (c *CheckedExtrinsic) Function() primitives.Call { return args.Get(0).(primitives.Call) } -func (c *CheckedExtrinsic) Validate(validator primitives.UnsignedValidator, source primitives.TransactionSource, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (c *CheckedExtrinsic) Validate(validator primitives.UnsignedValidator, source primitives.TransactionSource, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) { args := c.Called(validator, source, info, length) var arg0 primitives.ValidTransaction - var arg1 primitives.TransactionValidityError + var arg1 error if args.Get(0) != nil { arg0 = args.Get(0).(primitives.ValidTransaction) } if args.Get(1) != nil { - arg1 = args.Get(1).(primitives.TransactionValidityError) + arg1 = args.Get(1).(error) } return arg0, arg1 diff --git a/mocks/currency_adapter.go b/mocks/currency_adapter.go index 2cfe1761..2d610ee0 100644 --- a/mocks/currency_adapter.go +++ b/mocks/currency_adapter.go @@ -10,21 +10,21 @@ type CurrencyAdapter struct { mock.Mock } -func (m *CurrencyAdapter) DepositIntoExisting(who types.AccountId[types.PublicKey], value sc.U128) (types.Balance, types.DispatchError) { +func (m *CurrencyAdapter) DepositIntoExisting(who types.AccountId[types.PublicKey], value sc.U128) (types.Balance, error) { args := m.Called(who, value) if args.Get(1) != nil { - return args.Get(0).(types.Balance), args.Get(1).(types.DispatchError) + return args.Get(0).(types.Balance), args.Get(1).(error) } return args.Get(0).(types.Balance), nil } -func (m *CurrencyAdapter) Withdraw(who types.AccountId[types.PublicKey], value sc.U128, reasons sc.U8, liveness types.ExistenceRequirement) (types.Balance, types.DispatchError) { +func (m *CurrencyAdapter) Withdraw(who types.AccountId[types.PublicKey], value sc.U128, reasons sc.U8, liveness types.ExistenceRequirement) (types.Balance, error) { args := m.Called(who, value, reasons, liveness) if args.Get(1) != nil { - return args.Get(0).(types.Balance), args.Get(1).(types.DispatchError) + return args.Get(0).(types.Balance), args.Get(1).(error) } return args.Get(0).(types.Balance), nil diff --git a/mocks/executive.go b/mocks/executive.go index 2e90de90..fa66275d 100644 --- a/mocks/executive.go +++ b/mocks/executive.go @@ -26,11 +26,11 @@ func (m *Executive) ExecuteBlock(block types.Block) error { return args.Get(0).(error) } -func (m *Executive) ApplyExtrinsic(uxt types.UncheckedExtrinsic) (primitives.DispatchOutcome, primitives.TransactionValidityError) { +func (m *Executive) ApplyExtrinsic(uxt types.UncheckedExtrinsic) (primitives.DispatchOutcome, error) { args := m.Called(uxt) if args.Get(1) != nil { - return args.Get(0).(primitives.DispatchOutcome), args.Get(1).(primitives.TransactionValidityError) + return args.Get(0).(primitives.DispatchOutcome), args.Get(1).(error) } return args.Get(0).(primitives.DispatchOutcome), nil @@ -46,11 +46,11 @@ func (m *Executive) FinalizeBlock() (primitives.Header, error) { return args.Get(0).(primitives.Header), args.Get(1).(error) } -func (m *Executive) ValidateTransaction(source primitives.TransactionSource, uxt types.UncheckedExtrinsic, blockHash primitives.Blake2bHash) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (m *Executive) ValidateTransaction(source primitives.TransactionSource, uxt types.UncheckedExtrinsic, blockHash primitives.Blake2bHash) (primitives.ValidTransaction, error) { args := m.Called(source, uxt, blockHash) if args.Get(1) != nil { - return args.Get(0).(primitives.ValidTransaction), args.Get(1).(primitives.TransactionValidityError) + return args.Get(0).(primitives.ValidTransaction), args.Get(1).(error) } return args.Get(0).(primitives.ValidTransaction), nil diff --git a/mocks/grandpa.go b/mocks/grandpa.go index ad6107df..b5161175 100644 --- a/mocks/grandpa.go +++ b/mocks/grandpa.go @@ -21,14 +21,14 @@ func (m *GrandpaModule) Functions() map[sc.U8]primitives.Call { return args.Get(0).(map[sc.U8]primitives.Call) } -func (m *GrandpaModule) PreDispatch(call primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m *GrandpaModule) PreDispatch(call primitives.Call) (sc.Empty, error) { args := m.Called(call) - return args.Get(0).(sc.Empty), args.Get(1).(primitives.TransactionValidityError) + return args.Get(0).(sc.Empty), args.Get(1).(error) } -func (m *GrandpaModule) ValidateUnsigned(txSource primitives.TransactionSource, call primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (m *GrandpaModule) ValidateUnsigned(txSource primitives.TransactionSource, call primitives.Call) (primitives.ValidTransaction, error) { args := m.Called(txSource, call) - return args.Get(0).(primitives.ValidTransaction), args.Get(1).(primitives.TransactionValidityError) + return args.Get(0).(primitives.ValidTransaction), args.Get(1).(error) } func (m *GrandpaModule) KeyType() primitives.PublicKeyType { diff --git a/mocks/io_transactional.go b/mocks/io_transactional.go index a25c345c..70c5d561 100644 --- a/mocks/io_transactional.go +++ b/mocks/io_transactional.go @@ -2,20 +2,19 @@ package mocks import ( sc "github.com/LimeChain/goscale" - "github.com/LimeChain/gosemble/primitives/types" "github.com/stretchr/testify/mock" ) -type IoTransactional[T sc.Encodable, E types.DispatchError] struct { +type IoTransactional[T sc.Encodable] struct { mock.Mock } -func (m *IoTransactional[T, E]) WithStorageLayer(fn func() (T, types.DispatchError)) (T, E) { +func (m *IoTransactional[T]) WithStorageLayer(fn func() (T, error)) (T, error) { args := m.Called(fn) if args.Get(1) == nil { return args.Get(0).(T), nil } - return args.Get(0).(T), args.Get(1).(E) + return args.Get(0).(T), args.Get(1).(error) } diff --git a/mocks/module.go b/mocks/module.go index fae05376..01a9f5d9 100644 --- a/mocks/module.go +++ b/mocks/module.go @@ -22,24 +22,24 @@ func (m *Module) Functions() map[sc.U8]types.Call { return args.Get(0).(map[sc.U8]types.Call) } -func (m *Module) PreDispatch(call types.Call) (sc.Empty, types.TransactionValidityError) { +func (m *Module) PreDispatch(call types.Call) (sc.Empty, error) { args := m.Called(call) if args.Get(1) == nil { return args.Get(0).(sc.Empty), nil } - return args.Get(0).(sc.Empty), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(sc.Empty), args.Get(1).(error) } -func (m *Module) ValidateUnsigned(txSource types.TransactionSource, call types.Call) (types.ValidTransaction, types.TransactionValidityError) { +func (m *Module) ValidateUnsigned(txSource types.TransactionSource, call types.Call) (types.ValidTransaction, error) { args := m.Called(txSource, call) if args.Get(1) == nil { return args.Get(0).(types.ValidTransaction), nil } - return args.Get(0).(types.ValidTransaction), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(types.ValidTransaction), args.Get(1).(error) } func (m *Module) Metadata() (sc.Sequence[types.MetadataType], types.MetadataModule) { diff --git a/mocks/on_charge_transaction.go b/mocks/on_charge_transaction.go index 9bdb2d9d..6b664513 100644 --- a/mocks/on_charge_transaction.go +++ b/mocks/on_charge_transaction.go @@ -11,18 +11,18 @@ type OnChargeTransaction struct { mock.Mock } -func (ct *OnChargeTransaction) CorrectAndDepositFee(who primitives.AccountId[types.PublicKey], correctedFee types.Balance, tip types.Balance, alreadyWithdrawn sc.Option[types.Balance]) types.TransactionValidityError { +func (ct *OnChargeTransaction) CorrectAndDepositFee(who primitives.AccountId[types.PublicKey], correctedFee types.Balance, tip types.Balance, alreadyWithdrawn sc.Option[types.Balance]) error { args := ct.Called(who, correctedFee, tip, alreadyWithdrawn) if args.Get(0) == nil { return nil } - return args.Get(0).(types.TransactionValidityError) + return args.Get(0).(error) } func (ct *OnChargeTransaction) WithdrawFee(who primitives.AccountId[types.PublicKey], call primitives.Call, info *types.DispatchInfo, fee types.Balance, tip types.Balance) ( - sc.Option[types.Balance], types.TransactionValidityError) { + sc.Option[types.Balance], error) { args := ct.Called(who, call, info, fee, tip) @@ -30,5 +30,5 @@ func (ct *OnChargeTransaction) WithdrawFee(who primitives.AccountId[types.Public return args.Get(0).(sc.Option[types.Balance]), nil } - return sc.NewOption[types.Balance](nil), args.Get(1).(types.TransactionValidityError) + return sc.NewOption[types.Balance](nil), args.Get(1).(error) } diff --git a/mocks/signed_extra.go b/mocks/signed_extra.go index f1019c25..52c6ca7e 100644 --- a/mocks/signed_extra.go +++ b/mocks/signed_extra.go @@ -26,56 +26,62 @@ func (m *SignedExtra) Decode(buffer *bytes.Buffer) { m.Called(buffer) } -func (m *SignedExtra) AdditionalSigned() (types.AdditionalSigned, types.TransactionValidityError) { +func (m *SignedExtra) AdditionalSigned() (types.AdditionalSigned, error) { args := m.Called() if args.Get(1) != nil { - return args.Get(0).(types.AdditionalSigned), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(types.AdditionalSigned), args.Get(1).(error) } return args.Get(0).(types.AdditionalSigned), nil } -func (m *SignedExtra) Validate(who types.AccountId[types.PublicKey], call types.Call, info *types.DispatchInfo, length sc.Compact) (types.ValidTransaction, types.TransactionValidityError) { +func (m *SignedExtra) Validate(who types.AccountId[types.PublicKey], call types.Call, info *types.DispatchInfo, length sc.Compact) (types.ValidTransaction, error) { args := m.Called(who, call, info, length) if args.Get(1) != nil { - return args.Get(0).(types.ValidTransaction), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(types.ValidTransaction), args.Get(1).(error) } return args.Get(0).(types.ValidTransaction), nil } -func (m *SignedExtra) ValidateUnsigned(call types.Call, info *types.DispatchInfo, length sc.Compact) (types.ValidTransaction, types.TransactionValidityError) { +func (m *SignedExtra) ValidateUnsigned(call types.Call, info *types.DispatchInfo, length sc.Compact) (types.ValidTransaction, error) { args := m.Called(call, info, length) if args.Get(1) != nil { - return args.Get(0).(types.ValidTransaction), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(types.ValidTransaction), args.Get(1).(error) } return args.Get(0).(types.ValidTransaction), nil } -func (m *SignedExtra) PreDispatch(who types.AccountId[types.PublicKey], call types.Call, info *types.DispatchInfo, length sc.Compact) (sc.Sequence[types.Pre], types.TransactionValidityError) { +func (m *SignedExtra) PreDispatch(who types.AccountId[types.PublicKey], call types.Call, info *types.DispatchInfo, length sc.Compact) (sc.Sequence[types.Pre], error) { args := m.Called(who, call, info, length) if args.Get(1) != nil { - return args.Get(0).(sc.Sequence[types.Pre]), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(sc.Sequence[types.Pre]), args.Get(1).(error) } return args.Get(0).(sc.Sequence[types.Pre]), nil } -func (m *SignedExtra) PreDispatchUnsigned(call types.Call, info *types.DispatchInfo, length sc.Compact) types.TransactionValidityError { +func (m *SignedExtra) PreDispatchUnsigned(call types.Call, info *types.DispatchInfo, length sc.Compact) error { args := m.Called(call, info, length) - return args.Get(0).(types.TransactionValidityError) + if args.Get(0) != nil { + return args.Get(0).(error) + } + return nil } -func (m *SignedExtra) PostDispatch(pre sc.Option[sc.Sequence[types.Pre]], info *types.DispatchInfo, postInfo *types.PostDispatchInfo, length sc.Compact, result *types.DispatchResult) types.TransactionValidityError { +func (m *SignedExtra) PostDispatch(pre sc.Option[sc.Sequence[types.Pre]], info *types.DispatchInfo, postInfo *types.PostDispatchInfo, length sc.Compact, result *types.DispatchResult) error { args := m.Called(pre, info, postInfo, length, result) - return args.Get(0).(types.TransactionValidityError) + if args.Get(0) != nil { + return args.Get(0).(error) + } + return nil } func (m *SignedExtra) Metadata() (sc.Sequence[types.MetadataType], sc.Sequence[types.MetadataSignedExtension]) { diff --git a/mocks/system.go b/mocks/system.go index 2183b453..a929e549 100644 --- a/mocks/system.go +++ b/mocks/system.go @@ -71,14 +71,14 @@ func (m *SystemModule) Functions() map[sc.U8]primitives.Call { return args.Get(0).(map[sc.U8]primitives.Call) } -func (m *SystemModule) PreDispatch(call primitives.Call) (sc.Empty, primitives.TransactionValidityError) { +func (m *SystemModule) PreDispatch(call primitives.Call) (sc.Empty, error) { args := m.Called(call) - return args.Get(0).(sc.Empty), args.Get(1).(primitives.TransactionValidityError) + return args.Get(0).(sc.Empty), args.Get(1).(error) } -func (m *SystemModule) ValidateUnsigned(txSource primitives.TransactionSource, call primitives.Call) (primitives.ValidTransaction, primitives.TransactionValidityError) { +func (m *SystemModule) ValidateUnsigned(txSource primitives.TransactionSource, call primitives.Call) (primitives.ValidTransaction, error) { args := m.Called(txSource, call) - return args.Get(0).(primitives.ValidTransaction), args.Get(1).(primitives.TransactionValidityError) + return args.Get(0).(primitives.ValidTransaction), args.Get(1).(error) } func (m *SystemModule) Initialize(blockNumber sc.U64, parentHash primitives.Blake2bHash, digest primitives.Digest) { diff --git a/mocks/tx_payment_module.go b/mocks/tx_payment_module.go index 22cbd8e3..ab5b4ad1 100644 --- a/mocks/tx_payment_module.go +++ b/mocks/tx_payment_module.go @@ -71,14 +71,14 @@ func (m *TransactionPaymentModule) Functions() map[sc.U8]types.Call { return args.Get(0).(map[sc.U8]types.Call) } -func (m *TransactionPaymentModule) PreDispatch(call types.Call) (sc.Empty, types.TransactionValidityError) { +func (m *TransactionPaymentModule) PreDispatch(call types.Call) (sc.Empty, error) { args := m.Called(call) - return args.Get(0).(sc.Empty), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(sc.Empty), args.Get(1).(error) } -func (m *TransactionPaymentModule) ValidateUnsigned(source types.TransactionSource, call types.Call) (types.ValidTransaction, types.TransactionValidityError) { +func (m *TransactionPaymentModule) ValidateUnsigned(source types.TransactionSource, call types.Call) (types.ValidTransaction, error) { args := m.Called(source, call) - return args.Get(0).(types.ValidTransaction), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(types.ValidTransaction), args.Get(1).(error) } func (m *TransactionPaymentModule) Metadata() (sc.Sequence[types.MetadataType], types.MetadataModule) { diff --git a/mocks/unchecked_extrinsic.go b/mocks/unchecked_extrinsic.go index 3fec94f4..b9aad0b0 100644 --- a/mocks/unchecked_extrinsic.go +++ b/mocks/unchecked_extrinsic.go @@ -42,18 +42,18 @@ func (uxt *UncheckedExtrinsic) IsSigned() bool { return args.Get(0).(bool) } -func (uxt *UncheckedExtrinsic) Check() (primitives.CheckedExtrinsic, primitives.TransactionValidityError) { +func (uxt *UncheckedExtrinsic) Check() (primitives.CheckedExtrinsic, error) { args := uxt.Called() var arg0 primitives.CheckedExtrinsic - var arg1 primitives.TransactionValidityError + var arg1 error if args.Get(0) != nil { arg0 = args.Get(0).(primitives.CheckedExtrinsic) } if args.Get(1) != nil { - arg1 = args.Get(1).(primitives.TransactionValidityError) + arg1 = args.Get(1).(error) } return arg0, arg1 diff --git a/mocks/unsigned_validator.go b/mocks/unsigned_validator.go index bd8b7d13..50dfa50c 100644 --- a/mocks/unsigned_validator.go +++ b/mocks/unsigned_validator.go @@ -10,22 +10,22 @@ type UnsignedValidator struct { mock.Mock } -func (m *UnsignedValidator) PreDispatch(call types.Call) (sc.Empty, types.TransactionValidityError) { +func (m *UnsignedValidator) PreDispatch(call types.Call) (sc.Empty, error) { args := m.Called(call) if args.Get(1) == nil { return args.Get(0).(sc.Empty), nil } - return args.Get(0).(sc.Empty), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(sc.Empty), args.Get(1).(error) } -func (m *UnsignedValidator) ValidateUnsigned(source types.TransactionSource, call types.Call) (types.ValidTransaction, types.TransactionValidityError) { +func (m *UnsignedValidator) ValidateUnsigned(source types.TransactionSource, call types.Call) (types.ValidTransaction, error) { args := m.Called(source, call) if args.Get(1) == nil { return args.Get(0).(types.ValidTransaction), nil } - return args.Get(0).(types.ValidTransaction), args.Get(1).(types.TransactionValidityError) + return args.Get(0).(types.ValidTransaction), args.Get(1).(error) } diff --git a/primitives/types/apply_extrinsic_result.go b/primitives/types/apply_extrinsic_result.go index 824827be..3d1fc189 100644 --- a/primitives/types/apply_extrinsic_result.go +++ b/primitives/types/apply_extrinsic_result.go @@ -70,11 +70,11 @@ func DecodeApplyExtrinsicResult(buffer *bytes.Buffer) (ApplyExtrinsicResult, err } return NewApplyExtrinsicResult(value) case 1: - value, err := DecodeTransactionValidityError(buffer) - if err != nil { - return nil, err + err := DecodeTransactionValidityError(buffer) + if txErr, ok := err.(TransactionValidityError); ok { + return NewApplyExtrinsicResult(txErr) } - return NewApplyExtrinsicResult(value) + return nil, err default: return nil, newTypeError("ApplyExtrinsicResult") } diff --git a/primitives/types/apply_extrinsic_result_test.go b/primitives/types/apply_extrinsic_result_test.go index 43b983c4..4ddee700 100644 --- a/primitives/types/apply_extrinsic_result_test.go +++ b/primitives/types/apply_extrinsic_result_test.go @@ -8,14 +8,14 @@ import ( ) var ( - invalidTransactionCall, _ = NewTransactionValidityError(NewInvalidTransactionCall()) + invalidTransactionCall = NewTransactionValidityError(NewInvalidTransactionCall()) dispatchOutcome, _ = NewDispatchOutcome(nil) dispatchOutcomeBadOriginErr, _ = NewDispatchOutcome(NewDispatchErrorBadOrigin()) applyExtrinsicResultOutcome, _ = NewApplyExtrinsicResult(dispatchOutcome) applyExtrinsicResultBadOriginErr, _ = NewApplyExtrinsicResult(dispatchOutcomeBadOriginErr) - applyExtrinsicResultInvalidCall, _ = NewApplyExtrinsicResult(invalidTransactionCall) + applyExtrinsicResultInvalidCall, _ = NewApplyExtrinsicResult(invalidTransactionCall.(TransactionValidityError)) ) func Test_EncodeApplyExtrinsicResult(t *testing.T) { diff --git a/primitives/types/arithmetic_error.go b/primitives/types/arithmetic_error.go index bc5a5afa..a48a8294 100644 --- a/primitives/types/arithmetic_error.go +++ b/primitives/types/arithmetic_error.go @@ -12,34 +12,53 @@ const ( ArithmeticErrorDivisionByZero ) -type ArithmeticError = sc.VaryingData +type ArithmeticError struct { + sc.VaryingData +} func NewArithmeticErrorUnderflow() ArithmeticError { - return sc.NewVaryingData(ArithmeticErrorUnderflow) + return ArithmeticError{sc.NewVaryingData(ArithmeticErrorUnderflow)} } func NewArithmeticErrorOverflow() ArithmeticError { - return sc.NewVaryingData(ArithmeticErrorOverflow) + return ArithmeticError{sc.NewVaryingData(ArithmeticErrorOverflow)} } func NewArithmeticErrorDivisionByZero() ArithmeticError { - return sc.NewVaryingData(ArithmeticErrorDivisionByZero) + return ArithmeticError{sc.NewVaryingData(ArithmeticErrorDivisionByZero)} +} + +func (err ArithmeticError) Error() string { + if len(err.VaryingData) == 0 { + return "" + } + + switch err.VaryingData[0] { + case ArithmeticErrorUnderflow: + return "An underflow would occur" + case ArithmeticErrorOverflow: + return "An overflow would occur" + case ArithmeticErrorDivisionByZero: + return "Division by zero" + default: + return "" + } } -func DecodeArithmeticError(buffer *bytes.Buffer) (ArithmeticError, error) { +func DecodeArithmeticError(buffer *bytes.Buffer) error { b, err := sc.DecodeU8(buffer) if err != nil { - return ArithmeticError{}, err + return err } switch b { case ArithmeticErrorUnderflow: - return NewArithmeticErrorUnderflow(), nil + return NewArithmeticErrorUnderflow() case ArithmeticErrorOverflow: - return NewArithmeticErrorOverflow(), nil + return NewArithmeticErrorOverflow() case ArithmeticErrorDivisionByZero: - return NewArithmeticErrorDivisionByZero(), nil + return NewArithmeticErrorDivisionByZero() default: - return nil, newTypeError("ArithmeticError") + return newTypeError("ArithmeticError") } } diff --git a/primitives/types/arithmetic_error_test.go b/primitives/types/arithmetic_error_test.go index 0acc429c..8ef55fbc 100644 --- a/primitives/types/arithmetic_error_test.go +++ b/primitives/types/arithmetic_error_test.go @@ -11,19 +11,19 @@ import ( func Test_NewArithmeticErrorUnderflow(t *testing.T) { result := NewArithmeticErrorUnderflow() - assert.Equal(t, sc.U8(0), result[0]) + assert.Equal(t, sc.U8(0), result.VaryingData[0]) } func Test_NewArithmeticErrorOverflow(t *testing.T) { result := NewArithmeticErrorOverflow() - assert.Equal(t, sc.U8(1), result[0]) + assert.Equal(t, sc.U8(1), result.VaryingData[0]) } func Test_NewArithmeticErrorDivisionByZero(t *testing.T) { result := NewArithmeticErrorDivisionByZero() - assert.Equal(t, sc.U8(2), result[0]) + assert.Equal(t, sc.U8(2), result.VaryingData[0]) } func Test_ArithmeticError_Decode(t *testing.T) { @@ -39,20 +39,13 @@ func Test_ArithmeticError_Decode(t *testing.T) { for _, testExample := range testExamples { t.Run(testExample.label, func(t *testing.T) { - result, err := DecodeArithmeticError(bytes.NewBuffer(testExample.input)) - assert.NoError(t, err) - - assert.Equal(t, result, testExample.expectation) + buffer := bytes.NewBuffer(testExample.input) + assert.Equal(t, testExample.expectation, DecodeArithmeticError(buffer)) }) } } func Test_Decode_TypeError(t *testing.T) { buffer := bytes.NewBuffer([]byte{0x03}) - - res, err := DecodeArithmeticError(buffer) - - assert.Error(t, err) - assert.Equal(t, "not a valid 'ArithmeticError' type", err.Error()) - assert.Nil(t, res) + assert.Equal(t, "not a valid 'ArithmeticError' type", DecodeArithmeticError(buffer).Error()) } diff --git a/primitives/types/checked_extrinsic.go b/primitives/types/checked_extrinsic.go index 83eaf9ee..bf1fe0c4 100644 --- a/primitives/types/checked_extrinsic.go +++ b/primitives/types/checked_extrinsic.go @@ -3,7 +3,7 @@ package types import sc "github.com/LimeChain/goscale" type CheckedExtrinsic interface { - Apply(validator UnsignedValidator, info *DispatchInfo, length sc.Compact) (DispatchResultWithPostInfo[PostDispatchInfo], TransactionValidityError) + Apply(validator UnsignedValidator, info *DispatchInfo, length sc.Compact) (DispatchResultWithPostInfo[PostDispatchInfo], error) Function() Call - Validate(validator UnsignedValidator, source TransactionSource, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) + Validate(validator UnsignedValidator, source TransactionSource, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) } diff --git a/primitives/types/currency_adapter.go b/primitives/types/currency_adapter.go index 38cf9235..14460a12 100644 --- a/primitives/types/currency_adapter.go +++ b/primitives/types/currency_adapter.go @@ -7,10 +7,10 @@ type CurrencyAdapter interface { // DepositIntoExisting adds free balance to `who`. // Returns an error if `who` is a new account. // Deposits an event and returns `value`. - DepositIntoExisting(who AccountId[PublicKey], value sc.U128) (Balance, DispatchError) + DepositIntoExisting(who AccountId[PublicKey], value sc.U128) (Balance, error) // Withdraw removes free balance from `who` based on `reasons`. // If `liveness` is ExistenceRequirementKeepAlive, the remaining value must not be less than the existential deposit. // Checks `who` for liquidity restrictions and returns an error if they are not met. // Deposits a withdrawal event and returns `value`. - Withdraw(who AccountId[PublicKey], value sc.U128, reasons sc.U8, liveness ExistenceRequirement) (Balance, DispatchError) + Withdraw(who AccountId[PublicKey], value sc.U128, reasons sc.U8, liveness ExistenceRequirement) (Balance, error) } diff --git a/primitives/types/dispatch_errors.go b/primitives/types/dispatch_errors.go index 4e156427..dd7ed19b 100644 --- a/primitives/types/dispatch_errors.go +++ b/primitives/types/dispatch_errors.go @@ -22,153 +22,195 @@ const ( DispatchErrorUnavailable ) -type DispatchError = sc.VaryingData +type DispatchError struct { + sc.VaryingData +} func NewDispatchErrorOther(str sc.Str) DispatchError { - return sc.NewVaryingData(DispatchErrorOther, str) + return DispatchError{sc.NewVaryingData(DispatchErrorOther, str)} } func NewDispatchErrorCannotLookup() DispatchError { - return sc.NewVaryingData(DispatchErrorCannotLookup) + return DispatchError{sc.NewVaryingData(DispatchErrorCannotLookup)} } func NewDispatchErrorBadOrigin() DispatchError { - return sc.NewVaryingData(DispatchErrorBadOrigin) + return DispatchError{sc.NewVaryingData(DispatchErrorBadOrigin)} } func NewDispatchErrorModule(customModuleError CustomModuleError) DispatchError { - return sc.NewVaryingData(DispatchErrorModule, customModuleError) + return DispatchError{sc.NewVaryingData(DispatchErrorModule, customModuleError)} } func NewDispatchErrorConsumerRemaining() DispatchError { - return sc.NewVaryingData(DispatchErrorConsumerRemaining) + return DispatchError{sc.NewVaryingData(DispatchErrorConsumerRemaining)} } func NewDispatchErrorNoProviders() DispatchError { - return sc.NewVaryingData(DispatchErrorNoProviders) + return DispatchError{sc.NewVaryingData(DispatchErrorNoProviders)} } func NewDispatchErrorTooManyConsumers() DispatchError { - return sc.NewVaryingData(DispatchErrorTooManyConsumers) + return DispatchError{sc.NewVaryingData(DispatchErrorTooManyConsumers)} } func NewDispatchErrorToken(tokenError TokenError) DispatchError { // TODO: type safety - return sc.NewVaryingData(DispatchErrorToken, tokenError) + return DispatchError{sc.NewVaryingData(DispatchErrorToken, tokenError)} } func NewDispatchErrorArithmetic(arithmeticError ArithmeticError) DispatchError { // TODO: type safety - return sc.NewVaryingData(DispatchErrorArithmetic, arithmeticError) + return DispatchError{sc.NewVaryingData(DispatchErrorArithmetic, arithmeticError)} } func NewDispatchErrorTransactional(transactionalError TransactionalError) DispatchError { // TODO: type safety - return sc.NewVaryingData(DispatchErrorTransactional, transactionalError) + return DispatchError{sc.NewVaryingData(DispatchErrorTransactional, transactionalError)} } func NewDispatchErrorExhausted() DispatchError { - return sc.NewVaryingData(DispatchErrorExhausted) + return DispatchError{sc.NewVaryingData(DispatchErrorExhausted)} } func NewDispatchErrorCorruption() DispatchError { - return sc.NewVaryingData(DispatchErrorCorruption) + return DispatchError{sc.NewVaryingData(DispatchErrorCorruption)} } func NewDispatchErrorUnavailable() DispatchError { - return sc.NewVaryingData(DispatchErrorUnavailable) + return DispatchError{sc.NewVaryingData(DispatchErrorUnavailable)} } -func DecodeDispatchError(buffer *bytes.Buffer) (DispatchError, error) { +func (err DispatchError) Error() string { + if len(err.VaryingData) == 0 { + return "" + } + + switch dispatchErr := err.VaryingData[0]; dispatchErr { + case DispatchErrorOther: + return "Some unknown error occurred" + case DispatchErrorCannotLookup: + return "Cannot lookup" + case DispatchErrorBadOrigin: + return "Bad origin" + case DispatchErrorModule: + return dispatchErr.(CustomModuleError).Error() + case DispatchErrorConsumerRemaining: + return "Consumer remaining" + case DispatchErrorNoProviders: + return "No providers" + case DispatchErrorTooManyConsumers: + return "Too many consumers" + case DispatchErrorToken: + return dispatchErr.(TokenError).Error() + case DispatchErrorArithmetic: + return dispatchErr.(ArithmeticError).Error() + case DispatchErrorExhausted: + return "Resources exhausted" + case DispatchErrorCorruption: + return "State corrupt" + case DispatchErrorUnavailable: + return "Resource unavailable" + default: + return "" + } +} // e[0].(InvalidTransaction).Error() + +func DecodeDispatchError(buffer *bytes.Buffer) error { b, err := sc.DecodeU8(buffer) if err != nil { - return nil, err + return err } switch b { case DispatchErrorOther: value, err := sc.DecodeStr(buffer) if err != nil { - return nil, err + return err } - return NewDispatchErrorOther(value), nil + return NewDispatchErrorOther(value) case DispatchErrorCannotLookup: - return NewDispatchErrorCannotLookup(), nil + return NewDispatchErrorCannotLookup() case DispatchErrorBadOrigin: - return NewDispatchErrorBadOrigin(), nil + return NewDispatchErrorBadOrigin() case DispatchErrorModule: - module, err := DecodeCustomModuleError(buffer) - if err != nil { - return DispatchError{}, err + customErr := DecodeCustomModuleError(buffer) + if _, ok := customErr.(CustomModuleError); !ok { + return err } - return NewDispatchErrorModule(module), nil + return NewDispatchErrorModule(customErr.(CustomModuleError)) case DispatchErrorConsumerRemaining: - return NewDispatchErrorConsumerRemaining(), nil + return NewDispatchErrorConsumerRemaining() case DispatchErrorNoProviders: - return NewDispatchErrorNoProviders(), nil + return NewDispatchErrorNoProviders() case DispatchErrorTooManyConsumers: - return NewDispatchErrorTooManyConsumers(), nil + return NewDispatchErrorTooManyConsumers() case DispatchErrorToken: - tokenError, err := DecodeTokenError(buffer) - if err != nil { - return DispatchError{}, err + tokenError := DecodeTokenError(buffer) + if _, ok := tokenError.(TokenError); !ok { + return err } - return NewDispatchErrorToken(tokenError), nil + return NewDispatchErrorToken(tokenError.(TokenError)) case DispatchErrorArithmetic: - arithmeticError, err := DecodeArithmeticError(buffer) - if err != nil { - return nil, err + arithmeticErr := DecodeArithmeticError(buffer) + if _, ok := arithmeticErr.(ArithmeticError); !ok { + return err } - return NewDispatchErrorArithmetic(arithmeticError), nil + return NewDispatchErrorArithmetic(arithmeticErr.(ArithmeticError)) case DispatchErrorTransactional: - transactionalError, err := DecodeTransactionalError(buffer) - if err != nil { - return DispatchError{}, err + txErr := DecodeTransactionalError(buffer) + if _, ok := txErr.(TransactionalError); !ok { + return err } - return NewDispatchErrorTransactional(transactionalError), nil + return NewDispatchErrorTransactional(txErr.(TransactionalError)) case DispatchErrorExhausted: - return NewDispatchErrorExhausted(), nil + return NewDispatchErrorExhausted() case DispatchErrorCorruption: - return NewDispatchErrorCorruption(), nil + return NewDispatchErrorCorruption() case DispatchErrorUnavailable: - return NewDispatchErrorUnavailable(), nil + return NewDispatchErrorUnavailable() default: - return DispatchError{}, newTypeError("DispatchError") + return newTypeError("DispatchError") } } // CustomModuleError A custom error in a module. type CustomModuleError struct { Index sc.U8 // Module index matching the metadata module index. - Error sc.U32 // Module specific error value. + Err sc.U32 // Module specific error value. Message sc.Option[sc.Str] // Varying data type Option (Definition 190). The optional value is a SCALE encoded byte array containing a valid UTF-8 sequence. } -func (e CustomModuleError) Encode(buffer *bytes.Buffer) error { +func (err CustomModuleError) Error() string { + // todo + return "todo" +} + +func (err CustomModuleError) Encode(buffer *bytes.Buffer) error { return sc.EncodeEach(buffer, - e.Index, - e.Error, + err.Index, + err.Err, ) // e.Message is skipped in codec } -func DecodeCustomModuleError(buffer *bytes.Buffer) (CustomModuleError, error) { - e := CustomModuleError{} +func DecodeCustomModuleError(buffer *bytes.Buffer) error { + cErr := CustomModuleError{} idx, err := sc.DecodeU8(buffer) if err != nil { - return CustomModuleError{}, err + return err } - e.Index = idx + cErr.Index = idx decodedErr, err := sc.DecodeU32(buffer) if err != nil { - return CustomModuleError{}, err + return err } - e.Error = decodedErr + cErr.Err = decodedErr //e.Message = sc.DecodeOption[sc.Str](buffer) // Skipped in codec - return e, nil + return cErr } -func (e CustomModuleError) Bytes() []byte { - return sc.EncodedBytes(e) +func (err CustomModuleError) Bytes() []byte { + return sc.EncodedBytes(err) } // DispatchErrorWithPostInfo Result of a `Dispatchable` which contains the `DispatchResult` and additional information about @@ -178,31 +220,33 @@ type DispatchErrorWithPostInfo[T sc.Encodable] struct { PostInfo T // The actual `DispatchResult` indicating whether the dispatch was successful. - Error DispatchError + Err error } -func (e DispatchErrorWithPostInfo[PostDispatchInfo]) Encode(buffer *bytes.Buffer) error { - return sc.EncodeEach(buffer, - e.PostInfo, - e.Error, - ) +func (err DispatchErrorWithPostInfo[PostDispatchInfo]) Error() string { + return err.Err.Error() } -func DecodeErrorWithPostInfo(buffer *bytes.Buffer) (DispatchErrorWithPostInfo[PostDispatchInfo], error) { - e := DispatchErrorWithPostInfo[PostDispatchInfo]{} - postInfo, err := DecodePostDispatchInfo(buffer) - if err != nil { - return DispatchErrorWithPostInfo[PostDispatchInfo]{}, err +func (err DispatchErrorWithPostInfo[PostDispatchInfo]) Encode(buffer *bytes.Buffer) error { + if err := err.PostInfo.Encode(buffer); err != nil { + return err } - e.PostInfo = postInfo - dispatchError, err := DecodeDispatchError(buffer) + if _, ok := err.Err.(DispatchError); ok { + return err.Err.(DispatchError).Encode(buffer) + } + + return nil +} + +func DecodeErrorWithPostInfo(buffer *bytes.Buffer) error { + postInfo, err := DecodePostDispatchInfo(buffer) if err != nil { - return DispatchErrorWithPostInfo[PostDispatchInfo]{}, err + return err } - e.Error = dispatchError - return e, nil + + return DispatchErrorWithPostInfo[PostDispatchInfo]{PostInfo: postInfo, Err: DecodeDispatchError(buffer)} } -func (e DispatchErrorWithPostInfo[PostDispatchInfo]) Bytes() []byte { - return sc.EncodedBytes(e) +func (err DispatchErrorWithPostInfo[PostDispatchInfo]) Bytes() []byte { + return sc.EncodedBytes(err) } diff --git a/primitives/types/dispatch_errors_test.go b/primitives/types/dispatch_errors_test.go index 055017db..ec964140 100644 --- a/primitives/types/dispatch_errors_test.go +++ b/primitives/types/dispatch_errors_test.go @@ -48,11 +48,7 @@ func Test_DecodeDispatchError(t *testing.T) { t.Run(testExample.label, func(t *testing.T) { buffer := &bytes.Buffer{} buffer.Write(testExample.input) - - result, err := DecodeDispatchError(buffer) - assert.NoError(t, err) - - assert.Equal(t, testExample.expectation, result) + assert.Equal(t, testExample.expectation, DecodeDispatchError(buffer)) }) } } diff --git a/primitives/types/dispatch_outcome.go b/primitives/types/dispatch_outcome.go index 5339fb1b..09c67dbc 100644 --- a/primitives/types/dispatch_outcome.go +++ b/primitives/types/dispatch_outcome.go @@ -56,11 +56,11 @@ func DecodeDispatchOutcome(buffer *bytes.Buffer) (DispatchOutcome, error) { case 0: return NewDispatchOutcome(sc.Empty{}) case 1: - value, err := DecodeDispatchError(buffer) - if err != nil { - return DispatchOutcome{}, err + dispatchErr := DecodeDispatchError(buffer) + if _, ok := dispatchErr.(DispatchError); !ok { + return DispatchOutcome{}, dispatchErr } - return NewDispatchOutcome(value) + return NewDispatchOutcome(dispatchErr.(DispatchError)) default: return DispatchOutcome{}, newTypeError("DispatchOutcome") } diff --git a/primitives/types/dispatch_result_test.go b/primitives/types/dispatch_result_test.go index 8d08a3ad..16b720f8 100644 --- a/primitives/types/dispatch_result_test.go +++ b/primitives/types/dispatch_result_test.go @@ -17,7 +17,7 @@ var ( dispatchErrorWithPostInfo = DispatchErrorWithPostInfo[PostDispatchInfo]{ PostInfo: postDispatchInfoWithFee, - Error: dispatchError, + Err: dispatchError, } ) diff --git a/primitives/types/dispatch_result_with_post_info_test.go b/primitives/types/dispatch_result_with_post_info_test.go index c39ad8da..e8b2c2ef 100644 --- a/primitives/types/dispatch_result_with_post_info_test.go +++ b/primitives/types/dispatch_result_with_post_info_test.go @@ -31,7 +31,7 @@ func Test_ExtractActualWeight_DispatchResultOk(t *testing.T) { Ok: postDispatchInfoOk, Err: DispatchErrorWithPostInfo[PostDispatchInfo]{ PostInfo: postDispatchInfoErr, - Error: NewDispatchErrorBadOrigin(), + Err: NewDispatchErrorBadOrigin(), }, } @@ -46,7 +46,7 @@ func Test_ExtractActualWeight_DispatchResultErr(t *testing.T) { Ok: postDispatchInfoOk, Err: DispatchErrorWithPostInfo[PostDispatchInfo]{ PostInfo: postDispatchInfoErr, - Error: NewDispatchErrorBadOrigin(), + Err: NewDispatchErrorBadOrigin(), }, } @@ -61,7 +61,7 @@ func Test_ExtractActualPaysFee_DispatchResultOk(t *testing.T) { Ok: postDispatchInfoOk, Err: DispatchErrorWithPostInfo[PostDispatchInfo]{ PostInfo: postDispatchInfoErr, - Error: NewDispatchErrorBadOrigin(), + Err: NewDispatchErrorBadOrigin(), }, } @@ -76,7 +76,7 @@ func Test_ExtractActualPaysFee_DispatchResultErr(t *testing.T) { Ok: postDispatchInfoOk, Err: DispatchErrorWithPostInfo[PostDispatchInfo]{ PostInfo: postDispatchInfoErr, - Error: NewDispatchErrorBadOrigin(), + Err: NewDispatchErrorBadOrigin(), }, } diff --git a/primitives/types/errors.go b/primitives/types/errors.go index edd7ab4a..e7fa4231 100644 --- a/primitives/types/errors.go +++ b/primitives/types/errors.go @@ -10,6 +10,6 @@ func newTypeError(msg string) error { return typeError{message: msg} } -func (e typeError) Error() string { - return "not a valid '" + e.message + "' type" +func (err typeError) Error() string { + return "not a valid '" + err.message + "' type" } diff --git a/primitives/types/extra.go b/primitives/types/extra.go index 78a9e2ec..730bf016 100644 --- a/primitives/types/extra.go +++ b/primitives/types/extra.go @@ -12,12 +12,12 @@ type SignedExtra interface { Decode(buffer *bytes.Buffer) - AdditionalSigned() (AdditionalSigned, TransactionValidityError) - Validate(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) - ValidateUnsigned(call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) - PreDispatch(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (sc.Sequence[Pre], TransactionValidityError) - PreDispatchUnsigned(call Call, info *DispatchInfo, length sc.Compact) TransactionValidityError - PostDispatch(pre sc.Option[sc.Sequence[Pre]], info *DispatchInfo, postInfo *PostDispatchInfo, length sc.Compact, result *DispatchResult) TransactionValidityError + AdditionalSigned() (AdditionalSigned, error) + Validate(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) + ValidateUnsigned(call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) + PreDispatch(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (sc.Sequence[Pre], error) + PreDispatchUnsigned(call Call, info *DispatchInfo, length sc.Compact) error + PostDispatch(pre sc.Option[sc.Sequence[Pre]], info *DispatchInfo, postInfo *PostDispatchInfo, length sc.Compact, result *DispatchResult) error Metadata() (sc.Sequence[MetadataType], sc.Sequence[MetadataSignedExtension]) } @@ -53,7 +53,7 @@ func (e signedExtra) Decode(buffer *bytes.Buffer) { } } -func (e signedExtra) AdditionalSigned() (AdditionalSigned, TransactionValidityError) { +func (e signedExtra) AdditionalSigned() (AdditionalSigned, error) { result := AdditionalSigned{} for _, extra := range e.extras { @@ -67,7 +67,7 @@ func (e signedExtra) AdditionalSigned() (AdditionalSigned, TransactionValidityEr return result, nil } -func (e signedExtra) Validate(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) { +func (e signedExtra) Validate(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) { valid := DefaultValidTransaction() for _, extra := range e.extras { @@ -81,7 +81,7 @@ func (e signedExtra) Validate(who AccountId[PublicKey], call Call, info *Dispatc return valid, nil } -func (e signedExtra) ValidateUnsigned(call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) { +func (e signedExtra) ValidateUnsigned(call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) { valid := DefaultValidTransaction() for _, extra := range e.extras { @@ -95,7 +95,7 @@ func (e signedExtra) ValidateUnsigned(call Call, info *DispatchInfo, length sc.C return valid, nil } -func (e signedExtra) PreDispatch(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (sc.Sequence[Pre], TransactionValidityError) { +func (e signedExtra) PreDispatch(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (sc.Sequence[Pre], error) { pre := sc.Sequence[Pre]{} for _, extra := range e.extras { @@ -110,7 +110,7 @@ func (e signedExtra) PreDispatch(who AccountId[PublicKey], call Call, info *Disp return pre, nil } -func (e signedExtra) PreDispatchUnsigned(call Call, info *DispatchInfo, length sc.Compact) TransactionValidityError { +func (e signedExtra) PreDispatchUnsigned(call Call, info *DispatchInfo, length sc.Compact) error { for _, extra := range e.extras { err := extra.PreDispatchUnsigned(call, info, length) if err != nil { @@ -121,7 +121,7 @@ func (e signedExtra) PreDispatchUnsigned(call Call, info *DispatchInfo, length s return nil } -func (e signedExtra) PostDispatch(pre sc.Option[sc.Sequence[Pre]], info *DispatchInfo, postInfo *PostDispatchInfo, length sc.Compact, result *DispatchResult) TransactionValidityError { +func (e signedExtra) PostDispatch(pre sc.Option[sc.Sequence[Pre]], info *DispatchInfo, postInfo *PostDispatchInfo, length sc.Compact, result *DispatchResult) error { if pre.HasValue { preValue := pre.Value for i, extra := range e.extras { diff --git a/primitives/types/extra_test.go b/primitives/types/extra_test.go index 7937e7f0..125bdbc8 100644 --- a/primitives/types/extra_test.go +++ b/primitives/types/extra_test.go @@ -21,7 +21,7 @@ var ( Propagate: true, } - expectedTransactionValidityError, _ = NewTransactionValidityError(NewUnknownTransactionCustomUnknownTransaction(sc.U8(0))) + expectedTransactionValidityError = NewTransactionValidityError(NewUnknownTransactionCustomUnknownTransaction(sc.U8(0))) testExtraCheckMetadataType = MetadataType{ Id: sc.ToCompact(123456), diff --git a/primitives/types/extrinsic_signature_payload.go b/primitives/types/extrinsic_signature_payload.go index 27e2c32d..2245e765 100644 --- a/primitives/types/extrinsic_signature_payload.go +++ b/primitives/types/extrinsic_signature_payload.go @@ -29,7 +29,7 @@ type signedPayload struct { // NewSignedPayload creates a new `SignedPayload`. // It may fail if `additional_signed` of `Extra` is not available. -func NewSignedPayload(call Call, extra SignedExtra) (SignedPayload, TransactionValidityError) { +func NewSignedPayload(call Call, extra SignedExtra) (SignedPayload, error) { additionalSigned, err := extra.AdditionalSigned() if err != nil { return signedPayload{}, err diff --git a/primitives/types/extrinsic_signature_payload_test.go b/primitives/types/extrinsic_signature_payload_test.go index 12ece882..cd1cc942 100644 --- a/primitives/types/extrinsic_signature_payload_test.go +++ b/primitives/types/extrinsic_signature_payload_test.go @@ -14,7 +14,7 @@ var ( expectedAdditionalSigned = sc.NewVaryingData(sc.U32(1)) - expectedTransactionValidityErr, _ = NewTransactionValidityError(NewUnknownTransactionCustomUnknownTransaction(sc.U8(0))) + expectedTransactionValidityErr = NewTransactionValidityError(NewUnknownTransactionCustomUnknownTransaction(sc.U8(0))) ) var ( diff --git a/primitives/types/invalid_transaction.go b/primitives/types/invalid_transaction.go index f37f9ddc..fea71271 100644 --- a/primitives/types/invalid_transaction.go +++ b/primitives/types/invalid_transaction.go @@ -112,6 +112,39 @@ func NewInvalidTransactionBadSigner() InvalidTransaction { return InvalidTransaction{sc.NewVaryingData(InvalidTransactionBadSigner)} } +func (err InvalidTransaction) Error() string { + if len(err.VaryingData) == 0 { + return "" + } + + switch err.VaryingData[0] { + case InvalidTransactionCall: + return "Transaction call is not expected" + case InvalidTransactionPayment: + return "Inability to pay some fees (e.g. account balance too low)" + case InvalidTransactionFuture: + return "Transaction will be valid in the future" + case InvalidTransactionStale: + return "Transaction is outdated" + case InvalidTransactionBadProof: + return "Transaction has a bad signature" + case InvalidTransactionAncientBirthBlock: + return "Transaction has an ancient birth block" + case InvalidTransactionExhaustsResources: + return "Transaction would exhaust the block limits" + case InvalidTransactionCustom: + return "InvalidTransaction custom error" + case InvalidTransactionBadMandatory: + return "A call was labelled as mandatory, but resulted in an Error." + case InvalidTransactionMandatoryValidation: + return "Transaction dispatch is mandatory; transactions must not be validated." + case InvalidTransactionBadSigner: + return "Invalid signing address" + default: + return "" + } +} + func DecodeInvalidTransaction(buffer *bytes.Buffer) (InvalidTransaction, error) { b, err := sc.DecodeU8(buffer) if err != nil { diff --git a/primitives/types/lookup.go b/primitives/types/lookup.go index 0aceaa44..685720c6 100644 --- a/primitives/types/lookup.go +++ b/primitives/types/lookup.go @@ -2,15 +2,16 @@ package types import sc "github.com/LimeChain/goscale" -func Lookup(a MultiAddress) (AccountId[PublicKey], TransactionValidityError) { - // TODO https://github.com/LimeChain/gosemble/issues/271 - address, _ := lookupAddress(a) +func Lookup(a MultiAddress) (AccountId[PublicKey], error) { + address, err := lookupAddress(a) + if err != nil { + return AccountId[PublicKey]{}, err + } if address.HasValue { return address.Value, nil } - unknownTransactionCannotLookup, _ := NewTransactionValidityError(NewUnknownTransactionCannotLookup()) - return AccountId[PublicKey]{}, unknownTransactionCannotLookup + return AccountId[PublicKey]{}, NewTransactionValidityError(NewUnknownTransactionCannotLookup()) } // LookupAddress Lookup an address to get an Id, if there's one there. diff --git a/primitives/types/lookup_test.go b/primitives/types/lookup_test.go index 0455bdf3..f4cff201 100644 --- a/primitives/types/lookup_test.go +++ b/primitives/types/lookup_test.go @@ -15,7 +15,7 @@ var ( expectedAccountId = NewAccountId[PublicKey](ed25519SignerOnesAddress) invalidMultiAddress = MultiAddress{sc.NewVaryingData(sc.U8(5), sc.ToCompact(accountIndex))} - expectedTransactionCannotLookupErr, _ = NewTransactionValidityError(NewUnknownTransactionCannotLookup()) + expectedTransactionCannotLookupErr = NewTransactionValidityError(NewUnknownTransactionCannotLookup()) ) func Test_Lookup_AccountId(t *testing.T) { diff --git a/primitives/types/module.go b/primitives/types/module.go index 03724f73..7c27fe46 100644 --- a/primitives/types/module.go +++ b/primitives/types/module.go @@ -12,8 +12,8 @@ type Module interface { DispatchModule GetIndex() sc.U8 Functions() map[sc.U8]Call - PreDispatch(call Call) (sc.Empty, TransactionValidityError) - ValidateUnsigned(source TransactionSource, call Call) (ValidTransaction, TransactionValidityError) + PreDispatch(call Call) (sc.Empty, error) + ValidateUnsigned(source TransactionSource, call Call) (ValidTransaction, error) Metadata() (sc.Sequence[MetadataType], MetadataModule) } diff --git a/primitives/types/signed_extension.go b/primitives/types/signed_extension.go index 8bd0c15b..c05b6d66 100644 --- a/primitives/types/signed_extension.go +++ b/primitives/types/signed_extension.go @@ -34,7 +34,7 @@ type SignedExtension interface { // Construct any additional data that should be in the signed payload of the transaction. Can // also perform any pre-signature-verification checks and return an error if needed. - AdditionalSigned() (AdditionalSigned, TransactionValidityError) + AdditionalSigned() (AdditionalSigned, error) // Validate a signed transaction for the transaction queue. // @@ -45,12 +45,12 @@ type SignedExtension interface { // that are stale or incorrect. // // Make sure to perform the same checks in `pre_dispatch` function. - Validate(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) + Validate(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) // Do any pre-flight stuff for a signed transaction. // // Make sure to perform the same checks as in [`Self::validate`]. - PreDispatch(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (Pre, TransactionValidityError) + PreDispatch(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (Pre, error) // Validate an unsigned transaction for the transaction queue. // @@ -60,7 +60,7 @@ type SignedExtension interface { // and quickly eliminate ones that are stale or incorrect. // // Make sure to perform the same checks in `pre_dispatch_unsigned` function. - ValidateUnsigned(call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) + ValidateUnsigned(call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) // Do any pre-flight stuff for a unsigned transaction. // @@ -70,7 +70,7 @@ type SignedExtension interface { // // If you ever override this function, you need to make sure to always // perform the same validation as in `validate_unsigned`. - PreDispatchUnsigned(call Call, info *DispatchInfo, length sc.Compact) TransactionValidityError + PreDispatchUnsigned(call Call, info *DispatchInfo, length sc.Compact) error // Do any post-flight stuff for an extrinsic. // @@ -88,7 +88,7 @@ type SignedExtension interface { // It can only be used safely when you *know* that the extrinsic is one that can only be // introduced by the current block author; generally this implies that it is an inherent and // will come from either an offchain-worker or via `InherentData`.( - PostDispatch(pre sc.Option[Pre], info *DispatchInfo, postInfo *PostDispatchInfo, length sc.Compact, result *DispatchResult) TransactionValidityError + PostDispatch(pre sc.Option[Pre], info *DispatchInfo, postInfo *PostDispatchInfo, length sc.Compact, result *DispatchResult) error Metadata() (MetadataType, MetadataSignedExtension) } diff --git a/primitives/types/testextra_test.go b/primitives/types/testextra_test.go index 520a127e..59e0bc33 100644 --- a/primitives/types/testextra_test.go +++ b/primitives/types/testextra_test.go @@ -7,7 +7,7 @@ import ( ) var ( - unknownTransactionCustomUnknownTransaction, _ = NewTransactionValidityError(NewUnknownTransactionCustomUnknownTransaction(sc.U8(0))) + unknownTransactionCustomUnknownTransaction = NewTransactionValidityError(NewUnknownTransactionCustomUnknownTransaction(sc.U8(0))) ) type testExtraCheck struct { @@ -47,7 +47,7 @@ func (e *testExtraCheck) Decode(buffer *bytes.Buffer) error { return nil } -func (e testExtraCheck) AdditionalSigned() (AdditionalSigned, TransactionValidityError) { +func (e testExtraCheck) AdditionalSigned() (AdditionalSigned, error) { if e.hasError { return nil, unknownTransactionCustomUnknownTransaction } @@ -55,7 +55,7 @@ func (e testExtraCheck) AdditionalSigned() (AdditionalSigned, TransactionValidit return sc.NewVaryingData(e.value), nil } -func (e testExtraCheck) Validate(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) { +func (e testExtraCheck) Validate(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) { validTransaction := DefaultValidTransaction() validTransaction.Priority = 1 @@ -66,21 +66,21 @@ func (e testExtraCheck) Validate(who AccountId[PublicKey], call Call, info *Disp return validTransaction, nil } -func (e testExtraCheck) ValidateUnsigned(call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, TransactionValidityError) { +func (e testExtraCheck) ValidateUnsigned(call Call, info *DispatchInfo, length sc.Compact) (ValidTransaction, error) { return e.Validate(AccountId[PublicKey]{}, call, info, length) } -func (e testExtraCheck) PreDispatch(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (Pre, TransactionValidityError) { +func (e testExtraCheck) PreDispatch(who AccountId[PublicKey], call Call, info *DispatchInfo, length sc.Compact) (Pre, error) { _, err := e.Validate(who, call, info, length) return Pre{}, err } -func (e testExtraCheck) PreDispatchUnsigned(call Call, info *DispatchInfo, length sc.Compact) TransactionValidityError { +func (e testExtraCheck) PreDispatchUnsigned(call Call, info *DispatchInfo, length sc.Compact) error { _, err := e.ValidateUnsigned(call, info, length) return err } -func (e testExtraCheck) PostDispatch(pre sc.Option[Pre], info *DispatchInfo, postInfo *PostDispatchInfo, length sc.Compact, result *DispatchResult) TransactionValidityError { +func (e testExtraCheck) PostDispatch(pre sc.Option[Pre], info *DispatchInfo, postInfo *PostDispatchInfo, length sc.Compact, result *DispatchResult) error { if e.hasError { return unknownTransactionCustomUnknownTransaction } diff --git a/primitives/types/token_error.go b/primitives/types/token_error.go index d0b0e904..26e6e4b4 100644 --- a/primitives/types/token_error.go +++ b/primitives/types/token_error.go @@ -16,58 +16,85 @@ const ( TokenErrorUnsupported ) -type TokenError = sc.VaryingData +type TokenError struct { + sc.VaryingData +} func NewTokenErrorNoFounds() TokenError { - return sc.NewVaryingData(TokenErrorNoFunds) + return TokenError{sc.NewVaryingData(TokenErrorNoFunds)} } func NewTokenErrorWouldDie() TokenError { - return sc.NewVaryingData(TokenErrorWouldDie) + return TokenError{sc.NewVaryingData(TokenErrorWouldDie)} } func NewTokenErrorBelowMinimum() TokenError { - return sc.NewVaryingData(TokenErrorBelowMinimum) + return TokenError{sc.NewVaryingData(TokenErrorBelowMinimum)} } func NewTokenErrorCannotCreate() TokenError { - return sc.NewVaryingData(TokenErrorCannotCreate) + return TokenError{sc.NewVaryingData(TokenErrorCannotCreate)} } func NewTokenErrorUnknownAsset() TokenError { - return sc.NewVaryingData(TokenErrorUnknownAsset) + return TokenError{sc.NewVaryingData(TokenErrorUnknownAsset)} } func NewTokenErrorFrozen() TokenError { - return sc.NewVaryingData(TokenErrorFrozen) + return TokenError{sc.NewVaryingData(TokenErrorFrozen)} } func NewTokenErrorUnsupported() TokenError { - return sc.NewVaryingData(TokenErrorUnsupported) + return TokenError{sc.NewVaryingData(TokenErrorUnsupported)} +} + +func (err TokenError) Error() string { + if len(err.VaryingData) == 0 { + return "" + } + + switch err.VaryingData[0] { + case TokenErrorNoFunds: + return "Funds are unavailable" + case TokenErrorWouldDie: + return "Account that must exist would die" + case TokenErrorBelowMinimum: + return "Account cannot exist with the funds that would be given" + case TokenErrorCannotCreate: + return "Account cannot be created" + case TokenErrorUnknownAsset: + return "The asset in question is unknown" + case TokenErrorFrozen: + return "Funds exist but are frozen" + case TokenErrorUnsupported: + return "Operation is not supported by the asset" + default: + return "" + } } -func DecodeTokenError(buffer *bytes.Buffer) (TokenError, error) { +func DecodeTokenError(buffer *bytes.Buffer) error { b, err := sc.DecodeU8(buffer) if err != nil { - return nil, err + return err } switch b { case TokenErrorNoFunds: - return NewTokenErrorNoFounds(), nil + return NewTokenErrorNoFounds() case TokenErrorWouldDie: - return NewTokenErrorWouldDie(), nil + return NewTokenErrorWouldDie() case TokenErrorBelowMinimum: - return NewTokenErrorBelowMinimum(), nil + return NewTokenErrorBelowMinimum() case TokenErrorCannotCreate: - return NewTokenErrorCannotCreate(), nil + return NewTokenErrorCannotCreate() case TokenErrorUnknownAsset: - return NewTokenErrorUnknownAsset(), nil + return NewTokenErrorUnknownAsset() case TokenErrorFrozen: - return NewTokenErrorFrozen(), nil + return NewTokenErrorFrozen() case TokenErrorUnsupported: - return NewTokenErrorUnsupported(), nil + return NewTokenErrorUnsupported() default: - return nil, newTypeError("TokenError") + return newTypeError("TokenError") } } diff --git a/primitives/types/token_error_test.go b/primitives/types/token_error_test.go index eddbfa5d..673fa03b 100644 --- a/primitives/types/token_error_test.go +++ b/primitives/types/token_error_test.go @@ -9,110 +9,77 @@ import ( ) func Test_NewTokenErrorNoFunds(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TokenErrorNoFunds), NewTokenErrorNoFounds()) + assert.Equal(t, TokenError{sc.NewVaryingData(TokenErrorNoFunds)}, NewTokenErrorNoFounds()) } func Test_NewTokenErrorWouldDie(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TokenErrorWouldDie), NewTokenErrorWouldDie()) + assert.Equal(t, TokenError{sc.NewVaryingData(TokenErrorWouldDie)}, NewTokenErrorWouldDie()) } func Test_NewTokenErrorBelowMinimum(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TokenErrorBelowMinimum), NewTokenErrorBelowMinimum()) + assert.Equal(t, TokenError{sc.NewVaryingData(TokenErrorBelowMinimum)}, NewTokenErrorBelowMinimum()) } func Test_NewTokenErrorCannotCreate(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TokenErrorCannotCreate), NewTokenErrorCannotCreate()) + assert.Equal(t, TokenError{sc.NewVaryingData(TokenErrorCannotCreate)}, NewTokenErrorCannotCreate()) } func Test_NewTokenErrorUnknownAsset(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TokenErrorUnknownAsset), NewTokenErrorUnknownAsset()) + assert.Equal(t, TokenError{sc.NewVaryingData(TokenErrorUnknownAsset)}, NewTokenErrorUnknownAsset()) } func Test_NewTokenErrorFrozen(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TokenErrorFrozen), NewTokenErrorFrozen()) + assert.Equal(t, TokenError{sc.NewVaryingData(TokenErrorFrozen)}, NewTokenErrorFrozen()) } func Test_NewTokenErrorUnsupported(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TokenErrorUnsupported), NewTokenErrorUnsupported()) + assert.Equal(t, TokenError{sc.NewVaryingData(TokenErrorUnsupported)}, NewTokenErrorUnsupported()) } func Test_DecodeTokenError_NoFunds(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(0) - - result, err := DecodeTokenError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTokenErrorNoFounds(), result) + assert.Equal(t, NewTokenErrorNoFounds(), DecodeTokenError(buffer)) } func Test_DecodeTokenError_WouldDie(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(1) - - result, err := DecodeTokenError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTokenErrorWouldDie(), result) + assert.Equal(t, NewTokenErrorWouldDie(), DecodeTokenError(buffer)) } func Test_DecodeTokenError_BelowMinimum(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(2) - - result, err := DecodeTokenError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTokenErrorBelowMinimum(), result) + assert.Equal(t, NewTokenErrorBelowMinimum(), DecodeTokenError(buffer)) } func Test_DecodeTokenError_CannotCreate(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(3) - - result, err := DecodeTokenError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTokenErrorCannotCreate(), result) + assert.Equal(t, NewTokenErrorCannotCreate(), DecodeTokenError(buffer)) } func Test_DecodeTokenError_UnknownAsset(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(4) - - result, err := DecodeTokenError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTokenErrorUnknownAsset(), result) + assert.Equal(t, NewTokenErrorUnknownAsset(), DecodeTokenError(buffer)) } func Test_DecodeTokenError_Frozen(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(5) - - result, err := DecodeTokenError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTokenErrorFrozen(), result) + assert.Equal(t, NewTokenErrorFrozen(), DecodeTokenError(buffer)) } func Test_DecodeTokenError_Unsupported(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(6) - - result, err := DecodeTokenError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTokenErrorUnsupported(), result) + assert.Equal(t, NewTokenErrorUnsupported(), DecodeTokenError(buffer)) } func Test_DecodeTokenError_TypeError(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(7) - - res, err := DecodeTokenError(buffer) - - assert.Error(t, err) - assert.Equal(t, "not a valid 'TokenError' type", err.Error()) - assert.Nil(t, res) + assert.Equal(t, "not a valid 'TokenError' type", DecodeTokenError(buffer).Error()) } diff --git a/primitives/types/transaction_validity_error.go b/primitives/types/transaction_validity_error.go index 2724fc21..4ee178ec 100644 --- a/primitives/types/transaction_validity_error.go +++ b/primitives/types/transaction_validity_error.go @@ -19,15 +19,32 @@ const ( // TransactionValidityError Errors that can occur while checking the validity of a transaction. type TransactionValidityError sc.VaryingData -func NewTransactionValidityError(value sc.Encodable) (TransactionValidityError, error) { +func NewTransactionValidityError(value sc.Encodable) error { + // todo CONSIDER returning only error just like the rest + // InvalidTransaction = 0 - Transaction is invalid. // UnknownTransaction = 1 - Transaction validity can’t be determined. switch value.(type) { case InvalidTransaction, UnknownTransaction: default: - return TransactionValidityError{}, errInvalidTransactionValidityErrorType + return errInvalidTransactionValidityErrorType + } + return TransactionValidityError(sc.NewVaryingData(value)) +} + +func (err TransactionValidityError) Error() string { + if len(err) == 0 { + return "" + } + + switch txErr := err[0]; txErr { + case TransactionValidityErrorUnknownTransaction: + return txErr.(UnknownTransaction).Error() + case TransactionValidityErrorInvalidTransaction: + return txErr.(InvalidTransaction).Error() + default: + return "" } - return TransactionValidityError(sc.NewVaryingData(value)), nil } func (e TransactionValidityError) Encode(buffer *bytes.Buffer) error { @@ -51,27 +68,27 @@ func (e TransactionValidityError) Encode(buffer *bytes.Buffer) error { return value.Encode(buffer) } -func DecodeTransactionValidityError(buffer *bytes.Buffer) (TransactionValidityError, error) { +func DecodeTransactionValidityError(buffer *bytes.Buffer) error { b, err := sc.DecodeU8(buffer) if err != nil { - return TransactionValidityError{}, err + return err } switch b { case TransactionValidityErrorInvalidTransaction: value, err := DecodeInvalidTransaction(buffer) if err != nil { - return TransactionValidityError{}, err + return err } return NewTransactionValidityError(value) case TransactionValidityErrorUnknownTransaction: value, err := DecodeUnknownTransaction(buffer) if err != nil { - return TransactionValidityError{}, err + return err } return NewTransactionValidityError(value) default: - return TransactionValidityError{}, errInvalidTransactionValidityErrorType + return errInvalidTransactionValidityErrorType } } diff --git a/primitives/types/transaction_validity_error_test.go b/primitives/types/transaction_validity_error_test.go index 3ab9236b..961fd3ee 100644 --- a/primitives/types/transaction_validity_error_test.go +++ b/primitives/types/transaction_validity_error_test.go @@ -10,21 +10,20 @@ import ( ) var ( - unknownTransactionCannotLookup, _ = NewTransactionValidityError(NewUnknownTransactionCannotLookup()) + unknownTransactionCannotLookup = NewTransactionValidityError(NewUnknownTransactionCannotLookup()) ) func Test_NewTransactionValidityError_TypeError(t *testing.T) { - result, err := NewTransactionValidityError(sc.U8(6)) - - assert.Error(t, err) - assert.Equal(t, "not a valid 'TransactionValidityError' type", err.Error()) - assert.Equal(t, TransactionValidityError{}, result) + txErr := NewTransactionValidityError(sc.U8(6)) + _, ok := txErr.(TransactionValidityError) + assert.False(t, ok) + assert.Equal(t, "not a valid 'TransactionValidityError' type", txErr.Error()) } func Test_TransactionValidityError_Encode(t *testing.T) { var testExamples = []struct { label string - input TransactionValidityError + input error expectation []byte }{ { @@ -42,10 +41,7 @@ func Test_TransactionValidityError_Encode(t *testing.T) { for _, testExample := range testExamples { t.Run(testExample.label, func(t *testing.T) { buffer := &bytes.Buffer{} - - err := testExample.input.Encode(buffer) - - assert.NoError(t, err) + assert.NoError(t, testExample.input.(TransactionValidityError).Encode(buffer)) assert.Equal(t, testExample.expectation, buffer.Bytes()) }) } @@ -67,7 +63,7 @@ func Test_DecodeTransactionValidityError(t *testing.T) { var testExamples = []struct { label string input []byte - expectation TransactionValidityError + expectation error }{ { label: "Encode(TransactionValidityError(InvalidTransaction(PaymentError)))", @@ -85,11 +81,7 @@ func Test_DecodeTransactionValidityError(t *testing.T) { t.Run(testExample.label, func(t *testing.T) { buffer := &bytes.Buffer{} buffer.Write(testExample.input) - - result, err := DecodeTransactionValidityError(buffer) - assert.NoError(t, err) - - assert.Equal(t, testExample.expectation, result) + assert.Equal(t, testExample.expectation, DecodeTransactionValidityError(buffer)) }) } } @@ -98,16 +90,14 @@ func Test_DecodeTransactionValidityError_TypeError(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(6) - res, err := DecodeTransactionValidityError(buffer) - - assert.Error(t, err) - assert.Equal(t, "not a valid 'TransactionValidityError' type", err.Error()) - assert.Equal(t, TransactionValidityError{}, res) - + txErr := DecodeTransactionValidityError(buffer) + _, ok := txErr.(TransactionValidityError) + assert.False(t, ok) + assert.Equal(t, "not a valid 'TransactionValidityError' type", txErr.Error()) } func Test_TransactionValidityError_Bytes(t *testing.T) { expect, _ := hex.DecodeString("0001") - assert.Equal(t, expect, invalidTransactionPayment.Bytes()) + assert.Equal(t, expect, invalidTransactionPayment.(TransactionValidityError).Bytes()) } diff --git a/primitives/types/transaction_validity_result.go b/primitives/types/transaction_validity_result.go index 7a0d2646..260ddf4d 100644 --- a/primitives/types/transaction_validity_result.go +++ b/primitives/types/transaction_validity_result.go @@ -56,11 +56,11 @@ func DecodeTransactionValidityResult(buffer *bytes.Buffer) (TransactionValidityR } return NewTransactionValidityResult(val) case TransactionValidityResultError: - val, err := DecodeTransactionValidityError(buffer) - if err != nil { - return TransactionValidityResult{}, err + txErr := DecodeTransactionValidityError(buffer) + if _, ok := txErr.(TransactionValidityError); !ok { + return TransactionValidityResult{}, txErr } - return NewTransactionValidityResult(val) + return NewTransactionValidityResult(txErr.(TransactionValidityError)) default: return TransactionValidityResult{}, newTypeError("TransactionValidityResult") } diff --git a/primitives/types/transaction_validity_result_test.go b/primitives/types/transaction_validity_result_test.go index 11f97be7..75bf4053 100644 --- a/primitives/types/transaction_validity_result_test.go +++ b/primitives/types/transaction_validity_result_test.go @@ -10,9 +10,9 @@ import ( ) var ( - invalidTransactionPayment, _ = NewTransactionValidityError(NewInvalidTransactionPayment()) + invalidTransactionPayment = NewTransactionValidityError(NewInvalidTransactionPayment()) - transactionValidityResultTransactionPayment, _ = NewTransactionValidityResult(invalidTransactionPayment) + transactionValidityResultTransactionPayment, _ = NewTransactionValidityResult(invalidTransactionPayment.(TransactionValidityError)) transactionValidityResultDefaultValid, _ = NewTransactionValidityResult(DefaultValidTransaction()) ) @@ -38,7 +38,7 @@ func Test_TransactionValidityResult_Encode(t *testing.T) { { label: "Encode(TransactionValidityResult(TransactionValidityError))", input: transactionValidityResultTransactionPayment, - expect: append(TransactionValidityResultError.Bytes(), invalidTransactionPayment.Bytes()...), + expect: append(TransactionValidityResultError.Bytes(), invalidTransactionPayment.(TransactionValidityError).Bytes()...), }, } diff --git a/primitives/types/transactional_error.go b/primitives/types/transactional_error.go index 8d9839c6..e8aafeb3 100644 --- a/primitives/types/transactional_error.go +++ b/primitives/types/transactional_error.go @@ -13,28 +13,45 @@ const ( TransactionalErrorNoLayer ) -type TransactionalError = sc.VaryingData +type TransactionalError struct { + sc.VaryingData +} func NewTransactionalErrorLimitReached() TransactionalError { - return sc.NewVaryingData(TransactionalErrorLimitReached) + return TransactionalError{sc.NewVaryingData(TransactionalErrorLimitReached)} } func NewTransactionalErrorNoLayer() TransactionalError { - return sc.NewVaryingData(TransactionalErrorNoLayer) + return TransactionalError{sc.NewVaryingData(TransactionalErrorNoLayer)} +} + +func (err TransactionalError) Error() string { + if len(err.VaryingData) == 0 { + return "" + } + + switch err.VaryingData[0] { + case TransactionalErrorLimitReached: + return "Too many transactional layers have been spawned" + case TransactionalErrorNoLayer: + return "A transactional layer was expected, but does not exist" + default: + return "" + } } -func DecodeTransactionalError(buffer *bytes.Buffer) (TransactionalError, error) { +func DecodeTransactionalError(buffer *bytes.Buffer) error { b, err := sc.DecodeU8(buffer) if err != nil { - return TransactionalError{}, err + return err } switch b { case TransactionalErrorLimitReached: - return NewTransactionalErrorLimitReached(), nil + return NewTransactionalErrorLimitReached() case TransactionalErrorNoLayer: - return NewTransactionalErrorNoLayer(), nil + return NewTransactionalErrorNoLayer() default: - return nil, newTypeError("TransactionalError") + return newTypeError("TransactionalError") } } diff --git a/primitives/types/transactional_error_test.go b/primitives/types/transactional_error_test.go index 8f686762..d571fae6 100644 --- a/primitives/types/transactional_error_test.go +++ b/primitives/types/transactional_error_test.go @@ -9,40 +9,27 @@ import ( ) func Test_NewTransactionalErrorLimitReached(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TransactionalErrorLimitReached), NewTransactionalErrorLimitReached()) + assert.Equal(t, TransactionalError{sc.NewVaryingData(TransactionalErrorLimitReached)}, NewTransactionalErrorLimitReached()) } func Test_NewTransactionalErrorNoLayer(t *testing.T) { - assert.Equal(t, sc.NewVaryingData(TransactionalErrorNoLayer), NewTransactionalErrorNoLayer()) + assert.Equal(t, TransactionalError{sc.NewVaryingData(TransactionalErrorNoLayer)}, NewTransactionalErrorNoLayer()) } func Test_DecodeTransactionalError_LimitReached(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(0) - - result, err := DecodeTransactionalError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTransactionalErrorLimitReached(), result) + assert.Equal(t, NewTransactionalErrorLimitReached(), DecodeTransactionalError(buffer)) } func Test_DecodeTransactionalError_NoLayer(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(1) - - result, err := DecodeTransactionalError(buffer) - assert.NoError(t, err) - - assert.Equal(t, NewTransactionalErrorNoLayer(), result) + assert.Equal(t, NewTransactionalErrorNoLayer(), DecodeTransactionalError(buffer)) } func Test_DecodeTransactionalError_TypeError(t *testing.T) { buffer := &bytes.Buffer{} buffer.WriteByte(5) - - res, err := DecodeTransactionalError(buffer) - - assert.Error(t, err) - assert.Equal(t, "not a valid 'TransactionalError' type", err.Error()) - assert.Nil(t, res) + assert.Equal(t, "not a valid 'TransactionalError' type", DecodeTransactionalError(buffer).Error()) } diff --git a/primitives/types/unchecked_extrinsic.go b/primitives/types/unchecked_extrinsic.go index c417e20f..b7a9ae19 100644 --- a/primitives/types/unchecked_extrinsic.go +++ b/primitives/types/unchecked_extrinsic.go @@ -10,5 +10,5 @@ type UncheckedExtrinsic interface { Extra() SignedExtra IsSigned() bool - Check() (CheckedExtrinsic, TransactionValidityError) + Check() (CheckedExtrinsic, error) } diff --git a/primitives/types/unknown_transaction.go b/primitives/types/unknown_transaction.go index 8ec64faa..1769af08 100644 --- a/primitives/types/unknown_transaction.go +++ b/primitives/types/unknown_transaction.go @@ -33,6 +33,23 @@ func NewUnknownTransactionCustomUnknownTransaction(unknown sc.U8) UnknownTransac return UnknownTransaction{sc.NewVaryingData(UnknownTransactionCustomUnknownTransaction, unknown)} } +func (err UnknownTransaction) Error() string { + if len(err.VaryingData) == 0 { + return "" + } + + switch err.VaryingData[0] { + case UnknownTransactionCannotLookup: + return "Could not lookup information required to validate the transaction" + case UnknownTransactionNoUnsignedValidator: + return "Could not find an unsigned validator for the unsigned transaction" + case UnknownTransactionCustomUnknownTransaction: + return "UnknownTransaction custom error" + default: + return "" + } +} + func DecodeUnknownTransaction(buffer *bytes.Buffer) (UnknownTransaction, error) { b, err := sc.DecodeU8(buffer) if err != nil { diff --git a/primitives/types/unsigned_validator.go b/primitives/types/unsigned_validator.go index 18a0005a..acad5f4d 100644 --- a/primitives/types/unsigned_validator.go +++ b/primitives/types/unsigned_validator.go @@ -22,7 +22,7 @@ type UnsignedValidator interface { // ensure that the transaction is valid. // // Changes made to storage *WILL* be persisted if the call returns `Ok`. - PreDispatch(call Call) (ok sc.Empty, err TransactionValidityError) + PreDispatch(call Call) (ok sc.Empty, err error) // ValidateUnsigned returns the validity of the call // @@ -36,5 +36,5 @@ type UnsignedValidator interface { // like checking that the unsigned extrinsic was send by an authority in the active set. // // Changes made to storage should be discarded by caller. - ValidateUnsigned(source TransactionSource, call Call) (ok ValidTransaction, err TransactionValidityError) + ValidateUnsigned(source TransactionSource, call Call) (ok ValidTransaction, err error) } diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 2e9c0697..3a0ce584 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -64,20 +64,20 @@ var ( ) var ( - invalidTransactionStaleErr, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) - invalidTransactionFutureErr, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionFuture()) - invalidTransactionBadProofErr, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadProof()) - invalidTransactionExhaustsResourcesErr, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) - unknownTransactionNoUnsignedValidator, _ = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) - invalidTransactionMandatoryValidation, _ = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionMandatoryValidation()) + invalidTransactionStaleErr = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()) + invalidTransactionFutureErr = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionFuture()) + invalidTransactionBadProofErr = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionBadProof()) + invalidTransactionExhaustsResourcesErr = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionExhaustsResources()) + unknownTransactionNoUnsignedValidator = primitives.NewTransactionValidityError(primitives.NewUnknownTransactionNoUnsignedValidator()) + invalidTransactionMandatoryValidation = primitives.NewTransactionValidityError(primitives.NewInvalidTransactionMandatoryValidation()) ) var ( - transactionValidityResultStaleErr, _ = primitives.NewTransactionValidityResult(invalidTransactionStaleErr) - transactionValidityResultFutureErr, _ = primitives.NewTransactionValidityResult(invalidTransactionFutureErr) - transactionValidityResultExhaustsResourcesErr, _ = primitives.NewTransactionValidityResult(invalidTransactionExhaustsResourcesErr) - transactionValidityResultNoUnsignedValidatorErr, _ = primitives.NewTransactionValidityResult(unknownTransactionNoUnsignedValidator) - transactionValidityResultMandatoryValidationErr, _ = primitives.NewTransactionValidityResult(invalidTransactionMandatoryValidation) + transactionValidityResultStaleErr, _ = primitives.NewTransactionValidityResult(invalidTransactionStaleErr.(primitives.TransactionValidityError)) + transactionValidityResultFutureErr, _ = primitives.NewTransactionValidityResult(invalidTransactionFutureErr.(primitives.TransactionValidityError)) + transactionValidityResultExhaustsResourcesErr, _ = primitives.NewTransactionValidityResult(invalidTransactionExhaustsResourcesErr.(primitives.TransactionValidityError)) + transactionValidityResultNoUnsignedValidatorErr, _ = primitives.NewTransactionValidityResult(unknownTransactionNoUnsignedValidator.(primitives.TransactionValidityError)) + transactionValidityResultMandatoryValidationErr, _ = primitives.NewTransactionValidityResult(invalidTransactionMandatoryValidation.(primitives.TransactionValidityError)) dispatchOutcome, _ = primitives.NewDispatchOutcome(nil) dispatchOutcomeBadOriginErr, _ = primitives.NewDispatchOutcome(primitives.NewDispatchErrorBadOrigin()) @@ -86,27 +86,27 @@ var ( primitives.NewDispatchErrorModule( primitives.CustomModuleError{ Index: BalancesIndex, - Error: sc.U32(balances.ErrorInsufficientBalance), + Err: sc.U32(balances.ErrorInsufficientBalance), })) dispatchOutcomeExistentialDepositErr, _ = primitives.NewDispatchOutcome( primitives.NewDispatchErrorModule( primitives.CustomModuleError{ Index: BalancesIndex, - Error: sc.U32(balances.ErrorExistentialDeposit), + Err: sc.U32(balances.ErrorExistentialDeposit), })) dispatchOutcomeKeepAliveErr, _ = primitives.NewDispatchOutcome( primitives.NewDispatchErrorModule( primitives.CustomModuleError{ Index: BalancesIndex, - Error: sc.U32(balances.ErrorKeepAlive), + Err: sc.U32(balances.ErrorKeepAlive), })) applyExtrinsicResultOutcome, _ = primitives.NewApplyExtrinsicResult(dispatchOutcome) - applyExtrinsicResultExhaustsResourcesErr, _ = primitives.NewApplyExtrinsicResult(invalidTransactionExhaustsResourcesErr) + applyExtrinsicResultExhaustsResourcesErr, _ = primitives.NewApplyExtrinsicResult(invalidTransactionExhaustsResourcesErr.(primitives.TransactionValidityError)) applyExtrinsicResultBadOriginErr, _ = primitives.NewApplyExtrinsicResult(dispatchOutcomeBadOriginErr) - applyExtrinsicResultBadProofErr, _ = primitives.NewApplyExtrinsicResult(invalidTransactionBadProofErr) + applyExtrinsicResultBadProofErr, _ = primitives.NewApplyExtrinsicResult(invalidTransactionBadProofErr.(primitives.TransactionValidityError)) applyExtrinsicResultCustomModuleErr, _ = primitives.NewApplyExtrinsicResult(dispatchOutcomeCustomModuleErr) applyExtrinsicResultExistentialDepositErr, _ = primitives.NewApplyExtrinsicResult(dispatchOutcomeExistentialDepositErr) diff --git a/runtime/validate_transaction_test.go b/runtime/validate_transaction_test.go index 6cab886c..074d0919 100644 --- a/runtime/validate_transaction_test.go +++ b/runtime/validate_transaction_test.go @@ -76,8 +76,7 @@ func Test_ValidateTransaction_Success(t *testing.T) { buffer.Reset() buffer.Write(encTransactionValidityResult) transactionValidityResult, err := primitives.DecodeTransactionValidityResult(buffer) - assert.Nil(t, err) - + assert.NoError(t, err) assert.Equal(t, true, transactionValidityResult.IsValidTransaction()) } From 0d48bd26f2eee50c852503a934b581de883200fe Mon Sep 17 00:00:00 2001 From: Tugay Emin Date: Tue, 21 Nov 2023 08:58:21 +0200 Subject: [PATCH 2/8] fix tests + revert DispatchErrorWIthPostInfo --- api/block_builder/module.go | 6 +- api/block_builder/module_test.go | 29 +++- api/tagged_transaction_queue/module.go | 7 +- api/tagged_transaction_queue/module_test.go | 26 ++++ build/runtime.wasm | Bin 714433 -> 2658215 bytes execution/types/checked_extrinsic.go | 17 ++- execution/types/checked_extrinsic_test.go | 20 +-- frame/balances/call_force_free.go | 58 +++---- frame/balances/call_force_free_test.go | 23 ++- frame/balances/call_force_transfer.go | 53 ++++--- frame/balances/call_force_transfer_test.go | 6 +- frame/balances/call_set_balance.go | 18 +-- frame/balances/call_set_balance_test.go | 10 +- frame/balances/call_transfer.go | 94 ++++++------ frame/balances/call_transfer_all.go | 49 +++--- frame/balances/call_transfer_all_test.go | 4 +- frame/balances/call_transfer_keep_alive.go | 47 +++--- .../balances/call_transfer_keep_alive_test.go | 4 +- frame/balances/call_transfer_test.go | 16 +- frame/balances/mock_transfer_test.go | 6 +- frame/balances/module.go | 26 ++-- frame/balances/module_test.go | 12 +- frame/balances/types.go | 2 +- frame/executive/executive.go | 6 +- frame/executive/executive_test.go | 32 +++- frame/support/transactional.go | 47 +++--- frame/support/transactional_test.go | 18 +-- frame/system/call_remark.go | 10 +- frame/system/call_remark_test.go | 6 +- frame/system/events.go | 6 +- frame/system/extensions/check_genesis_test.go | 18 +++ .../system/extensions/check_mortality_test.go | 58 +++++++ frame/system/extensions/check_nonce_test.go | 38 +++++ frame/system/extensions/check_weight_test.go | 53 +++++++ frame/system/module.go | 10 +- frame/system/module_test.go | 4 +- frame/testable/call.go | 2 +- frame/timestamp/call_set.go | 4 +- frame/timestamp/call_set_test.go | 2 +- .../extensions/charge_transaction.go | 4 +- .../charge_transaction_payment_test.go | 33 ++++ mocks/currency_adapter.go | 12 +- mocks/io_transactional.go | 9 +- primitives/types/apply_extrinsic_result.go | 8 +- primitives/types/arithmetic_error.go | 16 +- primitives/types/arithmetic_error_test.go | 13 +- primitives/types/currency_adapter.go | 4 +- primitives/types/dispatch_errors.go | 143 ++++++++++-------- primitives/types/dispatch_errors_test.go | 6 +- primitives/types/dispatch_outcome.go | 8 +- primitives/types/dispatch_result_test.go | 2 +- .../dispatch_result_with_post_info_test.go | 8 +- primitives/types/invalid_transaction.go | 4 +- primitives/types/token_error.go | 24 +-- primitives/types/token_error_test.go | 49 +++++- .../types/transaction_validity_error.go | 34 +++-- .../types/transaction_validity_error_test.go | 27 ++-- .../types/transaction_validity_result.go | 8 +- primitives/types/transactional_error.go | 14 +- primitives/types/transactional_error_test.go | 19 ++- primitives/types/unknown_transaction.go | 4 +- runtime/validate_transaction_test.go | 3 +- 62 files changed, 836 insertions(+), 463 deletions(-) diff --git a/api/block_builder/module.go b/api/block_builder/module.go index cde868d0..5b3c62c7 100644 --- a/api/block_builder/module.go +++ b/api/block_builder/module.go @@ -67,11 +67,11 @@ func (m Module) ApplyExtrinsic(dataPtr int32, dataLen int32) int64 { log.Critical(err.Error()) } - ok, errApplyExtr := m.executive.ApplyExtrinsic(uxt) + ok, err := m.executive.ApplyExtrinsic(uxt) var applyExtrinsicResult primitives.ApplyExtrinsicResult - switch errApplyExtr.(type) { + switch err.(type) { case primitives.TransactionValidityError: - applyExtrinsicResult, err = primitives.NewApplyExtrinsicResult(errApplyExtr.(primitives.TransactionValidityError)) + applyExtrinsicResult, err = primitives.NewApplyExtrinsicResult(err.(primitives.TransactionValidityError)) case nil: applyExtrinsicResult, err = primitives.NewApplyExtrinsicResult(ok) } diff --git a/api/block_builder/module_test.go b/api/block_builder/module_test.go index ece55e1f..f8e37fb2 100644 --- a/api/block_builder/module_test.go +++ b/api/block_builder/module_test.go @@ -2,6 +2,7 @@ package blockbuilder import ( "bytes" + "errors" "io" "testing" @@ -80,15 +81,15 @@ func Test_Module_ApplyExtrinsic_Fails(t *testing.T) { bufferUxt := bytes.NewBuffer(bUxt) outcome, err := primitives.NewDispatchOutcome(sc.Empty{}) assert.Nil(t, err) - txErr, ok := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()).(primitives.TransactionValidityError) + validityError, ok := primitives.NewTransactionValidityError(primitives.NewInvalidTransactionStale()).(primitives.TransactionValidityError) assert.True(t, ok) - applyExtrinsicResultValidityErr, err := primitives.NewApplyExtrinsicResult(txErr) + applyExtrinsicResultValidityErr, err := primitives.NewApplyExtrinsicResult(validityError) assert.Nil(t, err) bExtrinsicResult := applyExtrinsicResultValidityErr.Bytes() mockMemoryUtils.On("GetWasmMemorySlice", dataPtr, dataLen).Return(bUxt) mockRuntimeDecoder.On("DecodeUncheckedExtrinsic", bufferUxt).Return(uxt, nil) - mockExecutive.On("ApplyExtrinsic", uxt).Return(outcome, txErr) + mockExecutive.On("ApplyExtrinsic", uxt).Return(outcome, validityError) mockMemoryUtils.On("BytesToOffsetAndSize", bExtrinsicResult).Return(ptrAndSize) result := target.ApplyExtrinsic(dataPtr, dataLen) @@ -100,6 +101,28 @@ func Test_Module_ApplyExtrinsic_Fails(t *testing.T) { mockMemoryUtils.AssertCalled(t, "BytesToOffsetAndSize", bExtrinsicResult) } +func Test_Module_ApplyExtrinsic_Panics(t *testing.T) { + target := setup() + + bufferUxt := bytes.NewBuffer(bUxt) + outcome, err := primitives.NewDispatchOutcome(sc.Empty{}) + assert.Nil(t, err) + expectedErr := errors.New("panic") + + mockMemoryUtils.On("GetWasmMemorySlice", dataPtr, dataLen).Return(bUxt) + mockRuntimeDecoder.On("DecodeUncheckedExtrinsic", bufferUxt).Return(uxt, nil) + mockExecutive.On("ApplyExtrinsic", uxt).Return(outcome, expectedErr) + + assert.PanicsWithValue(t, + expectedErr.Error(), + func() { target.ApplyExtrinsic(dataPtr, dataLen) }, + ) + + mockMemoryUtils.AssertCalled(t, "GetWasmMemorySlice", dataPtr, dataLen) + mockRuntimeDecoder.AssertExpectations(t) + mockExecutive.AssertCalled(t, "ApplyExtrinsic", uxt) +} + func Test_Module_FinalizeBlock(t *testing.T) { target := setup() diff --git a/api/tagged_transaction_queue/module.go b/api/tagged_transaction_queue/module.go index 19632c0a..d47d5e66 100644 --- a/api/tagged_transaction_queue/module.go +++ b/api/tagged_transaction_queue/module.go @@ -69,14 +69,13 @@ func (m Module) ValidateTransaction(dataPtr int32, dataLen int32) int64 { log.Critical(err.Error()) } - ok, errTx := m.executive.ValidateTransaction(txSource, tx, blockHash) + ok, err := m.executive.ValidateTransaction(txSource, tx, blockHash) var res primitives.TransactionValidityResult - switch errTx.(type) { + switch err.(type) { case primitives.TransactionValidityError: - res, err = primitives.NewTransactionValidityResult(errTx.(primitives.TransactionValidityError)) + res, err = primitives.NewTransactionValidityResult(err.(primitives.TransactionValidityError)) case nil: res, err = primitives.NewTransactionValidityResult(ok) - default: } if err != nil { log.Critical(err.Error()) diff --git a/api/tagged_transaction_queue/module_test.go b/api/tagged_transaction_queue/module_test.go index 5b630de5..caa13586 100644 --- a/api/tagged_transaction_queue/module_test.go +++ b/api/tagged_transaction_queue/module_test.go @@ -2,6 +2,7 @@ package tagged_transaction_queue import ( "bytes" + "errors" "testing" "github.com/ChainSafe/gossamer/lib/common" @@ -100,6 +101,31 @@ func Test_Module_ValidateTransaction_Fails(t *testing.T) { mockMemoryUtils.AssertCalled(t, "BytesToOffsetAndSize", validityFailResult.Bytes()) } +func Test_Module_ValidateTransaction_Panics(t *testing.T) { + target := setup() + + data := append(txSource.Bytes(), blockHash.Bytes()...) + expectBuffer := bytes.NewBuffer(data) + _, err := expectBuffer.ReadByte() + assert.Nil(t, err) + + expectedErr := errors.New("panic") + + mockMemoryUtils.On("GetWasmMemorySlice", dataPtr, dataLen).Return(data) + mockRuntimeDecoder.On("DecodeUncheckedExtrinsic", expectBuffer).Return(mockUxt, nil) + mockExecutive.On("ValidateTransaction", txSource, mockUxt, blockHash). + Return(primitives.ValidTransaction{}, expectedErr) + + assert.PanicsWithValue(t, + expectedErr.Error(), + func() { target.ValidateTransaction(dataPtr, dataLen) }, + ) + + mockMemoryUtils.AssertCalled(t, "GetWasmMemorySlice", dataPtr, dataLen) + mockRuntimeDecoder.AssertExpectations(t) + mockExecutive.AssertCalled(t, "ValidateTransaction", txSource, mockUxt, blockHash) +} + func Test_Module_Metadata(t *testing.T) { target := setup() diff --git a/build/runtime.wasm b/build/runtime.wasm index 9a273b988651847c586d2a8d1eb5cacc7cc1eb81..76e1ee3862d4ec63758e1d3ad06b9be04a78b503 100755 GIT binary patch literal 2658215 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

tTy+^PZ?mVJ;Tj2@+ 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