From b5552383d9b2f8696115aee6501dfb8c43be6ebf Mon Sep 17 00:00:00 2001 From: Kanishka Date: Wed, 21 Jun 2023 04:37:41 -0600 Subject: [PATCH] feat/runtime: Add few parachain runtime calls (#3241) Co-authored-by: Kishan Mohanbhai Sagathiya --- dot/core/mock_runtime_instance_test.go | 122 ++ dot/state/mocks_runtime_test.go | 122 ++ dot/sync/mock_runtime_test.go | 122 ++ lib/babe/mocks/runtime.go | 122 ++ lib/blocktree/mocks_test.go | 122 ++ lib/grandpa/mocks_runtime_test.go | 122 ++ lib/runtime/constants.go | 22 + lib/runtime/interface.go | 15 + lib/runtime/mocks/mocks.go | 122 ++ lib/runtime/test_helpers.go | 3 + lib/runtime/wasmer/exports.go | 520 +++++++ lib/runtime/wasmer/exports_test.go | 1514 ++++++++++++++++++++ lib/runtime/wasmer/test_helpers.go | 90 ++ lib/runtime/wasmer/testdata/parachain.yaml | 63 + lib/runtime/wazero/instance.go | 171 ++- 15 files changed, 3251 insertions(+), 1 deletion(-) create mode 100644 lib/runtime/wasmer/exports.go create mode 100644 lib/runtime/wasmer/exports_test.go create mode 100644 lib/runtime/wasmer/test_helpers.go create mode 100644 lib/runtime/wasmer/testdata/parachain.yaml diff --git a/dot/core/mock_runtime_instance_test.go b/dot/core/mock_runtime_instance_test.go index 0a1f6a7478..e671aee681 100644 --- a/dot/core/mock_runtime_instance_test.go +++ b/dot/core/mock_runtime_instance_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/dot/state/mocks_runtime_test.go b/dot/state/mocks_runtime_test.go index 83be8da0e1..4029d21a02 100644 --- a/dot/state/mocks_runtime_test.go +++ b/dot/state/mocks_runtime_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/dot/sync/mock_runtime_test.go b/dot/sync/mock_runtime_test.go index f1a583b884..36b3842e3c 100644 --- a/dot/sync/mock_runtime_test.go +++ b/dot/sync/mock_runtime_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/babe/mocks/runtime.go b/lib/babe/mocks/runtime.go index 369e51c6dc..2701d8022a 100644 --- a/lib/babe/mocks/runtime.go +++ b/lib/babe/mocks/runtime.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/blocktree/mocks_test.go b/lib/blocktree/mocks_test.go index 7c5eb64806..b1ea7d6183 100644 --- a/lib/blocktree/mocks_test.go +++ b/lib/blocktree/mocks_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/grandpa/mocks_runtime_test.go b/lib/grandpa/mocks_runtime_test.go index fc0360e78f..236cea4c69 100644 --- a/lib/grandpa/mocks_runtime_test.go +++ b/lib/grandpa/mocks_runtime_test.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/runtime/constants.go b/lib/runtime/constants.go index 26d0ccd267..ce70426c81 100644 --- a/lib/runtime/constants.go +++ b/lib/runtime/constants.go @@ -22,6 +22,12 @@ const ( WESTEND_RUNTIME_V0929_FP = "westend_runtime-v929.compact.wasm" WESTEND_RUNTIME_V0929_URL = "https://github.com/paritytech/polkadot/releases/download/v0.9." + "29/westend_runtime-v9290.compact.compressed.wasm?raw=true" + + // v0.9.42 westend + WESTEND_RUNTIME_v0942 = "westend_runtime-v942" + WESTEND_RUNTIME_V0942_FP = "westend_runtime-v942.compact.wasm" + WESTEND_RUNTIME_V0942_URL = "https://github.com/paritytech/polkadot/releases/download/v0.9." + + "42/westend_runtime-v9420.compact.compressed.wasm?raw=true" ) const ( @@ -62,4 +68,20 @@ const ( TransactionPaymentCallAPIQueryCallInfo = "TransactionPaymentCallApi_query_call_info" // TransactionPaymentCallAPIQueryCallFeeDetails returns call query call fee details TransactionPaymentCallAPIQueryCallFeeDetails = "TransactionPaymentCallApi_query_call_fee_details" + // ParachainHostValidators is the runtime API call ParachainHost_validators + ParachainHostValidators = "ParachainHost_validators" + // ParachainHostValidatorGroups is the runtime API call ParachainHost_validator_groups + ParachainHostValidatorGroups = "ParachainHost_validator_groups" + // ParachainHostAvailabilityCores is the runtime API call ParachainHost_availability_cores + ParachainHostAvailabilityCores = "ParachainHost_availability_cores" + // ParachainHostCheckValidationOutputs is the runtime API call ParachainHost_check_validation_outputs + ParachainHostCheckValidationOutputs = "ParachainHost_check_validation_outputs" + // ParachainHostSessionIndexForChild is the runtime API call ParachainHost_session_index_for_child + ParachainHostSessionIndexForChild = "ParachainHost_session_index_for_child" + // ParachainHostCandidatePendingAvailability is the runtime API call ParachainHost_candidate_pending_availability + ParachainHostCandidatePendingAvailability = "ParachainHost_candidate_pending_availability" + // ParachainHostCandidateEvents is the runtime API call ParachainHost_candidate_events + ParachainHostCandidateEvents = "ParachainHost_candidate_events" + // ParachainHostSessionInfo is the runtime API call ParachainHost_session_info + ParachainHostSessionInfo = "ParachainHost_session_info" ) diff --git a/lib/runtime/interface.go b/lib/runtime/interface.go index 6e14a27d80..473710cd99 100644 --- a/lib/runtime/interface.go +++ b/lib/runtime/interface.go @@ -8,7 +8,9 @@ import ( "github.com/ChainSafe/gossamer/lib/common" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" "github.com/ChainSafe/gossamer/lib/keystore" + "github.com/ChainSafe/gossamer/lib/parachain" "github.com/ChainSafe/gossamer/lib/transaction" + "github.com/ChainSafe/gossamer/pkg/scale" ) // Instance for runtime methods @@ -48,4 +50,17 @@ type Instance interface { GrandpaSubmitReportEquivocationUnsignedExtrinsic( equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, ) error + ParachainHostValidators() ([]parachain.ValidatorID, error) + ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) + ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) + ParachainHostCheckValidationOutputs( + parachainID parachain.ParaID, + outputs parachain.CandidateCommitments, + ) (bool, error) + ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) + ParachainHostCandidatePendingAvailability( + parachainID parachain.ParaID, + ) (*parachain.CommittedCandidateReceipt, error) + ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) + ParachainHostSessionInfo(sessionIndex parachain.SessionIndex) (*parachain.SessionInfo, error) } diff --git a/lib/runtime/mocks/mocks.go b/lib/runtime/mocks/mocks.go index 22f87dbeff..9db3aa6bf0 100644 --- a/lib/runtime/mocks/mocks.go +++ b/lib/runtime/mocks/mocks.go @@ -11,8 +11,10 @@ import ( common "github.com/ChainSafe/gossamer/lib/common" ed25519 "github.com/ChainSafe/gossamer/lib/crypto/ed25519" keystore "github.com/ChainSafe/gossamer/lib/keystore" + parachain "github.com/ChainSafe/gossamer/lib/parachain" runtime "github.com/ChainSafe/gossamer/lib/runtime" transaction "github.com/ChainSafe/gossamer/lib/transaction" + scale "github.com/ChainSafe/gossamer/pkg/scale" gomock "github.com/golang/mock/gomock" ) @@ -338,6 +340,126 @@ func (mr *MockInstanceMockRecorder) OffchainWorker() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OffchainWorker", reflect.TypeOf((*MockInstance)(nil).OffchainWorker)) } +// ParachainHostAvailabilityCores mocks base method. +func (m *MockInstance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostAvailabilityCores") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostAvailabilityCores indicates an expected call of ParachainHostAvailabilityCores. +func (mr *MockInstanceMockRecorder) ParachainHostAvailabilityCores() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostAvailabilityCores", reflect.TypeOf((*MockInstance)(nil).ParachainHostAvailabilityCores)) +} + +// ParachainHostCandidateEvents mocks base method. +func (m *MockInstance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidateEvents") + ret0, _ := ret[0].(*scale.VaryingDataTypeSlice) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidateEvents indicates an expected call of ParachainHostCandidateEvents. +func (mr *MockInstanceMockRecorder) ParachainHostCandidateEvents() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidateEvents", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidateEvents)) +} + +// ParachainHostCandidatePendingAvailability mocks base method. +func (m *MockInstance) ParachainHostCandidatePendingAvailability(arg0 parachain.ParaID) (*parachain.CommittedCandidateReceipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCandidatePendingAvailability", arg0) + ret0, _ := ret[0].(*parachain.CommittedCandidateReceipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCandidatePendingAvailability indicates an expected call of ParachainHostCandidatePendingAvailability. +func (mr *MockInstanceMockRecorder) ParachainHostCandidatePendingAvailability(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCandidatePendingAvailability", reflect.TypeOf((*MockInstance)(nil).ParachainHostCandidatePendingAvailability), arg0) +} + +// ParachainHostCheckValidationOutputs mocks base method. +func (m *MockInstance) ParachainHostCheckValidationOutputs(arg0 parachain.ParaID, arg1 parachain.CandidateCommitments) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostCheckValidationOutputs", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostCheckValidationOutputs indicates an expected call of ParachainHostCheckValidationOutputs. +func (mr *MockInstanceMockRecorder) ParachainHostCheckValidationOutputs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostCheckValidationOutputs", reflect.TypeOf((*MockInstance)(nil).ParachainHostCheckValidationOutputs), arg0, arg1) +} + +// ParachainHostSessionIndexForChild mocks base method. +func (m *MockInstance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionIndexForChild") + ret0, _ := ret[0].(parachain.SessionIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionIndexForChild indicates an expected call of ParachainHostSessionIndexForChild. +func (mr *MockInstanceMockRecorder) ParachainHostSessionIndexForChild() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionIndexForChild", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionIndexForChild)) +} + +// ParachainHostSessionInfo mocks base method. +func (m *MockInstance) ParachainHostSessionInfo(arg0 parachain.SessionIndex) (*parachain.SessionInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostSessionInfo", arg0) + ret0, _ := ret[0].(*parachain.SessionInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostSessionInfo indicates an expected call of ParachainHostSessionInfo. +func (mr *MockInstanceMockRecorder) ParachainHostSessionInfo(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostSessionInfo", reflect.TypeOf((*MockInstance)(nil).ParachainHostSessionInfo), arg0) +} + +// ParachainHostValidatorGroups mocks base method. +func (m *MockInstance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidatorGroups") + ret0, _ := ret[0].(*parachain.ValidatorGroups) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidatorGroups indicates an expected call of ParachainHostValidatorGroups. +func (mr *MockInstanceMockRecorder) ParachainHostValidatorGroups() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidatorGroups", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidatorGroups)) +} + +// ParachainHostValidators mocks base method. +func (m *MockInstance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ParachainHostValidators") + ret0, _ := ret[0].([]parachain.ValidatorID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ParachainHostValidators indicates an expected call of ParachainHostValidators. +func (mr *MockInstanceMockRecorder) ParachainHostValidators() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ParachainHostValidators", reflect.TypeOf((*MockInstance)(nil).ParachainHostValidators)) +} + // PaymentQueryInfo mocks base method. func (m *MockInstance) PaymentQueryInfo(arg0 []byte) (*types.RuntimeDispatchInfo, error) { m.ctrl.T.Helper() diff --git a/lib/runtime/test_helpers.go b/lib/runtime/test_helpers.go index c6a5e836ac..66b65d0131 100644 --- a/lib/runtime/test_helpers.go +++ b/lib/runtime/test_helpers.go @@ -78,6 +78,9 @@ func GetRuntime(ctx context.Context, runtime string) ( case WESTEND_RUNTIME_v0929: runtimeFilename = WESTEND_RUNTIME_V0929_FP url = WESTEND_RUNTIME_V0929_URL + case WESTEND_RUNTIME_v0942: + runtimeFilename = WESTEND_RUNTIME_V0942_FP + url = WESTEND_RUNTIME_V0942_URL default: return "", fmt.Errorf("%w: %s", ErrRuntimeUnknown, runtime) } diff --git a/lib/runtime/wasmer/exports.go b/lib/runtime/wasmer/exports.go new file mode 100644 index 0000000000..c083318956 --- /dev/null +++ b/lib/runtime/wasmer/exports.go @@ -0,0 +1,520 @@ +// Copyright 2021 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package wasmer + +import ( + "bytes" + "fmt" + + "github.com/ChainSafe/gossamer/dot/types" + "github.com/ChainSafe/gossamer/lib/crypto/ed25519" + "github.com/ChainSafe/gossamer/lib/parachain" + "github.com/ChainSafe/gossamer/lib/runtime" + "github.com/ChainSafe/gossamer/lib/transaction" + "github.com/ChainSafe/gossamer/pkg/scale" +) + +// ValidateTransaction runs the extrinsic through the runtime function +// TaggedTransactionQueue_validate_transaction and returns *transaction.Validity. The error can +// be a VDT of either transaction.InvalidTransaction or transaction.UnknownTransaction, or can represent +// a normal error i.e. unmarshalling error +func (in *Instance) ValidateTransaction(e types.Extrinsic) ( + *transaction.Validity, error) { + ret, err := in.Exec(runtime.TaggedTransactionQueueValidateTransaction, e) + if err != nil { + return nil, err + } + + return runtime.UnmarshalTransactionValidity(ret) +} + +// Version returns the instance version. +// This is cheap to call since the instance version is cached. +// Note the instance version is set at creation and on code update. +func (in *Instance) Version() (runtime.Version, error) { + if in.ctx.Version != nil { + return *in.ctx.Version, nil + } + + err := in.version() + if err != nil { + return runtime.Version{}, err + } + + return *in.ctx.Version, nil +} + +// version calls runtime function Core_Version and returns the +// decoded version structure. +func (in *Instance) version() error { + res, err := in.Exec(runtime.CoreVersion, []byte{}) + if err != nil { + return err + } + + version, err := runtime.DecodeVersion(res) + if err != nil { + return fmt.Errorf("decoding version: %w", err) + } + + in.ctx.Version = &version + + return nil +} + +// Metadata calls runtime function Metadata_metadata +func (in *Instance) Metadata() ([]byte, error) { + return in.Exec(runtime.Metadata, []byte{}) +} + +// BabeConfiguration gets the configuration data for BABE from the runtime +func (in *Instance) BabeConfiguration() (*types.BabeConfiguration, error) { + data, err := in.Exec(runtime.BabeAPIConfiguration, []byte{}) + if err != nil { + return nil, err + } + + bc := new(types.BabeConfiguration) + err = scale.Unmarshal(data, bc) + if err != nil { + return nil, err + } + + return bc, nil +} + +// GrandpaAuthorities returns the genesis authorities from the runtime +func (in *Instance) GrandpaAuthorities() ([]types.Authority, error) { + ret, err := in.Exec(runtime.GrandpaAuthorities, []byte{}) + if err != nil { + return nil, err + } + + var gar []types.GrandpaAuthoritiesRaw + err = scale.Unmarshal(ret, &gar) + if err != nil { + return nil, err + } + + return types.GrandpaAuthoritiesRawToAuthorities(gar) +} + +// BabeGenerateKeyOwnershipProof returns the babe key ownership proof from the runtime. +func (in *Instance) BabeGenerateKeyOwnershipProof(slot uint64, authorityID [32]byte) ( + types.OpaqueKeyOwnershipProof, error) { + + // scale encoded slot uint64 + scale encoded array of 32 bytes + const maxBufferLength = 8 + 33 + buffer := bytes.NewBuffer(make([]byte, 0, maxBufferLength)) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(slot) + if err != nil { + return nil, fmt.Errorf("encoding slot: %w", err) + } + err = encoder.Encode(authorityID) + if err != nil { + return nil, fmt.Errorf("encoding authority id: %w", err) + } + + encodedKeyOwnershipProof, err := in.Exec(runtime.BabeAPIGenerateKeyOwnershipProof, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("executing %s: %w", runtime.BabeAPIGenerateKeyOwnershipProof, err) + } + + var keyOwnershipProof *types.OpaqueKeyOwnershipProof + err = scale.Unmarshal(encodedKeyOwnershipProof, &keyOwnershipProof) + if err != nil { + return nil, fmt.Errorf("scale decoding key ownership proof: %w", err) + } + + if keyOwnershipProof == nil { + return nil, nil + } + + return *keyOwnershipProof, nil +} + +// BabeSubmitReportEquivocationUnsignedExtrinsic reports equivocation report to the runtime. +func (in *Instance) BabeSubmitReportEquivocationUnsignedExtrinsic( + equivocationProof types.BabeEquivocationProof, keyOwnershipProof types.OpaqueKeyOwnershipProof, +) error { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(equivocationProof) + if err != nil { + return fmt.Errorf("encoding equivocation proof: %w", err) + } + err = encoder.Encode(keyOwnershipProof) + if err != nil { + return fmt.Errorf("encoding key ownership proof: %w", err) + } + _, err = in.Exec(runtime.BabeAPISubmitReportEquivocationUnsignedExtrinsic, buffer.Bytes()) + return err +} + +// InitializeBlock calls runtime API function Core_initialise_block +func (in *Instance) InitializeBlock(header *types.Header) error { + encodedHeader, err := scale.Marshal(*header) + if err != nil { + return fmt.Errorf("cannot encode header: %w", err) + } + + _, err = in.Exec(runtime.CoreInitializeBlock, encodedHeader) + return err +} + +// InherentExtrinsics calls runtime API function BlockBuilder_inherent_extrinsics +func (in *Instance) InherentExtrinsics(data []byte) ([]byte, error) { + return in.Exec(runtime.BlockBuilderInherentExtrinsics, data) +} + +// ApplyExtrinsic calls runtime API function BlockBuilder_apply_extrinsic +func (in *Instance) ApplyExtrinsic(data types.Extrinsic) ([]byte, error) { + return in.Exec(runtime.BlockBuilderApplyExtrinsic, data) +} + +// FinalizeBlock calls runtime API function BlockBuilder_finalize_block +func (in *Instance) FinalizeBlock() (*types.Header, error) { + data, err := in.Exec(runtime.BlockBuilderFinalizeBlock, []byte{}) + if err != nil { + return nil, err + } + + bh := types.NewEmptyHeader() + err = scale.Unmarshal(data, bh) + if err != nil { + return nil, err + } + + return bh, nil +} + +// ExecuteBlock calls runtime function Core_execute_block +func (in *Instance) ExecuteBlock(block *types.Block) ([]byte, error) { + // copy block since we're going to modify it + b, err := block.DeepCopy() + if err != nil { + return nil, err + } + + b.Header.Digest = types.NewDigest() + + // remove seal digest only + for _, d := range block.Header.Digest.Types { + digestValue, err := d.Value() + if err != nil { + return nil, fmt.Errorf("getting digest type value: %w", err) + } + switch digestValue.(type) { + case types.SealDigest: + continue + default: + err = b.Header.Digest.Add(digestValue) + if err != nil { + return nil, err + } + } + } + + bdEnc, err := b.Encode() + if err != nil { + return nil, err + } + + return in.Exec(runtime.CoreExecuteBlock, bdEnc) +} + +// DecodeSessionKeys decodes the given public session keys. Returns a list of raw public keys including their key type. +func (in *Instance) DecodeSessionKeys(enc []byte) ([]byte, error) { + return in.Exec(runtime.DecodeSessionKeys, enc) +} + +// PaymentQueryInfo returns information of a given extrinsic +func (in *Instance) PaymentQueryInfo(ext []byte) (*types.RuntimeDispatchInfo, error) { + encLen, err := scale.Marshal(uint32(len(ext))) + if err != nil { + return nil, err + } + + resBytes, err := in.Exec(runtime.TransactionPaymentAPIQueryInfo, append(ext, encLen...)) + if err != nil { + return nil, err + } + + dispatchInfo := new(types.RuntimeDispatchInfo) + if err = scale.Unmarshal(resBytes, dispatchInfo); err != nil { + return nil, err + } + + return dispatchInfo, nil +} + +// QueryCallInfo returns information of a given extrinsic +func (in *Instance) QueryCallInfo(ext []byte) (*types.RuntimeDispatchInfo, error) { + encLen, err := scale.Marshal(uint32(len(ext))) + if err != nil { + return nil, err + } + + resBytes, err := in.Exec(runtime.TransactionPaymentCallAPIQueryCallInfo, append(ext, encLen...)) + if err != nil { + return nil, err + } + + dispatchInfo := new(types.RuntimeDispatchInfo) + if err = scale.Unmarshal(resBytes, dispatchInfo); err != nil { + return nil, err + } + + return dispatchInfo, nil +} + +// QueryCallFeeDetails returns call fee details for given call +func (in *Instance) QueryCallFeeDetails(ext []byte) (*types.FeeDetails, error) { + encLen, err := scale.Marshal(uint32(len(ext))) + if err != nil { + return nil, err + } + + resBytes, err := in.Exec(runtime.TransactionPaymentCallAPIQueryCallFeeDetails, append(ext, encLen...)) + if err != nil { + return nil, err + } + + dispatchInfo := new(types.FeeDetails) + if err = scale.Unmarshal(resBytes, dispatchInfo); err != nil { + return nil, err + } + + return dispatchInfo, nil +} + +// CheckInherents checks inherents in the block verification process. +// TODO: use this in block verification process (#1873) +func (in *Instance) CheckInherents() {} + +// GrandpaGenerateKeyOwnershipProof returns grandpa key ownership proof from the runtime. +func (in *Instance) GrandpaGenerateKeyOwnershipProof(authSetID uint64, authorityID ed25519.PublicKeyBytes) ( + types.GrandpaOpaqueKeyOwnershipProof, error) { + const bufferSize = 8 + 32 // authSetID uint64 + ed25519.PublicKeyBytes + buffer := bytes.NewBuffer(make([]byte, 0, bufferSize)) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(authSetID) + if err != nil { + return nil, fmt.Errorf("encoding auth set id: %w", err) + } + err = encoder.Encode(authorityID) + if err != nil { + return nil, fmt.Errorf("encoding authority id: %w", err) + } + encodedOpaqueKeyOwnershipProof, err := in.Exec(runtime.GrandpaGenerateKeyOwnershipProof, buffer.Bytes()) + if err != nil { + return nil, err + } + + var keyOwnershipProof *types.GrandpaOpaqueKeyOwnershipProof + err = scale.Unmarshal(encodedOpaqueKeyOwnershipProof, &keyOwnershipProof) + if err != nil { + return nil, fmt.Errorf("scale decoding: %w", err) + } + + if keyOwnershipProof == nil { + return nil, nil + } + + return *keyOwnershipProof, nil +} + +// GrandpaSubmitReportEquivocationUnsignedExtrinsic reports an equivocation report to the runtime. +func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( + equivocationProof types.GrandpaEquivocationProof, keyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof, +) error { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(equivocationProof) + if err != nil { + return fmt.Errorf("encoding equivocation proof: %w", err) + } + err = encoder.Encode(keyOwnershipProof) + if err != nil { + return fmt.Errorf("encoding key ownership proof: %w", err) + } + _, err = in.Exec(runtime.GrandpaSubmitReportEquivocation, buffer.Bytes()) + if err != nil { + return err + } + return nil +} + +// ParachainHostValidators returns the validator set at the current state. +// The specified validators are responsible for backing parachains for the current state. +func (in *Instance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + encodedValidators, err := in.Exec(runtime.ParachainHostValidators, []byte{}) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + var validatorIDs []parachain.ValidatorID + err = scale.Unmarshal(encodedValidators, &validatorIDs) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return validatorIDs, nil +} + +// ParachainHostValidatorGroups returns the validator groups used during the current session. +// The validators in the groups are referred to by the validator set Id. +func (in *Instance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + encodedValidatorGroups, err := in.Exec(runtime.ParachainHostValidatorGroups, []byte{}) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + var validatorGroups parachain.ValidatorGroups + err = scale.Unmarshal(encodedValidatorGroups, &validatorGroups) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return &validatorGroups, nil +} + +// ParachainHostAvailabilityCores returns the availability cores for the current state. +func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + encodedAvailabilityCores, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + availabilityCores, err := parachain.NewAvailabilityCores() + if err != nil { + return nil, fmt.Errorf("new availability cores: %w", err) + } + err = scale.Unmarshal(encodedAvailabilityCores, &availabilityCores) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return &availabilityCores, nil +} + +// ParachainHostCheckValidationOutputs checks the validation outputs of a candidate. +// Returns true if the candidate is valid. +func (in *Instance) ParachainHostCheckValidationOutputs( + parachainID parachain.ParaID, + outputs parachain.CandidateCommitments, +) (bool, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(parachainID) + if err != nil { + return false, fmt.Errorf("encode parachainID: %w", err) + } + err = encoder.Encode(outputs) + if err != nil { + return false, fmt.Errorf("encode outputs: %w", err) + } + + encodedPersistedValidationData, err := in.Exec(runtime.ParachainHostCheckValidationOutputs, buffer.Bytes()) + if err != nil { + return false, fmt.Errorf("exec: %w", err) + } + + var isValid bool + err = scale.Unmarshal(encodedPersistedValidationData, &isValid) + if err != nil { + return false, fmt.Errorf("unmarshalling: %w", err) + } + + return isValid, nil +} + +// ParachainHostSessionIndexForChild returns the session index that is expected at the child of a block. +func (in *Instance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + encodedSessionIndex, err := in.Exec(runtime.ParachainHostSessionIndexForChild, []byte{}) + if err != nil { + return 0, fmt.Errorf("exec: %w", err) + } + + var sessionIndex parachain.SessionIndex + err = scale.Unmarshal(encodedSessionIndex, &sessionIndex) + if err != nil { + return 0, fmt.Errorf("unmarshalling: %w", err) + } + + return sessionIndex, nil +} + +// ParachainHostCandidatePendingAvailability returns the receipt of a candidate pending availability +// for any parachain assigned to an occupied availability core. +func (in *Instance) ParachainHostCandidatePendingAvailability( + parachainID parachain.ParaID, +) (*parachain.CommittedCandidateReceipt, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(parachainID) + if err != nil { + return nil, fmt.Errorf("encode parachainID: %w", err) + } + + encodedCandidateReceipt, err := in.Exec(runtime.ParachainHostCandidatePendingAvailability, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + var candidateReceipt *parachain.CommittedCandidateReceipt + err = scale.Unmarshal(encodedCandidateReceipt, &candidateReceipt) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return candidateReceipt, nil +} + +// ParachainHostCandidateEvents returns an array of candidate events that occurred within the latest state. +func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + encodedCandidateEvents, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + candidateEvents, err := parachain.NewCandidateEvents() + if err != nil { + return nil, fmt.Errorf("create new candidate events: %w", err) + } + err = scale.Unmarshal(encodedCandidateEvents, &candidateEvents) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return &candidateEvents, nil +} + +// ParachainHostSessionInfo returns the session info of the given session, if available. +func (in *Instance) ParachainHostSessionInfo(sessionIndex parachain.SessionIndex) (*parachain.SessionInfo, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(sessionIndex) + if err != nil { + return nil, fmt.Errorf("encode sessionIndex: %w", err) + } + + encodedSessionInfo, err := in.Exec(runtime.ParachainHostSessionInfo, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + var sessionInfo *parachain.SessionInfo + err = scale.Unmarshal(encodedSessionInfo, &sessionInfo) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return sessionInfo, nil +} + +func (in *Instance) RandomSeed() {} +func (in *Instance) OffchainWorker() {} +func (in *Instance) GenerateSessionKeys() {} diff --git a/lib/runtime/wasmer/exports_test.go b/lib/runtime/wasmer/exports_test.go new file mode 100644 index 0000000000..5e16c75b27 --- /dev/null +++ b/lib/runtime/wasmer/exports_test.go @@ -0,0 +1,1514 @@ +// Copyright 2021 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package wasmer + +import ( + "bytes" + _ "embed" + "encoding/json" + "fmt" + "math/big" + "os" + "testing" + + "github.com/ChainSafe/gossamer/lib/runtime/storage" + "gopkg.in/yaml.v3" + + "github.com/ChainSafe/gossamer/dot/types" + "github.com/ChainSafe/gossamer/internal/log" + "github.com/ChainSafe/gossamer/lib/common" + "github.com/ChainSafe/gossamer/lib/crypto/ed25519" + "github.com/ChainSafe/gossamer/lib/genesis" + "github.com/ChainSafe/gossamer/lib/parachain" + "github.com/ChainSafe/gossamer/lib/runtime" + "github.com/ChainSafe/gossamer/lib/runtime/wasmer/testdata" + "github.com/ChainSafe/gossamer/lib/trie" + "github.com/ChainSafe/gossamer/lib/utils" + "github.com/ChainSafe/gossamer/pkg/scale" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +//go:embed testdata/parachain.yaml +var parachainTestDataRaw string + +type Storage struct { + Key string `yaml:"key"` + Value string `yaml:"value"` +} + +type Data struct { + Storage []Storage `yaml:"storage"` + Expected map[string]string `yaml:"expected"` +} + +var parachainTestData Data + +func init() { + err := yaml.Unmarshal([]byte(parachainTestDataRaw), ¶chainTestData) + if err != nil { + fmt.Println("Error unmarshaling test data:", err) + return + } +} + +// this is generated by printing key ownership proof while running `test_generate_equivocation_report_blob` +// https://github.com/paritytech/substrate/blob/ded44948e2d5a398abcb4e342b0513cb690961bb/frame/grandpa/src/benchmarking.rs#L85 +var testKeyOwnershipProof types.OpaqueKeyOwnershipProof = types.OpaqueKeyOwnershipProof([]byte{64, 138, 252, 29, 127, 102, 189, 129, 207, 47, 157, 60, 17, 138, 194, 121, 139, 92, 176, 175, 224, 16, 185, 93, 175, 251, 224, 81, 209, 61, 0, 71}) //nolint:lll + +func Test_Instance_Version(t *testing.T) { + t.Parallel() + + type instanceVersioner interface { + Version() (runtime.Version, error) + } + + testCases := map[string]struct { + instanceBuilder func(t *testing.T) instanceVersioner + expectedVersion runtime.Version + }{ + "kusama": { + instanceBuilder: func(t *testing.T) instanceVersioner { + genesisPath := utils.GetKusamaGenesisPath(t) + kusamaGenesis := genesisFromRawJSON(t, genesisPath) + genesisTrie, err := runtime.NewTrieFromGenesis(kusamaGenesis) + require.NoError(t, err) + + cfg := Config{ + Storage: storage.NewTrieState(&genesisTrie), + LogLvl: log.Critical, + } + + instance, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + return instance + }, + expectedVersion: runtime.Version{ + SpecName: []byte("kusama"), + ImplName: []byte("parity-kusama"), + AuthoringVersion: 2, + SpecVersion: 1020, + ImplVersion: 0, + APIItems: []runtime.APIItem{ + {Name: [8]uint8{0xdf, 0x6a, 0xcb, 0x68, 0x99, 0x7, 0x60, 0x9b}, Ver: 0x2}, + {Name: [8]uint8{0x37, 0xe3, 0x97, 0xfc, 0x7c, 0x91, 0xf5, 0xe4}, Ver: 0x1}, + {Name: [8]uint8{0x40, 0xfe, 0x3a, 0xd4, 0x1, 0xf8, 0x95, 0x9a}, Ver: 0x4}, + {Name: [8]uint8{0xd2, 0xbc, 0x98, 0x97, 0xee, 0xd0, 0x8f, 0x15}, Ver: 0x1}, + {Name: [8]uint8{0xf7, 0x8b, 0x27, 0x8b, 0xe5, 0x3f, 0x45, 0x4c}, Ver: 0x1}, + {Name: [8]uint8{0xaf, 0x2c, 0x2, 0x97, 0xa2, 0x3e, 0x6d, 0x3d}, Ver: 0x1}, + {Name: [8]uint8{0xed, 0x99, 0xc5, 0xac, 0xb2, 0x5e, 0xed, 0xf5}, Ver: 0x2}, + {Name: [8]uint8{0xcb, 0xca, 0x25, 0xe3, 0x9f, 0x14, 0x23, 0x87}, Ver: 0x1}, + {Name: [8]uint8{0x68, 0x7a, 0xd4, 0x4a, 0xd3, 0x7f, 0x3, 0xc2}, Ver: 0x1}, + {Name: [8]uint8{0xab, 0x3c, 0x5, 0x72, 0x29, 0x1f, 0xeb, 0x8b}, Ver: 0x1}, + {Name: [8]uint8{0xbc, 0x9d, 0x89, 0x90, 0x4f, 0x5b, 0x92, 0x3f}, Ver: 0x1}, + {Name: [8]uint8{0x37, 0xc8, 0xbb, 0x13, 0x50, 0xa9, 0xa2, 0xa8}, Ver: 0x1}, + }, + }, + }, + "polkadot_v0929": { + instanceBuilder: func(t *testing.T) instanceVersioner { + return NewTestInstance(t, runtime.POLKADOT_RUNTIME_v0929) + }, + expectedVersion: runtime.Version{ + SpecName: []byte("polkadot"), + ImplName: []byte("parity-polkadot"), + AuthoringVersion: 0, + SpecVersion: 9290, + ImplVersion: 0, + APIItems: []runtime.APIItem{ + {Name: [8]uint8{0xdf, 0x6a, 0xcb, 0x68, 0x99, 0x7, 0x60, 0x9b}, Ver: 0x4}, + {Name: [8]uint8{0x37, 0xe3, 0x97, 0xfc, 0x7c, 0x91, 0xf5, 0xe4}, Ver: 0x1}, + {Name: [8]uint8{0x40, 0xfe, 0x3a, 0xd4, 0x1, 0xf8, 0x95, 0x9a}, Ver: 0x6}, + {Name: [8]uint8{0x17, 0xa6, 0xbc, 0xd, 0x0, 0x62, 0xae, 0xb3}, Ver: 0x1}, + {Name: [8]uint8{0xd2, 0xbc, 0x98, 0x97, 0xee, 0xd0, 0x8f, 0x15}, Ver: 0x3}, + {Name: [8]uint8{0xf7, 0x8b, 0x27, 0x8b, 0xe5, 0x3f, 0x45, 0x4c}, Ver: 0x2}, + {Name: [8]uint8{0xaf, 0x2c, 0x2, 0x97, 0xa2, 0x3e, 0x6d, 0x3d}, Ver: 0x2}, + {Name: [8]uint8{0x49, 0xea, 0xaf, 0x1b, 0x54, 0x8a, 0xc, 0xb0}, Ver: 0x1}, + {Name: [8]uint8{0x91, 0xd5, 0xdf, 0x18, 0xb0, 0xd2, 0xcf, 0x58}, Ver: 0x1}, + {Name: [8]uint8{0xed, 0x99, 0xc5, 0xac, 0xb2, 0x5e, 0xed, 0xf5}, Ver: 0x3}, + {Name: [8]uint8{0xcb, 0xca, 0x25, 0xe3, 0x9f, 0x14, 0x23, 0x87}, Ver: 0x2}, + {Name: [8]uint8{0x68, 0x7a, 0xd4, 0x4a, 0xd3, 0x7f, 0x3, 0xc2}, Ver: 0x1}, + {Name: [8]uint8{0xab, 0x3c, 0x5, 0x72, 0x29, 0x1f, 0xeb, 0x8b}, Ver: 0x1}, + {Name: [8]uint8{0xbc, 0x9d, 0x89, 0x90, 0x4f, 0x5b, 0x92, 0x3f}, Ver: 0x1}, + {Name: [8]uint8{0x37, 0xc8, 0xbb, 0x13, 0x50, 0xa9, 0xa2, 0xa8}, Ver: 0x1}, + {Name: [8]uint8{0xf3, 0xff, 0x14, 0xd5, 0xab, 0x52, 0x70, 0x59}, Ver: 0x1}, + }, + TransactionVersion: 14, + }, + }, + "westend_v0929": { + instanceBuilder: func(t *testing.T) instanceVersioner { + return NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + }, + expectedVersion: runtime.Version{ + SpecName: []byte("westend"), + ImplName: []byte("parity-westend"), + AuthoringVersion: 2, + SpecVersion: 9290, + ImplVersion: 0, + APIItems: []runtime.APIItem{ + {Name: [8]uint8{0xdf, 0x6a, 0xcb, 0x68, 0x99, 0x7, 0x60, 0x9b}, Ver: 0x4}, + {Name: [8]uint8{0x37, 0xe3, 0x97, 0xfc, 0x7c, 0x91, 0xf5, 0xe4}, Ver: 0x1}, + {Name: [8]uint8{0x40, 0xfe, 0x3a, 0xd4, 0x1, 0xf8, 0x95, 0x9a}, Ver: 0x6}, + {Name: [8]uint8{0xd2, 0xbc, 0x98, 0x97, 0xee, 0xd0, 0x8f, 0x15}, Ver: 0x3}, + {Name: [8]uint8{0xf7, 0x8b, 0x27, 0x8b, 0xe5, 0x3f, 0x45, 0x4c}, Ver: 0x2}, + {Name: [8]uint8{0xaf, 0x2c, 0x2, 0x97, 0xa2, 0x3e, 0x6d, 0x3d}, Ver: 0x2}, + {Name: [8]uint8{0x49, 0xea, 0xaf, 0x1b, 0x54, 0x8a, 0xc, 0xb0}, Ver: 0x1}, + {Name: [8]uint8{0x91, 0xd5, 0xdf, 0x18, 0xb0, 0xd2, 0xcf, 0x58}, Ver: 0x1}, + {Name: [8]uint8{0xed, 0x99, 0xc5, 0xac, 0xb2, 0x5e, 0xed, 0xf5}, Ver: 0x3}, + {Name: [8]uint8{0xcb, 0xca, 0x25, 0xe3, 0x9f, 0x14, 0x23, 0x87}, Ver: 0x2}, + {Name: [8]uint8{0x68, 0x7a, 0xd4, 0x4a, 0xd3, 0x7f, 0x3, 0xc2}, Ver: 0x1}, + {Name: [8]uint8{0xab, 0x3c, 0x5, 0x72, 0x29, 0x1f, 0xeb, 0x8b}, Ver: 0x1}, + {Name: [8]uint8{0xbc, 0x9d, 0x89, 0x90, 0x4f, 0x5b, 0x92, 0x3f}, Ver: 0x1}, + {Name: [8]uint8{0x37, 0xc8, 0xbb, 0x13, 0x50, 0xa9, 0xa2, 0xa8}, Ver: 0x1}, + {Name: [8]uint8{0xf3, 0xff, 0x14, 0xd5, 0xab, 0x52, 0x70, 0x59}, Ver: 0x1}, + {Name: [8]uint8{0x17, 0xa6, 0xbc, 0xd, 0x0, 0x62, 0xae, 0xb3}, Ver: 0x1}, + }, + TransactionVersion: 12, + }, + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + instance := testCase.instanceBuilder(t) + version, err := instance.Version() + require.NoError(t, err) + assert.Equal(t, testCase.expectedVersion, version) + }) + } +} + +func balanceKey(t *testing.T, pub []byte) []byte { + h0, err := common.Twox128Hash([]byte("System")) + require.NoError(t, err) + h1, err := common.Twox128Hash([]byte("Account")) + require.NoError(t, err) + h2, err := common.Blake2b128(pub) + require.NoError(t, err) + return append(append(append(h0, h1...), h2...), pub...) +} + +func TestWestendRuntime_ValidateTransaction(t *testing.T) { + genesisPath := utils.GetWestendDevRawGenesisPath(t) + gen := genesisFromRawJSON(t, genesisPath) + genTrie, err := runtime.NewTrieFromGenesis(gen) + require.NoError(t, err) + + // set state to genesis state + genState := storage.NewTrieState(&genTrie) + + cfg := Config{ + Storage: genState, + LogLvl: log.Critical, + } + + nodeStorage := runtime.NodeStorage{} + nodeStorage.BaseDB = runtime.NewInMemoryDB(t) + cfg.NodeStorage = nodeStorage + + rt, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + + alicePub := common.MustHexToBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d") + aliceBalanceKey := balanceKey(t, alicePub) + + accInfo := types.AccountInfo{ + Nonce: 0, + Data: types.AccountData{ + Free: scale.MustNewUint128(big.NewInt(1152921504606846976)), + Reserved: scale.MustNewUint128(big.NewInt(0)), + MiscFrozen: scale.MustNewUint128(big.NewInt(0)), + FreeFrozen: scale.MustNewUint128(big.NewInt(0)), + }, + } + + encBal, err := scale.Marshal(accInfo) + require.NoError(t, err) + + rt.ctx.Storage.Put(aliceBalanceKey, encBal) + // this key is System.UpgradedToDualRefCount -> set to true since all accounts have been upgraded to v0.9 format + rt.ctx.Storage.Put(common.UpgradedToDualRefKey, []byte{1}) + + genesisHeader := &types.Header{ + Number: 0, + StateRoot: genTrie.MustHash(), + } + + extHex := runtime.NewTestExtrinsic(t, rt, genesisHeader.Hash(), genesisHeader.Hash(), + 0, signature.TestKeyringPairAlice, "System.remark", []byte{0xab, 0xcd}) + + genesisHashBytes := genesisHeader.Hash().ToBytes() + + validateTransactionArguments := [][]byte{ + {byte(types.TxnExternal)}, + common.MustHexToBytes(extHex), + genesisHashBytes} + + extrinsicsBytes := bytes.Join(validateTransactionArguments, nil) + + runtime.InitializeRuntimeToTest(t, rt, genesisHeader) + _, err = rt.ValidateTransaction(extrinsicsBytes) + require.NoError(t, err) +} + +func TestInstance_GrandpaAuthorities_NodeRuntime(t *testing.T) { + tt := trie.NewEmptyTrie() + + value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key := common.MustHexToBytes(genesis.GrandpaAuthoritiesKeyHex) + tt.Put(key, value) + + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + auths, err := rt.GrandpaAuthorities() + require.NoError(t, err) + + authABytes, _ := common.HexToBytes("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") + authBBytes, _ := common.HexToBytes("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") + + authA, _ := ed25519.NewPublicKey(authABytes) + authB, _ := ed25519.NewPublicKey(authBBytes) + + expected := []types.Authority{ + {Key: authA, Weight: 1}, + {Key: authB, Weight: 1}, + } + + require.Equal(t, expected, auths) +} + +func TestInstance_GrandpaAuthorities_PolkadotRuntime(t *testing.T) { + tt := trie.NewEmptyTrie() + + value, err := common.HexToBytes("0x0108eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key := common.MustHexToBytes(genesis.GrandpaAuthoritiesKeyHex) + tt.Put(key, value) + + rt := NewTestInstanceWithTrie(t, runtime.POLKADOT_RUNTIME_v0929, tt) + + auths, err := rt.GrandpaAuthorities() + require.NoError(t, err) + + authABytes, _ := common.HexToBytes("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") + authBBytes, _ := common.HexToBytes("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") + + authA, _ := ed25519.NewPublicKey(authABytes) + authB, _ := ed25519.NewPublicKey(authBBytes) + + expected := []types.Authority{ + {Key: authA, Weight: 1}, + {Key: authB, Weight: 1}, + } + + require.Equal(t, expected, auths) +} + +func TestInstance_BabeGenerateKeyOwnershipProof(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + targetRuntime string + }{ + { + name: "with_polkadot_runtime", + targetRuntime: runtime.POLKADOT_RUNTIME_v0929, + }, + { + name: "with_westend_runtime", + targetRuntime: runtime.WESTEND_RUNTIME_v0929, + }, + } + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + tt := trie.NewEmptyTrie() + + randomnessValue, err := common.HexToHash("0x01") + require.NoError(t, err) + key := common.MustHexToBytes(genesis.BABERandomnessKeyHex) + tt.Put(key, randomnessValue[:]) + + authorityValue, err := common.HexToBytes("0x08eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key = common.MustHexToBytes(genesis.BABEAuthoritiesKeyHex) + tt.Put(key, authorityValue) + + rt := NewTestInstanceWithTrie(t, testCase.targetRuntime, tt) + + babeConfig, err := rt.BabeConfiguration() + require.NoError(t, err) + + require.NotEmpty(t, babeConfig.GenesisAuthorities) + + authorityID := babeConfig.GenesisAuthorities[0].Key + + const slot = uint64(10) + res, err := rt.BabeGenerateKeyOwnershipProof(slot, authorityID) + require.NoError(t, err) + require.Nil(t, res) + }) + } +} + +func TestInstance_BabeSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + targetRuntime string + }{ + { + name: "with_polkadot_runtime", + targetRuntime: runtime.POLKADOT_RUNTIME_v0929, + }, + { + name: "with_westend_runtime", + targetRuntime: runtime.WESTEND_RUNTIME_v0929, + }, + } + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + tt := trie.NewEmptyTrie() + rt := NewTestInstanceWithTrie(t, testCase.targetRuntime, tt) + authorityID := types.AuthorityID{1} + const slot = uint64(1) + + keyOwnershipProof := testKeyOwnershipProof + + equivocationProof := types.BabeEquivocationProof{ + Offender: authorityID, + Slot: slot, + } + + err := rt.BabeSubmitReportEquivocationUnsignedExtrinsic(equivocationProof, keyOwnershipProof) + require.NoError(t, err) + }) + } +} + +func TestInstance_BabeConfiguration_WestendRuntime_NoAuthorities(t *testing.T) { + rt := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + cfg, err := rt.BabeConfiguration() + require.NoError(t, err) + + expected := &types.BabeConfiguration{ + SlotDuration: 6000, + EpochLength: 600, + C1: 1, + C2: 4, + GenesisAuthorities: nil, + Randomness: [32]byte{}, + SecondarySlots: 2, + } + require.Equal(t, expected, cfg) +} + +func TestInstance_BabeConfiguration_WestendRuntime_WithAuthorities(t *testing.T) { + tt := trie.NewEmptyTrie() + + randomnessValue, err := common.HexToHash("0x01") + require.NoError(t, err) + key := common.MustHexToBytes(genesis.BABERandomnessKeyHex) + tt.Put(key, randomnessValue[:]) + + authorityValue, err := common.HexToBytes("0x08eea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d714103640100000000000000b64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d7170100000000000000") //nolint:lll + require.NoError(t, err) + + key = common.MustHexToBytes(genesis.BABEAuthoritiesKeyHex) + tt.Put(key, authorityValue) + + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + cfg, err := rt.BabeConfiguration() + require.NoError(t, err) + + authA, _ := common.HexToHash("0xeea1eabcac7d2c8a6459b7322cf997874482bfc3d2ec7a80888a3a7d71410364") + authB, _ := common.HexToHash("0xb64994460e59b30364cad3c92e3df6052f9b0ebbb8f88460c194dc5794d6d717") + + expectedAuthData := []types.AuthorityRaw{ + {Key: authA, Weight: 1}, + {Key: authB, Weight: 1}, + } + + expected := &types.BabeConfiguration{ + SlotDuration: 6000, + EpochLength: 600, + C1: 1, + C2: 4, + GenesisAuthorities: expectedAuthData, + Randomness: [32]byte{1}, + SecondarySlots: 2, + } + + require.Equal(t, expected, cfg) +} + +func TestInstance_InitializeBlock_NodeRuntime(t *testing.T) { + rt := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + + header := &types.Header{ + Number: 1, + Digest: types.NewDigest(), + } + + err := rt.InitializeBlock(header) + require.NoError(t, err) +} + +func TestInstance_InitializeBlock_PolkadotRuntime(t *testing.T) { + rt := NewTestInstance(t, runtime.POLKADOT_RUNTIME_v0929) + + header := &types.Header{ + Number: 1, + Digest: types.NewDigest(), + } + + err := rt.InitializeBlock(header) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_WestendRuntime(t *testing.T) { + instance := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + block := runtime.InitializeRuntimeToTest(t, instance, &types.Header{}) + + // reset state back to parent state before executing + parentState := storage.NewTrieState(nil) + instance.SetContextStorage(parentState) + + _, err := instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ApplyExtrinsic_WestendRuntime(t *testing.T) { + genesisPath := utils.GetWestendDevRawGenesisPath(t) + gen := genesisFromRawJSON(t, genesisPath) + genTrie, err := runtime.NewTrieFromGenesis(gen) + require.NoError(t, err) + + // set state to genesis state + genState := storage.NewTrieState(&genTrie) + + cfg := Config{ + Storage: genState, + LogLvl: log.Critical, + } + + instance, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + + // reset state back to parent state before executing + parentState := storage.NewTrieState(&genTrie) + instance.SetContextStorage(parentState) + + genesisHeader := &types.Header{ + Number: 0, + StateRoot: genTrie.MustHash(), + } + header := &types.Header{ + ParentHash: genesisHeader.Hash(), + Number: 1, + Digest: types.NewDigest(), + } + + err = instance.InitializeBlock(header) + require.NoError(t, err) + + extHex := runtime.NewTestExtrinsic(t, instance, genesisHeader.Hash(), genesisHeader.Hash(), + 0, signature.TestKeyringPairAlice, "System.remark", []byte{0xab, 0xcd}) + + res, err := instance.ApplyExtrinsic(common.MustHexToBytes(extHex)) + require.NoError(t, err) + require.Equal(t, []byte{0, 0}, res) +} + +func TestInstance_ExecuteBlock_PolkadotRuntime(t *testing.T) { + DefaultTestLogLvl = 0 + + instance := NewTestInstance(t, runtime.POLKADOT_RUNTIME_v0929) + + block := runtime.InitializeRuntimeToTest(t, instance, &types.Header{}) + + // reset state back to parent state before executing + parentState := storage.NewTrieState(nil) + instance.SetContextStorage(parentState) + + _, err := instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_PolkadotRuntime_PolkadotBlock1(t *testing.T) { + genesisPath := utils.GetPolkadotGenesisPath(t) + gen := genesisFromRawJSON(t, genesisPath) + genTrie, err := runtime.NewTrieFromGenesis(gen) + require.NoError(t, err) + + expectedGenesisRoot := common.MustHexToHash("0x29d0d972cd27cbc511e9589fcb7a4506d5eb6a9e8df205f00472e5ab354a4e17") + require.Equal(t, expectedGenesisRoot, genTrie.MustHash()) + + // set state to genesis state + genState := storage.NewTrieState(&genTrie) + + cfg := Config{ + Storage: genState, + LogLvl: log.Critical, + } + + instance, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + + // block data is received from querying a polkadot node + body := []byte{8, 40, 4, 3, 0, 11, 80, 149, 160, 81, 114, 1, 16, 4, 20, 0, 0} + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 2, len(exts)) + + // digest data received from querying polkadot node + digestBytes := common.MustHexToBytes("0x0c0642414245b501010000000093decc0f00000000362ed8d6055645487fe42e9c8640be651f70a3a2a03658046b2b43f021665704501af9b1ca6e974c257e3d26609b5f68b5b0a1da53f7f252bbe5d94948c39705c98ffa4b869dd44ac29528e3723d619cc7edf1d3f7b7a57a957f6a7e9bdb270a044241424549040118fa3437b10f6e7af8f31362df3a179b991a8c56313d1bcd6307a4d0c734c1ae310100000000000000d2419bc8835493ac89eb09d5985281f5dff4bc6c7a7ea988fd23af05f301580a0100000000000000ccb6bef60defc30724545d57440394ed1c71ea7ee6d880ed0e79871a05b5e40601000000000000005e67b64cf07d4d258a47df63835121423551712844f5b67de68e36bb9a21e12701000000000000006236877b05370265640c133fec07e64d7ca823db1dc56f2d3584b3d7c0f1615801000000000000006c52d02d95c30aa567fda284acf25025ca7470f0b0c516ddf94475a1807c4d250100000000000000000000000000000000000000000000000000000000000000000000000000000005424142450101d468680c844b19194d4dfbdc6697a35bf2b494bda2c5a6961d4d4eacfbf74574379ba0d97b5bb650c2e8670a63791a727943bcb699dc7a228bdb9e0a98c9d089") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + + // polkadot block 1, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3"), + Number: 1, + StateRoot: common.MustHexToHash("0xc56fcd6e7a757926ace3e1ecff9b4010fc78b90d459202a339266a7f6360002f"), + ExtrinsicsRoot: common.MustHexToHash("0x9a87f6af64ef97aff2d31bebfdd59f8fe2ef6019278b634b2515a38f1c4c2420"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock1(t *testing.T) { + genesisPath := utils.GetKusamaGenesisPath(t) + gen := genesisFromRawJSON(t, genesisPath) + genTrie, err := runtime.NewTrieFromGenesis(gen) + require.NoError(t, err) + + expectedGenesisRoot := common.MustHexToHash("0xb0006203c3a6e6bd2c6a17b1d4ae8ca49a31da0f4579da950b127774b44aef6b") + require.Equal(t, expectedGenesisRoot, genTrie.MustHash()) + + // set state to genesis state + genState := storage.NewTrieState(&genTrie) + + cfg := Config{ + Storage: genState, + LogLvl: log.Critical, + } + + instance, err := NewRuntimeFromGenesis(cfg) + require.NoError(t, err) + + // block data is received from querying a polkadot node + body := []byte{8, 40, 4, 2, 0, 11, 144, 17, 14, 179, 110, 1, 16, 4, 20, 0, 0} + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 2, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x0c0642414245340201000000ef55a50f00000000044241424549040118ca239392960473fe1bc65f94ee27d890a49c1b200c006ff5dcc525330ecc16770100000000000000b46f01874ce7abbb5220e8fd89bede0adad14c73039d91e28e881823433e723f0100000000000000d684d9176d6eb69887540c9a89fa6097adea82fc4b0ff26d1062b488f352e179010000000000000068195a71bdde49117a616424bdc60a1733e96acb1da5aeab5d268cf2a572e94101000000000000001a0575ef4ae24bdfd31f4cb5bd61239ae67c12d4e64ae51ac756044aa6ad8200010000000000000018168f2aad0081a25728961ee00627cfe35e39833c805016632bf7c14da5800901000000000000000000000000000000000000000000000000000000000000000000000000000000054241424501014625284883e564bc1e4063f5ea2b49846cdddaa3761d04f543b698c1c3ee935c40d25b869247c36c6b8a8cbbd7bb2768f560ab7c276df3c62df357a7e3b1ec8d") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + + // kusama block 1, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe"), + Number: 1, + StateRoot: common.MustHexToHash("0xfabb0c6e92d29e8bb2167f3c6fb0ddeb956a4278a3cf853661af74a076fc9cb7"), + ExtrinsicsRoot: common.MustHexToHash("0xa35fb7f7616f5c979d48222b3d2fa7cb2331ef73954726714d91ca945cc34fd8"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock3784(t *testing.T) { + gossTrie3783 := newTrieFromPairs(t, "../test_data/kusama/block3783.out") + expectedRoot := common.MustHexToHash("0x948338bc0976aee78879d559a1f42385407e5a481b05a91d2a9386aa7507e7a0") + require.Equal(t, expectedRoot, gossTrie3783.MustHash()) + + // set state to genesis state + state3783 := storage.NewTrieState(gossTrie3783) + + cfg := Config{ + Storage: state3783, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(gossTrie3783, cfg) + require.NoError(t, err) + + // block data is received from querying a polkadot node + body := common.MustHexToBytes("0x10280402000bb00d69b46e0114040900193b10041400009101041300eaaec5728cd6ea9160ff92a49bb45972c532d2163241746134726aaa5b2f72129d8650715320f23765c6306503669f69bf684b188dea73b1e247dd1dd166513b1c13daa387c35f24ac918d2fa772b73cffd20204a8875e48a1b11bb3229deb7f00") //nolint:lll + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 4, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x080642414245340203000000bd64a50f0000000005424142450101bc0d6850dba8d32ea1dbe26cb4ac56da6cca662c7cc642dc8eed32d2bddd65029f0721436eafeebdf9b4f17d1673c6bc6c3c51fe3dda3121a5fc60c657a5808b") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + + // kusama block 3784, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x4843b4aa38cf2e3e2f6fae401b98dd705bed668a82dd3751dc38f1601c814ca8"), + Number: 3784, + StateRoot: common.MustHexToHash("0xac44cc18ec22f0f3fca39dfe8725c0383af1c982a833e081fbb2540e46eb09a5"), + ExtrinsicsRoot: common.MustHexToHash("0x52b7d4852fc648cb8f908901e1e36269593c25050c31718454bca74b69115d12"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock901442(t *testing.T) { + ksmTrie901441 := newTrieFromPairs(t, "../test_data/kusama/block901441.out") + expectedRoot := common.MustHexToHash("0x3a2ef7ee032f5810160bb8f3ffe3e3377bb6f2769ee9f79a5425973347acd504") + require.Equal(t, expectedRoot, ksmTrie901441.MustHash()) + + // set state to genesis state + state901441 := storage.NewTrieState(ksmTrie901441) + + cfg := Config{ + Storage: state901441, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(ksmTrie901441, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x0c280402000b207eb80a70011c040900fa0437001004140000") + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 3, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x080642414245340244000000aeffb30f00000000054241424501011cbef2a084a774c34d9990c7bfc6b4d2d5e9f5b59feca792cd2bb89a890c2a6f09668b5e8224879f007f49f299d25fbb3c0f30d94fb8055e07fa8a4ed10f8083") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + require.Equal(t, 2, len(digest.Types)) + + // kusama block 901442, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x68d9c5f75225f09d7ce493eff8aabac7bae8b65cb81a2fd532a99fbb8c663931"), + Number: 901442, + StateRoot: common.MustHexToHash("0x6ea065f850894c5b58cb1a73ec887e56842851943641149c57cea357cae4f596"), + ExtrinsicsRoot: common.MustHexToHash("0x13483a4c148fff5f072e86b5af52bf031556514e9c87ea19f9e31e7b13c0c414"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock1377831(t *testing.T) { + ksmTrie := newTrieFromPairs(t, "../test_data/kusama/block1377830.out") + expectedRoot := common.MustHexToHash("0xe4de6fecda9e9e35f937d159665cf984bc1a68048b6c78912de0aeb6bd7f7e99") + require.Equal(t, expectedRoot, ksmTrie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(ksmTrie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(ksmTrie, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x08280402000b60c241c070011004140000") + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 2, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x080642414245b50101020000008abebb0f00000000045553c32a949242580161bcc35d7c3e492e66defdcf4525d7a338039590012f42660acabf1952a2d5d01725601705404d6ac671507a6aa2cf09840afbdfbb006f48062dae16c56b8dc5c6ea6ffba854b7e8f46e153e98c238cbe7bbb1556f0b0542414245010136914c6832dd5ba811a975a3b654d76a1ec81684f4b03d115ce2e694feadc96411930438fde4beb008c5f8e26cfa2f5b554fa3814b5b73d31f348446fd4fd688") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + require.Equal(t, 2, len(digest.Types)) + + // kusama block 1377831, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0xca387b3cc045e8848277069d8794cbf077b08218c0b55f74d81dd750b14e768c"), + Number: 1377831, + StateRoot: common.MustHexToHash("0x7e5569e652c4b1a3cecfcf5e5e64a97fe55071d34bab51e25626ec20cae05a02"), + ExtrinsicsRoot: common.MustHexToHash("0x7f3ea0ed63b4053d9b75e7ee3e5b3f6ce916e8f59b7b6c5e966b7a56ea0a563a"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock1482003(t *testing.T) { + ksmTrie := newTrieFromPairs(t, "../test_data/kusama/block1482002.out") + expectedRoot := common.MustHexToHash("0x09f9ca28df0560c2291aa16b56e15e07d1e1927088f51356d522722aa90ca7cb") + require.Equal(t, expectedRoot, ksmTrie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(ksmTrie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(ksmTrie, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x0c280402000b10c3e3e570011c04090042745a001004140000") + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 3, len(exts)) + + // digest from polkadot.js + digestBytes := testdata.DigestKusama1482002(t) + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + + require.Equal(t, 4, len(digest.Types)) + + // kusama block 1482003, from polkadot.js + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x587f6da1bfa71a675f10dfa0f63edfcf168e8ece97eb5f526aaf0e8a8e82db3f"), + Number: 1482003, + StateRoot: common.MustHexToHash("0xd2de750002f33968437bdd54912dd4f55c3bddc5a391a8e0b8332568e1efea8d"), + ExtrinsicsRoot: common.MustHexToHash("0xdf5da95780b77e83ad0bf820d5838f07a0d5131aa95a75f8dfbd01fbccb300bd"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_KusamaRuntime_KusamaBlock4939774(t *testing.T) { + t.Skip("skip for now as block4939773 is too large") + ksmTrie := newTrieFromPairs(t, "../test_data/kusama/block4939773.out") + expectedRoot := common.MustHexToHash("0xc45748e6e8632b44fc32b04cc4380098a9584cbd63ffbc59adce189574fc36fe") + require.Equal(t, expectedRoot, ksmTrie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(ksmTrie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(ksmTrie, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x08280402000b80eb3cd17501710984c2292bcf6f34fc2d25f7a1ebaec41c3239536f12f75417c73f7c5aca53308668016ec90c2318ee45af373755527436c4d7a257c481fdc3214634eb4b5c6711ae181827c378843da82c72191647667607ee97e0f0335f14d0876c63503b5f2b8986650304001f010200083e1f2bfd408d3b8d2266ce9b6f2d40acef27b773414537be72576ee3e6108b256eb45e26258d7ac737c3ad3af8cd1b2208d45c472ba19ebfc3e2fb834a6e904d01de574b00010000007506180228040052dac5497bbdd42583d07aa46102790d54aacdcbfac8877189e3b609117a29150b00a0724e180904001cf8853df87ca8588405e30c46a434d636c86561b955b09e2e9b27fc296bf4290b005039278c040400f49db9c8894863a7dd213be93b1c440b145cc19d4927b4c29fe5fa25e8a1667f0b005039278c040400e05f031d874257a24232076830a073a6af6851c07735de201edfc412ca8853180b005039278c0404009289e88ec986066d04f7d93d80f7a3c9794580b5e59d2a7af6b19745dd148f6f0b005039278c0404006c8aff52c496b64b476ca22e58fc54822b435abbbbcaf0c9dd7cf1ab573227790b005039278c04040044e31f7c4afa3b055696923ccb405da2ee2d9eefccf568aa3c6855dbff573e5f0b005039278c040400469ec0f872af2503a9251666fd089d0e84d3f6c8b761ee94b0e868788e0f60500b005039278c040400b41cc00e4ee2945ce9974dbb355265e39c9cf325c176147d7f6b1631af38ce590b005039278c040400d8e2f26a12d4bfc513fd32c1e5a7f14e930c3ef37997bf4e3de2fed51eed515a0b005039278c040048227b8300000000") //nolint:lll + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 2, len(exts)) + + digestBytes := common.MustHexToBytes("0x080642414245b50101ef0100000815f30f000000004014ed1a99f017ea2c0d879d7317f51106938f879b296ff92c64319c0c70fe453d72035395da8d53e885def26e63cf90461ee549d0864f9691a4f401b31c1801730c014bc0641b307e8a30692e7d074b4656993b40d6f08698bc49dea40c11090542414245010192ed24972a8108b9bad1a8785b443efe72d4bc2069ab40eac65519fb01ff04250f44f6202d30ca88c30fee385bc8d7f51df15dddacf4e5d53788d260ce758c89") //nolint:lll + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + require.Equal(t, 2, len(digest.Types)) + + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0xac08290f49cb9760a3a4c5a49351af76ba9432add29178e5cc27d4451f9126c9"), + Number: 4939774, + StateRoot: common.MustHexToHash("0x5d66f43cdbf1740b8ca41f0cd016602f1648fb08b74fe49f5f078845071d0a54"), + ExtrinsicsRoot: common.MustHexToHash("0x5d887e118ee6320aca38e49cbd98adc25472c6efbf77a695ab0d6c476a4ec6e9"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ExecuteBlock_PolkadotBlock1089328(t *testing.T) { + dotTrie := newTrieFromPairs(t, "../test_data/polkadot/block1089327.json") + expectedRoot := common.MustHexToHash("0x87ed9ebe7fb645d3b5b0255cc16e78ed022d9fbb52486105436e15a74557535b") + require.Equal(t, expectedRoot, dotTrie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(dotTrie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(dotTrie, cfg) + require.NoError(t, err) + + body := common.MustHexToBytes("0x0c280403000be02ab6d873011004140000b90384468e34dbdcc8da24e44b0f0d34d97ccad5ce0281e465db0cc1d8e1423d50d90a018a89185c693f77b050fa35d1f80b19608b72a6e626110e835caedf949668a12b0ad7b786accf2caac0ec874941ccea9825d50b6bb5870e1400f0e56bb4c18b87a5021501001d00862e432e0cf75693899c62691ac0f48967f815add97ae85659dcde8332708551001b000cf4da8aea0e5649a8bedbc1f08e8a8c0febe50cd5b1c9ce0da2164f19aef40f01014a87a7d3673e5c80aec79973682140828a0d1c3899f4f3cc953bd02673e11a022aaa4f269e3f1a90156db29df88f780b1540b610aeb5cd347ee703c5dff48485") //nolint:lll + var exts [][]byte + err = scale.Unmarshal(body, &exts) + require.NoError(t, err) + require.Equal(t, 3, len(exts)) + + // digest from polkadot.js + digestBytes := common.MustHexToBytes("0x080642414245b501017b000000428edd0f00000000c4fd75c7535d8eec375d70d21cc62262247b599aa67d8a9cf2f7d1b8cb93cd1f9539f04902c33d4c0fe47f723dfed8505d31de1c04d0036a9df233ff902fce0d70060908faa4b3f481e54cbd6a52dfc20c3faac82f746d84dc03c2f824a89a0d0542414245010122041949669a56c8f11b3e3e7c803e477ad24a71ed887bc81c956b59ea8f2b30122e6042494aab60a75e0db8fdff45951e456e6053bd64eb5722600e4a13038b") //nolint:lll + + digest := types.NewDigest() + err = scale.Unmarshal(digestBytes, &digest) + require.NoError(t, err) + require.Equal(t, 2, len(digest.Types)) + + block := &types.Block{ + Header: types.Header{ + ParentHash: common.MustHexToHash("0x21dc35454805411be396debf3e1d5aad8d6e9d0d7679cce0cc632ba8a647d07c"), + Number: 1089328, + StateRoot: common.MustHexToHash("0x257b1a7f6bc0287fcbf50676dd29817f2f7ae193cb65b31962e351917406fa23"), + ExtrinsicsRoot: common.MustHexToHash("0x950173af1d9fdcd0be5428fc3eaf05d5f34376bd3882d9a61b348fa2dc641012"), + Digest: digest, + }, + Body: *types.NewBody(types.BytesArrayToExtrinsics(exts)), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_DecodeSessionKeys(t *testing.T) { + keys := "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d34309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc3852042602634309a9d2a24213896ff06895db16aade8b6502f3a71cf56374cc38520426026" //nolint:lll + pubkeys, err := common.HexToBytes(keys) + require.NoError(t, err) + + pukeysBytes, err := scale.Marshal(pubkeys) + require.NoError(t, err) + + instance := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + decoded, err := instance.DecodeSessionKeys(pukeysBytes) + require.NoError(t, err) + + var decodedKeys *[]struct { + Data []uint8 + Type [4]uint8 + } + + err = scale.Unmarshal(decoded, &decodedKeys) + require.NoError(t, err) + + require.NotNil(t, decodedKeys) + require.Len(t, *decodedKeys, 6) +} + +func TestInstance_PaymentQueryInfo(t *testing.T) { + tests := []struct { + extB []byte + ext string + errMessage string + expect *types.RuntimeDispatchInfo + }{ + { + // Was made with @polkadot/api on https://github.com/danforbes/polkadot-js-scripts/tree/create-signed-tx + ext: "0xd1018400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01bc2b6e35929aabd5b8bc4e5b0168c9bee59e2bb9d6098769f6683ecf73e44c776652d947a270d59f3d37eb9f9c8c17ec1b4cc473f2f9928ffdeef0f3abd43e85d502000000012844616e20466f72626573", //nolint:lll + expect: &types.RuntimeDispatchInfo{ + Weight: 0, + Class: 0, + PartialFee: &scale.Uint128{ + Upper: 0, + Lower: uint64(12800000000), + }, + }, + }, + { + // incomplete extrinsic + ext: "0x4ccde39a5684e7a56da23b22d4d9fbadb023baa19c56495432884d0640000000000000000000000000000000", + errMessage: "running runtime function: " + + "Failed to call the `TransactionPaymentApi_query_info` exported function.", + }, + { + // incomplete extrinsic + extB: nil, + errMessage: "running runtime function: " + + "Failed to call the `TransactionPaymentApi_query_info` exported function.", + }, + } + + for _, test := range tests { + var err error + var extBytes []byte + + if test.ext == "" { + extBytes = test.extB + } else { + extBytes, err = common.HexToBytes(test.ext) + require.NoError(t, err) + } + + ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + info, err := ins.PaymentQueryInfo(extBytes) + + if test.errMessage != "" { + assert.EqualError(t, err, test.errMessage) + continue + } + require.NoError(t, err) + require.NotNil(t, info) + require.Equal(t, test.expect, info) + } +} + +func newTrieFromPairs(t *testing.T, filename string) *trie.Trie { + data, err := os.ReadFile(filename) + require.NoError(t, err) + + rpcPairs := make(map[string]interface{}) + err = json.Unmarshal(data, &rpcPairs) + require.NoError(t, err) + pairs := rpcPairs["result"].([]interface{}) + + entries := make(map[string]string) + for _, pair := range pairs { + pairArr := pair.([]interface{}) + entries[pairArr[0].(string)] = pairArr[1].(string) + } + + tr, err := trie.LoadFromMap(entries) + require.NoError(t, err) + return &tr +} + +func TestInstance_TransactionPaymentCallApi_QueryCallInfo(t *testing.T) { + t.Parallel() + ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + tests := []struct { + callHex string + errMessage string + expect *types.RuntimeDispatchInfo + }{ + { + // call generated by using palkadot.js/api v9.5.1: api.tx.system.remark("Ed") + // and removing first byte (encoding) and second byte (unknown) + callHex: "0x0001084564", + expect: &types.RuntimeDispatchInfo{ + Weight: 0, + Class: 0, + PartialFee: &scale.Uint128{ + Upper: 0, + Lower: uint64(1500000000), + }, + }, + }, + { + // call removing encoding (first byte), polkadot.js/api v9.5.1: api.tx.system.remark("Ed") + // polkadot.js/api returns error: RPC-CORE: call(method: Text, data: Bytes, at?: BlockHash): + // Bytes:: -32000: Client error: Execution failed: Execution aborted due to trap: wasm trap: wasm + //`unreachable` instruction executed + callHex: "0x040001084564", + errMessage: "running runtime function: " + + "Failed to call the `TransactionPaymentCallApi_query_call_info` exported function.", + }, + { + // call without removing any bytes, polkadot.js/api v9.5.1: api.tx.system.remark("Ed test") + // polkadot.js/api returns error: Error: createType(Call):: findMetaCall: Unable to find Call with index + // [44, 4]/[44,4] + callHex: "0x2c0400011c45642074657374", + errMessage: "running runtime function: " + + "Failed to call the `TransactionPaymentCallApi_query_call_info` exported function.", + }, + } + + for _, test := range tests { + var err error + var callBytes []byte + + callBytes, err = common.HexToBytes(test.callHex) + require.NoError(t, err) + + info, err := ins.QueryCallInfo(callBytes) + + if test.errMessage != "" { + assert.EqualError(t, err, test.errMessage) + continue + } + + require.NoError(t, err) + require.NotNil(t, info) + require.Equal(t, test.expect, info) + } +} + +func TestInstance_TransactionPaymentCallApi_QueryCallFeeDetails(t *testing.T) { + t.Parallel() + ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + tests := []struct { + callHex string + errMessage string + expect *types.FeeDetails + }{ + { + // call generated by using palkadot.js/api v9.5.1: api.tx.system.remark("Ed") + // and removing first byte (encoding) and second byte (unknown) + callHex: "0x0001084564", + expect: &types.FeeDetails{ + InclusionFee: types.InclusionFee{ + BaseFee: &scale.Uint128{ + Upper: 0, + Lower: uint64(256000000001), + }, + LenFee: &scale.Uint128{ + Upper: 0, + Lower: uint64(128000000000), + }, + AdjustedWeightFee: &scale.Uint128{}, + }, + Tip: &scale.Uint128{}, + }, + }, + { + // call removing encoding (first byte), polkadot.js/api v9.5.1: api.tx.system.remark("Ed") + // when calling polkadot node (v0.9.29) with polkadot.js/api the node returns error: RPC-CORE: call( + // method: Text, data: Bytes, at?: BlockHash): Bytes:: -32000: Client error: Execution failed: + // Execution aborted due to trap: wasm trap: wasm `unreachable` instruction executed + callHex: "0x040001084564", + errMessage: "running runtime function: " + + "Failed to call the `TransactionPaymentCallApi_query_call_fee_details` exported function.", + }, + { + // call without removing any bytes, polkadot.js/api v9.5.1: api.tx.system.remark("Ed test") + // when calling polkadot (v0.9.29) with polkadot.js/api the node returns error: Error: createType( + //Call):: findMetaCall: Unable to find Call with index [44, 4]/[44,4] + callHex: "0x18040001084564", + errMessage: "running runtime function: " + + "Failed to call the `TransactionPaymentCallApi_query_call_fee_details` exported function.", + }, + } + + for _, test := range tests { + extBytes, err := common.HexToBytes(test.callHex) + require.NoError(t, err) + + details, err := ins.QueryCallFeeDetails(extBytes) + + if test.errMessage != "" { + assert.EqualError(t, err, test.errMessage) + continue + } + + require.NoError(t, err) + require.NotNil(t, details) + require.Equal(t, test.expect, details) + } +} + +func TestInstance_GrandpaGenerateKeyOwnershipProof(t *testing.T) { + t.Parallel() + instance := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + identity := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee") + identityPubKey, _ := ed25519.NewPublicKey(identity) + authorityID := identityPubKey.AsBytes() + + opaqueKeyOwnershipProof, err := instance.GrandpaGenerateKeyOwnershipProof(uint64(0), authorityID) + // Since the input is not valid with respect to the instance, an empty proof is returned + require.NoError(t, err) + require.Nil(t, opaqueKeyOwnershipProof) +} + +func TestInstance_GrandpaSubmitReportEquivocationUnsignedExtrinsic(t *testing.T) { + t.Parallel() + identity := common.MustHexToBytes("0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee") + identityPubKey, _ := ed25519.NewPublicKey(identity) + runtime := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929) + + keyOwnershipProofRaw := types.GrandpaOpaqueKeyOwnershipProof([]byte{64, 138, 252, 29, 127, 102, 189, 129, 207, 47, + 157, 60, 17, 138, 194, 121, 139, 92, 176, 175, 224, 16, 185, 93, 175, 251, 224, 81, 209, 61, 0, 71}) + keyOwnershipProof := scale.MustMarshal(keyOwnershipProofRaw) + + var opaqueKeyOwnershipProof types.GrandpaOpaqueKeyOwnershipProof + err := scale.Unmarshal(keyOwnershipProof, &opaqueKeyOwnershipProof) + require.NoError(t, err) + + firstVote := types.GrandpaVote{ + Hash: common.MustHexToHash("0x4801b8e62d31167d30c893cc1970f6a0e289420282a4b245b75f2c46fb308af1"), + Number: 10, + } + secondVote := types.GrandpaVote{ + Hash: common.MustHexToHash("0xc314327941fdd924bc67fd72651c40aececd485ca3e878c21e02abb40feae5bd"), + Number: 10, + } + + firstSignatureArray := mustHexTo64BArray(t, "0xd7292caacc62504365f179892a7399f233944bf261f8a3f66260f70e0016f2d"+ + "b63922726b015c82dc7131f4730fbec61f71672a571453e51029bfb469070900f") + + secondSignatureArray := mustHexTo64BArray(t, "0xb3c408b74905dfedfffa66f99f16fe8b938fd8df76a92225228a1ca07523"+ + "0b99a2d9e173c561952e1e378b701915ca188d2c832ef92a3fab8e455f32570c0807") + + grandpaEquivocation := types.GrandpaEquivocation{ + RoundNumber: 1, + ID: identityPubKey.AsBytes(), + FirstVote: firstVote, + FirstSignature: firstSignatureArray, + SecondVote: secondVote, + SecondSignature: secondSignatureArray, + } + preVoteEquivocation := types.PreVote(grandpaEquivocation) + equivocationVote := types.NewGrandpaEquivocation() + err = equivocationVote.Set(preVoteEquivocation) + require.NoError(t, err) + + equivocationProof := types.GrandpaEquivocationProof{ + SetID: 1, + Equivocation: *equivocationVote, + } + err = runtime.GrandpaSubmitReportEquivocationUnsignedExtrinsic(equivocationProof, opaqueKeyOwnershipProof) + require.NoError(t, err) +} + +func loadEntries(t *testing.T, filename string) *trie.Trie { + data, err := os.ReadFile(filename) + require.NoError(t, err) + + entries := make([][2][]byte, 0) + err = json.Unmarshal(data, &entries) + require.NoError(t, err) + + tr, err := trie.LoadFromEntries(entries) + require.NoError(t, err) + return tr +} + +func TestInstance_ExecuteBlock_WestendBlock1097836(t *testing.T) { + trie := loadEntries(t, "../test_data/westend/entrieslist-1097836.json") + expectedRoot := common.MustHexToHash("0x97d68d4c5a01571cf4beea9b058d53dfd6d6ce5382d0657a185041d736880e03") + require.Equal(t, expectedRoot, trie.MustHash()) + + // set state to genesis state + state := storage.NewTrieState(trie) + + cfg := Config{ + Storage: state, + LogLvl: log.Critical, + } + + instance, err := NewInstanceFromTrie(trie, cfg) + require.NoError(t, err) + + digest := types.NewDigest() + digest.Add( + *types.NewBABEPreRuntimeDigest(common.MustHexToBytes("0x02020000006522d30f00000000")), + types.SealDigest{ + ConsensusEngineID: types.BabeEngineID, + Data: common.MustHexToBytes("0xa06e4a23ae347c7edd24f84153c007563895d64a06b8781b1e21bf2c8bc426676bfd4bf20c08f276e54598aff3b64541d84c4b5da7bfa39479d0a45585a75388"), //nolint:lll + }, + ) + + exts := make([]types.Extrinsic, 0) + ext, err := common.HexToBytes("0x0402000b301f76e47201") + require.NoError(t, err) + exts = append(exts, ext) + ext, err = common.HexToBytes("0x040d0000") + require.NoError(t, err) + exts = append(exts, ext) + ext, err = common.HexToBytes("0x84c2c9676ac7a4e56bcb861cf443899114a17baa817ae5c295b9bb6f947fc427fd02db25d6a66498b5e81ac3a52ae4025eef7bb36eee31195c60c7ebdb6f0bac4177baf32e73719fe3e5fdce1059e9e16bb85bad0a0c4e34c4b0e680fb7a132cc4f7018502000004000c60f6d9b5a5ee5a0c0428d1940936a1b91cd29924578f7ac9e793db6dab0cd70700e40b5402") //nolint:lll + require.NoError(t, err) + exts = append(exts, ext) + + header := types.NewHeader( + common.MustHexToHash("0x805b7d8f50e4f30b014a25460c3a4057072ed902058d1f49fbbd99d3d6925ba3"), + common.MustHexToHash("0xb4df4c5bbceb56923f77d003e5064a839d3a319c0c930b955159637fdd74c393"), + common.MustHexToHash("0x2b0ee636bae60b595392d330a57e20524a13614605d3b3665433b7875f7a06fc"), + 1097836, + digest, + ) + require.Equal(t, "0x32ad1878e447c67f12395cef8d3f9e1c7871170711ba61350f40766e00998f89", header.Hash().String()) + + block := &types.Block{ + Header: *header, + Body: types.Body(exts), + } + + _, err = instance.ExecuteBlock(block) + require.NoError(t, err) +} + +func TestInstance_ParachainHostValidators(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) + + response, err := rt.ParachainHostValidators() + require.NoError(t, err) + + expected := []parachain.ValidatorID{ + parachain.ValidatorID(mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x74c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xe61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xb61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xcee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xe2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848")), + parachain.ValidatorID(mustHexTo32BArray(t, "0xa0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a")), + parachain.ValidatorID(mustHexTo32BArray(t, "0x4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936")), + } + require.Equal(t, expected, response) +} + +func TestInstance_ParachainHostValidatorGroups(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) + + response, err := rt.ParachainHostValidatorGroups() + require.NoError(t, err) + + expected := ¶chain.ValidatorGroups{ + Validators: [][]parachain.ValidatorIndex{ + {0, 1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10, 11}, + {12, 13, 14, 15, 16}, + }, + GroupRotationInfo: parachain.GroupRotationInfo{ + SessionStartBlock: 15946156, + GroupRotationFrequency: 10, + Now: 15946391, + }, + } + + require.Equal(t, expected, response) +} + +func TestInstance_ParachainHostAvailabilityCores(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) + + response, err := rt.ParachainHostAvailabilityCores() + require.NoError(t, err) + + expectedHash := parachainTestData.Expected["availabilityCores"] + if expectedHash == "" { + t.Fatal("could not get expected hash from test data") + } + expected := common.MustHexToBytes(expectedHash) + encoded, err := scale.Marshal(*response) + require.NoError(t, err) + require.Equal(t, expected, encoded) +} + +func TestInstance_ParachainHostSessionIndexForChild(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0929, tt) + + response, err := rt.ParachainHostSessionIndexForChild() + require.NoError(t, err) + + expected := parachain.SessionIndex(27379) + require.Equal(t, expected, response) +} + +func TestInstance_ParachainHostCandidatePendingAvailability(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) + + response, err := rt.ParachainHostCandidatePendingAvailability(parachain.ParaID(1000)) + require.NoError(t, err) + + expectedHash := parachainTestData.Expected["candidatePendingAvailability"] + if expectedHash == "" { + t.Fatal("could not get expected hash from test data") + } + + b, err := scale.Marshal(*response) + require.NoError(t, err) + + resultHex := common.BytesToHex(b) + require.Equal(t, expectedHash, resultHex) +} + +func TestInstance_ParachainHostCandidateEvents(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) + + response, err := rt.ParachainHostCandidateEvents() + require.NoError(t, err) + + encoded, err := scale.Marshal(*response) + require.NoError(t, err) + expectedHash := parachainTestData.Expected["candidateEvents"] + if expectedHash == "" { + t.Fatal("candidateEvents expected hash is not defined in test data") + } + expected := common.MustHexToBytes(expectedHash) + require.Equal(t, expected, encoded) +} + +func TestInstance_ParachainHostSessionInfo(t *testing.T) { + t.Parallel() + + tt := getParachainHostTrie(t) + rt := NewTestInstanceWithTrie(t, runtime.WESTEND_RUNTIME_v0942, tt) + + response, err := rt.ParachainHostSessionInfo(parachain.SessionIndex(27379)) + require.NoError(t, err) + + expected := ¶chain.SessionInfo{ + ActiveValidatorIndices: []parachain.ValidatorIndex{7, 12, 14, 1, 4, 16, 3, 11, 9, 6, 13, 15, 5, 0, 8, 10, 2}, + RandomSeed: mustHexTo32BArray(t, "0x9a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e"), + DisputePeriod: 6, + Validators: []parachain.ValidatorID{ + mustHexTo32BArray(t, "0xa262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d"), + mustHexTo32BArray(t, "0x804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e"), + mustHexTo32BArray(t, "0x4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe72"), + mustHexTo32BArray(t, "0x74c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68"), + mustHexTo32BArray(t, "0xe61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c511"), + mustHexTo32BArray(t, "0x94ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050e"), + mustHexTo32BArray(t, "0xac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841"), + mustHexTo32BArray(t, "0xb61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12"), + mustHexTo32BArray(t, "0x382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c"), + mustHexTo32BArray(t, "0x0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547"), + mustHexTo32BArray(t, "0xcee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237"), + mustHexTo32BArray(t, "0xe2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53"), + mustHexTo32BArray(t, "0xce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016"), + mustHexTo32BArray(t, "0xae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848"), + mustHexTo32BArray(t, "0xa0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a"), + mustHexTo32BArray(t, "0x807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a"), + mustHexTo32BArray(t, "0x4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936"), + }, + DiscoveryKeys: []parachain.AuthorityDiscoveryID{ + mustHexTo32BArray(t, "0x407a89ac6943b9d2ef1ceb5f1299941758a6af5b8f79b89b90f95a3e38179341"), + mustHexTo32BArray(t, "0x307744a128c608be0dff2189557715b74734359974606d96dc4d256d61b1047d"), + mustHexTo32BArray(t, "0x74fff2667b4a2cc69198ec9d3bf41f4d001ab644b45feaf89a21ff7ef3bd2618"), + mustHexTo32BArray(t, "0x98ab99b4b982d6a1d983ab05ac530b373043e6b7a4a7e5a7dc7ca1942196ae6c"), + mustHexTo32BArray(t, "0x94f9e38609dd9972bfdbe4664f2063499f6233f895ee13b71793c926018a9428"), + mustHexTo32BArray(t, "0x4ce0e8ec374f50c27948b8880628918a41b56930f1af675a5b5099d23f326763"), + mustHexTo32BArray(t, "0x3a58b8f1f529e55fc3dac1dd81cb4547565c09f6e98d97243acb98bdda890028"), + mustHexTo32BArray(t, "0x982bcec62ad60cf9fd00e89b7e3589adb668fcbc467127537851b5a5f3dbbb16"), + mustHexTo32BArray(t, "0x0695b906f52a88f18bdecd811785b4299c51ebb2a2755f0b4c0d83fbef431861"), + mustHexTo32BArray(t, "0x0ec5e1d2d044023009c63659c65a79aaf07ecbf5b9887958243aa873a63e5a1b"), + mustHexTo32BArray(t, "0x52ef04ed449e4db577d98ad433b779c36f0d122df03e1cdc3e840a49016c5f16"), + mustHexTo32BArray(t, "0xc2d4b5973000d0b175631dde5d1657b3e34c2f75e8a6d5414013ce4036d83355"), + mustHexTo32BArray(t, "0xa6e01665b2d8490abf45551088021041dfb41772a9d596ed6e9f261ed1c8ae72"), + mustHexTo32BArray(t, "0xb436c143e295617afb60353a01f2941bd33370a662c99c040984e52a072b5f22"), + mustHexTo32BArray(t, "0x4c4c4b178f1a3d67e5f26d6b93b9a43937cd2d1d1cb2acc4650f504125df2e18"), + mustHexTo32BArray(t, "0xca17f0edc319c140113a44722f829aa1313da1b54298a10df49ad7d67d9de85f"), + mustHexTo32BArray(t, "0x5a6bf6911fc41d8981c7c28f87e8ed4416c65e15624f7b4e36c6a1a72c7a7819"), + }, + AssignmentKeys: []parachain.AssignmentID{ + mustHexTo32BArray(t, "0x6acc35b896fe346adeda25c4031cf6a81e58dca091164370859828cc4456901a"), + mustHexTo32BArray(t, "0x466627d554785807aaf50bfbdc9b8f729e8e20eb596ee5def5acd2acb72e405f"), + mustHexTo32BArray(t, "0xc05cab9e7773ffaf045407579f9c8e16d56f119117421cd18a250c2e37fcb53a"), + mustHexTo32BArray(t, "0xe2dca6ce9b3ebb40052c34392dc74d3cdd648399119fa470222a10956769d64f"), + mustHexTo32BArray(t, "0x7477459916ace4f77d97d6ab5e1a2f06092282c7f0a1332628c14896e8e9be62"), + mustHexTo32BArray(t, "0xc2574de3dc8feebfad1b3bee36a7bfe6c994e5d1459a5372ff447ac32dd46c11"), + mustHexTo32BArray(t, "0xb0a8ed99f1e7ab160e0ac2fcfeee0d92d807c8fb4c1678e37997715578926c5c"), + mustHexTo32BArray(t, "0x6c9bfa7c2e0f8e10a1a78bb982313c5c347a018cb3828886b99e109a8799d272"), + mustHexTo32BArray(t, "0xe6037f1fc5b19015b7089ecf90034349e3f5c37cb50dec5356743614f94f8c33"), + mustHexTo32BArray(t, "0x964b85f2b8e10e859e306d3670b8bdc0cea17b97dfd3edc8a9e1be1f127fee5b"), + mustHexTo32BArray(t, "0x44d421ae62038ba15a377cad85e4ecd3c2a63b54fdbb82c47fb3e9c026405226"), + mustHexTo32BArray(t, "0x48c51db949a58fd5f36a19888986275547b0c2fbb0b348ccb85dfc6c998dbe16"), + mustHexTo32BArray(t, "0x0ae9425710301a9241837d624438a5d82edbbd6bf2cdbcc2694ad7db31ef9921"), + mustHexTo32BArray(t, "0x9e47376e9af08b294901b879c7d658c41386453c6baa7c26560c5fd3b164e05d"), + mustHexTo32BArray(t, "0x8af1a51649d44d12dffc24337f0a5424b18db9604133eafcb2639ddcdc2a7f0f"), + mustHexTo32BArray(t, "0xae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022"), + mustHexTo32BArray(t, "0xeeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e6067"), + }, + ValidatorGroups: [][]parachain.ValidatorIndex{ + { + 0, 1, 2, 3, 4, 5, + }, + { + 6, 7, 8, 9, 10, 11, + }, + { + 12, 13, 14, 15, 16, + }, + }, + NCores: 3, + ZerothDelayTrancheWidth: 0, + RelayVRFModuloSamples: 1, + NDelayTranches: 40, + NoShowSlots: 2, + NeededApprovals: 2, + } + require.Equal(t, expected, response) +} + +func getParachainHostTrie(t *testing.T) *trie.Trie { + tt := trie.NewEmptyTrie() + + for _, s := range parachainTestData.Storage { + key := common.MustHexToBytes(s.Key) + value := common.MustHexToBytes(s.Value) + err := tt.Put(key, value) + require.NoError(t, err) + } + + return tt +} diff --git a/lib/runtime/wasmer/test_helpers.go b/lib/runtime/wasmer/test_helpers.go new file mode 100644 index 0000000000..7f862d4e0e --- /dev/null +++ b/lib/runtime/wasmer/test_helpers.go @@ -0,0 +1,90 @@ +// Copyright 2021 ChainSafe Systems (ON) +// SPDX-License-Identifier: LGPL-3.0-only + +package wasmer + +import ( + "context" + "testing" + + "github.com/ChainSafe/gossamer/internal/log" + "github.com/ChainSafe/gossamer/lib/common" + "github.com/ChainSafe/gossamer/lib/keystore" + "github.com/ChainSafe/gossamer/lib/runtime" + "github.com/ChainSafe/gossamer/lib/runtime/mocks" + "github.com/ChainSafe/gossamer/lib/runtime/storage" + "github.com/ChainSafe/gossamer/lib/trie" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" +) + +// DefaultTestLogLvl is the log level used for test runtime instances +var DefaultTestLogLvl = log.Info + +func mustHexTo64BArray(t *testing.T, inputHex string) (outputArray [64]byte) { + t.Helper() + copy(outputArray[:], common.MustHexToBytes(inputHex)) + return outputArray +} + +func mustHexTo32BArray(t *testing.T, inputHex string) (outputArray [32]byte) { + t.Helper() + copy(outputArray[:], common.MustHexToBytes(inputHex)) + return outputArray +} + +// NewTestInstance will create a new runtime instance using the given target runtime +func NewTestInstance(t *testing.T, targetRuntime string) *Instance { + t.Helper() + return NewTestInstanceWithTrie(t, targetRuntime, nil) +} + +// NewTestInstanceWithTrie returns an instance based on the target runtime string specified, +// which can be a file path or a constant from the constants defined in `lib/runtime/constants.go`. +// The instance uses the trie given as argument for its storage. +func NewTestInstanceWithTrie(t *testing.T, targetRuntime string, tt *trie.Trie) *Instance { + t.Helper() + + ctrl := gomock.NewController(t) + + cfg := setupConfig(t, ctrl, tt, DefaultTestLogLvl, common.NoNetworkRole, targetRuntime) + targetRuntime, err := runtime.GetRuntime(context.Background(), targetRuntime) + require.NoError(t, err) + + r, err := NewInstanceFromFile(targetRuntime, cfg) + require.NoError(t, err) + + return r +} + +func setupConfig(t *testing.T, ctrl *gomock.Controller, tt *trie.Trie, lvl log.Level, + role common.NetworkRole, targetRuntime string) Config { + t.Helper() + + s := storage.NewTrieState(tt) + + ns := runtime.NodeStorage{ + LocalStorage: runtime.NewInMemoryDB(t), + PersistentStorage: runtime.NewInMemoryDB(t), // we're using a local storage here since this is a test runtime + BaseDB: runtime.NewInMemoryDB(t), // we're using a local storage here since this is a test runtime + } + + version := (*runtime.Version)(nil) + if targetRuntime == runtime.HOST_API_TEST_RUNTIME { + // Force state version to 0 since the host api test runtime + // does not implement the Core_version call so we cannot get the + // state version from it. + version = &runtime.Version{} + } + + return Config{ + Storage: s, + Keystore: keystore.NewGlobalKeystore(), + LogLvl: lvl, + NodeStorage: ns, + Network: new(runtime.TestRuntimeNetwork), + Transaction: mocks.NewMockTransactionState(ctrl), + Role: role, + testVersion: version, + } +} diff --git a/lib/runtime/wasmer/testdata/parachain.yaml b/lib/runtime/wasmer/testdata/parachain.yaml new file mode 100644 index 0000000000..440df4c7e7 --- /dev/null +++ b/lib/runtime/wasmer/testdata/parachain.yaml @@ -0,0 +1,63 @@ +# taken from https://polkadot.js.org/apps/#/chainstate (westend) +# at: 0x03458e146407a2ad41a87b18298540cad7d48f931f4815ca1fbef281e5943ef5 + +storage: +# parasShared.activeValidatorKeys + - key: "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e" + value: "0x44a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e36858936" +# system.number + - key: "0x26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac" + value: "0x9652f300" +# paraScheduler.validatorGroups + - key: "0x94eadf0156a8ad5156507773d0471e4a16973e1142f5bd30d9464076794007db" + value: "0x0c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000" +# paraScheduler.sessionStartBlock + - key: "0x94eadf0156a8ad5156507773d0471e4a9ce0310edffce7a01a96c2039f92dd10" + value: "0xac51f300" +# configuration.activeConfig + - key: "0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385" + value: "0x00005000005000000a00000000c8000000c800000a0000000a000000c80000006400000000000000000000000000500000c800000700e8764817020040010a0000000000000000c0220fca950300000000000000000000c0220fca9503000000000000000000e8030000009001000a0000000000000000900100008070000000000000000000000a000000050000000500000001000000010500000001c8000000060000005802000002000000280000000000000002000000010000000700c817a8040200400101020000000f000000" +# paraScheduler.availabilityCores + - key: "0x94eadf0156a8ad5156507773d0471e4ab8ebad86f546c7e0b135a4212aace339" + value: "0x0c010101010101" +# paras.parachains + - key: "0xcd710b30bd2eab0352ddcc26417aa1940b76934f4cc08dee01012d059e1b83ee" + value: "0x0ce8030000e9030000ea030000" +# paraInclusion.pendingAvailability[paraId=1000] + - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b6ff6f7d467b87a9e8030000" + value: "0x0000000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337440000004400f0019552f3009652f30002000000" +# paraInclusion.pendingAvailabilityCommitments[paraId=1000] + - key: "0x196e027349017067f9eb56e2c4d9ded50433e4ed72dccf0edcf58c3192f16e4bb6ff6f7d467b87a9e8030000" + value: "0x000000e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000009552f300" +# paraInclusion.pendingAvailability[paraId=1001] + - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865adc7217647a32b0be9030000" + value: "0x010000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e6744000000443f00009552f3009652f30000000000" +# paraInclusion.pendingAvailability[paraId=1002] + - key: "0x196e027349017067f9eb56e2c4d9ded5a2ee677da3917cc29ee3b29c9f94c865b2b032492225337bea030000" + value: "0x020000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc529964400000044c00f009552f3009652f30001000000" +# parasShared.currentSessionIndex + - key: "0xb341e3a63e58a188839b242d17f8c9f8b5cab3380174032968897a4c3ce57c0a" + value: "0xf36a0000" +# paraSessionInfo.sessions[Id=27379] + - key: "0x4da2c41eaffa8e1a791c5d65beeefd1f028685274e698e781f7f2766cba0cc83f36a0000" + value: "0x44070000000c0000000e000000010000000400000010000000030000000b00000009000000060000000d0000000f0000000500000000000000080000000a000000020000009a14667dcf973e46392904593e8caf2fb7a57904edbadf1547531657e7a56b5e0600000044a262f83b46310770ae8d092147176b8b25e8855bcfbbe701d346b10db0c5385d804b9df571e2b744d65eca2d4c59eb8e4345286c00389d97bfc1d8d13aa6e57e4eb63e4aad805c06dc924e2f19b1dde7faf507e5bb3c1838d6a3cfc10e84fe7274c337d57035cd6b7718e92a0d8ea6ef710da8ab1215a057c40c4ef792155a68e61d138eebd2069f1a76b3570f9de6a4b196289b198e33e6f0b59cef8837c51194ef34321ca5d37a6e8953183406b76f8ebf6a4be5eefc3997d022ac6e0a050eac837e8ca589521a83e7d9a7b307d1c41a5d9b940422488236f99646d21f3841b61cb85f7cf7616f9ef8f95010a51a68a4eae8afcdff715cc6a8d43da4a32a12382f17dae6b13a8ce5a7cc805056d9b592d918c8593f077db28cb14cf08a760c0825ba7677597ec9453ab5dbaa9e68bf89dc36694cb6e74cbd5a9a74b167e547cee3f65d78a239d7d199b100295e7a2d852ae898a6b81fd867b3471f25be7237e2ac8f039eb02370a9577e49ffc6032e6b5bf5ff77783bdc676d1432d714fd53ce35fa64fe7a5a6fc456ed2830e64d5d1a5dba26e7a57ab458f8cedf1ec77016ae40e895f46c8bfb3df63c119047d7faf21c3fe3e7a91994a3f00da6fa80f848a0e038975cff34d01c62960828c23ec10a305fe9f5c3589c2ae40f51963e380a807fa54347a8957ff5ef6c28e2403c83947e5fad4aa805c914df0645a07aab5a4c8e878d7f558ce5086cc37ca0d5964bed54ddd6b15a6663a95fe42e3685893644407a89ac6943b9d2ef1ceb5f1299941758a6af5b8f79b89b90f95a3e38179341307744a128c608be0dff2189557715b74734359974606d96dc4d256d61b1047d74fff2667b4a2cc69198ec9d3bf41f4d001ab644b45feaf89a21ff7ef3bd261898ab99b4b982d6a1d983ab05ac530b373043e6b7a4a7e5a7dc7ca1942196ae6c94f9e38609dd9972bfdbe4664f2063499f6233f895ee13b71793c926018a94284ce0e8ec374f50c27948b8880628918a41b56930f1af675a5b5099d23f3267633a58b8f1f529e55fc3dac1dd81cb4547565c09f6e98d97243acb98bdda890028982bcec62ad60cf9fd00e89b7e3589adb668fcbc467127537851b5a5f3dbbb160695b906f52a88f18bdecd811785b4299c51ebb2a2755f0b4c0d83fbef4318610ec5e1d2d044023009c63659c65a79aaf07ecbf5b9887958243aa873a63e5a1b52ef04ed449e4db577d98ad433b779c36f0d122df03e1cdc3e840a49016c5f16c2d4b5973000d0b175631dde5d1657b3e34c2f75e8a6d5414013ce4036d83355a6e01665b2d8490abf45551088021041dfb41772a9d596ed6e9f261ed1c8ae72b436c143e295617afb60353a01f2941bd33370a662c99c040984e52a072b5f224c4c4b178f1a3d67e5f26d6b93b9a43937cd2d1d1cb2acc4650f504125df2e18ca17f0edc319c140113a44722f829aa1313da1b54298a10df49ad7d67d9de85f5a6bf6911fc41d8981c7c28f87e8ed4416c65e15624f7b4e36c6a1a72c7a7819446acc35b896fe346adeda25c4031cf6a81e58dca091164370859828cc4456901a466627d554785807aaf50bfbdc9b8f729e8e20eb596ee5def5acd2acb72e405fc05cab9e7773ffaf045407579f9c8e16d56f119117421cd18a250c2e37fcb53ae2dca6ce9b3ebb40052c34392dc74d3cdd648399119fa470222a10956769d64f7477459916ace4f77d97d6ab5e1a2f06092282c7f0a1332628c14896e8e9be62c2574de3dc8feebfad1b3bee36a7bfe6c994e5d1459a5372ff447ac32dd46c11b0a8ed99f1e7ab160e0ac2fcfeee0d92d807c8fb4c1678e37997715578926c5c6c9bfa7c2e0f8e10a1a78bb982313c5c347a018cb3828886b99e109a8799d272e6037f1fc5b19015b7089ecf90034349e3f5c37cb50dec5356743614f94f8c33964b85f2b8e10e859e306d3670b8bdc0cea17b97dfd3edc8a9e1be1f127fee5b44d421ae62038ba15a377cad85e4ecd3c2a63b54fdbb82c47fb3e9c02640522648c51db949a58fd5f36a19888986275547b0c2fbb0b348ccb85dfc6c998dbe160ae9425710301a9241837d624438a5d82edbbd6bf2cdbcc2694ad7db31ef99219e47376e9af08b294901b879c7d658c41386453c6baa7c26560c5fd3b164e05d8af1a51649d44d12dffc24337f0a5424b18db9604133eafcb2639ddcdc2a7f0fae7a30d143fd125490434ca7325025a2338d0b8bb28dcd9373dfd83756191022eeba7c46f5fa1ea21e736d9ebd7a171fb2afe0a4f828a222ea0605a4ad0e60670c1800000000010000000200000003000000040000000500000018060000000700000008000000090000000a0000000b000000140c0000000d0000000e0000000f00000010000000030000000000000001000000280000000200000002000000" +# system.events + - key: "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7" + value: "0x1400000000000000e249433d551702000000010000002c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e00000000020000000000010000002c00e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d01000000000000000000010000002c00ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000000001000000000007559ff8970d26023b00020000" +# system.eventCount + - key: "0x26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850" + value: "0x05000000" +# hrmp.hrmpIngressChannelsIndex[paraId=1000] + - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000" + value: "0x08d007000049080000" +# hrmp.hrmpIngressChannelsIndex[paraId=1001] + - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000" + value: "0x08d007000049080000" +# hrmp.hrmpIngressChannelsIndex[paraId=1002] + - key: "0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948b6ff6f7d467b87a9e8030000" + value: "0x08d007000049080000" +expected: + availabilityCores: "0x0c0001e8030000009652f3009c52f30001e803000000440000000200000058b29da15fc66c19ef0ad4e66e95c8e42718d2455001ec6876f4173489a705fbe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b51453370001e9030000009652f3009c52f30001e90300000044000000000000000571a387d344bef8a77d3a99895958644dee97345861f7747b1cb8186a14089ee9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e670001ea030000009652f3009c52f30001ea0300000044000000010000009b716202cd9fabb93b278a41d9344faecb1300241d255d1de0675a42ebff6b6eea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc52996" + candidateEvents: "0x0c00e8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b514533734cd6976981877d40277ad627ec04b2fc4ba04f558d9e4b41d911a6f41610350e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000000200000000e9030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083c2d011b32106cc9030d8d22770c632b611c613e4ed351c149ba59e7d61cd6d0055e865b40a8dcf60422987c985c6022231106e0a4556c0270ffcb99e656dd7be25c5eb2a93cbada931620b5bceebe187bf77aa6dde41a6cbb09f0cbbf291faa5a33ec5ebf7fa730c95c84650a68d432ed53fc77b6d8bff3ce50f19d48317c30aca695f1737408d7dd47052c3b3016128ed3d6ac5b3b46be0cc9537919b9f594fa704bc2e304492c6e835db7f2bfe17d5da9102834f5be31865468357055164895cd3b32bdb452067ab9b91421ace94cd58599e42f287eb47663289375824a5f02dbd44d6cb9847e46210a665f28147957290a6d3cf758aa31af9d3ba54c01e67514f16481063738cae77af97e154a475018c89ac13ca21452572447ae3bea823e90259b97f6f68683641a4b1046440cedddbc2054805e95504e9813b7c352d68ce57ba9357001fb3b6742be5e417621c0fd5f742e9f1d142518605af00a244dc61ebd42d63e07666532e9e2ab468d56fccb902fa801513a4dddc19d9e4b1edaae85ef1d1758908066175726120f4635e080000000005617572610101ba71303b6313ffc193e07bd26aeed8754fd02e86d3fd314074dcb2393a2eae08d32f5ec38737493bbcb09abeb020eb7eadbef00102bd3802b0545d5bca7e6a8d010000000000000000ea030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e14508106083004c606d630584c98d4165a9dfbf9f2a60890f303686b7e5fcb428773a88ad6f08db9fcb4c0e4c4883dee0f9281e1de995b0575ef784a9fda4d58c55cdcc326dc8c838bfbf21eaca646aa5eef8e34d5776310f51b2e1eb1d6b1d86f05739c208efde19b42cad56b4c1e50a381a480ea65aea7c0b0e9f254174bec6f36ebccb70a69233b495ea5a88376ca43e908bbf8b921398dc491d94d1f8ac6f4f4ca6f02d4d71b3b7a81d9a11d797928c060d8c992f908005c1f1460d3ad4fa284dae0b8d9a32fdfc8217ce1456dc87c592ae674614dfadbd1098a3a2889e9c2ada44dac40d6b0154b039a3c7dfead7371f3f1d406f3a7a52307e99588a5d1743cfc5299687f044d87495f20844ff334fe3ff1fb62568167d343d8f39dba5673d75452c06e9023c1bee939fc42a875b2921ecda1e413a5bad4b53bfa7aa314ba9aaf7f66d272cfe563500c93f096e27f359c7834c3b56180169d6055dc7d002bbee58e5b300004a6bf77091facd6381ad90cc2dc3ddab148eede30441cf6767ba2b3ce03b8401a52fdaa208066175726120f4635e080000000005617572610101960963f3ebff0b6b57bf99454febef94f04726a2c94abd401c5d3b568ec3cc384b10dd3dd7d96d456df0b8ed5cc6bacab809e163f85ec0b96529a9f3fa28f5870200000001000000" + candidatePendingAvailability: "0xe8030000b5504a29f00279e92b26d78f1961fea0a0736cfe73c9095c30d3e145081060831aa591a0575f87105ee7feed9a16f697fe2c82ce6759c12c145d429000c20251a2777204e645e33cc3c33bfe795163156f1a8efc379437c040ed8b7184e49dd520d856b61211a44f787be0fa889e056c53ed71c1cb57076c011a5f5a06763293d91329423a01e48b3367edfddbcc708f66fdbc083f646e6407d6d0a685403c3b68aa60144a3d436c639747333586d4f2ca7b434e2cf34880d510be840133df593a63398c0efa2e9cd097176df66954fe7c38634aa7fc8d55e4756210b9c6b084d94221f82a5674177741aa1d30667e25217b14629aa48bf7f9676d19a90c8211cafdc44448ed62f5f67e5c340b420c51fe3bee7c1577f9fa0e819383b5145337000000e902d91574d9e4897d88a7fb40130cf6c7900b5cb7238036726cd6c07a2255c8ed1c32a018010915879f32707df4a034c9a329ca83a80fab304d1a860690def304379ac236284091930e2b657bf56c4353bdca877b2c8a6bc33ba1611a5d79b2858b00bc707f08066175726120f4635e08000000000561757261010172b799cfe3e2ba2bd80349c7c92d1d84ff01ad6b3d491ff523ee2759e81dc22d58a94cd968ed300dbbc725144a04fa3622a11b2614255b802261d03c53af6f8e000000009552f300" + diff --git a/lib/runtime/wazero/instance.go b/lib/runtime/wazero/instance.go index 9d329341ee..1b1c7254f6 100644 --- a/lib/runtime/wazero/instance.go +++ b/lib/runtime/wazero/instance.go @@ -16,6 +16,7 @@ import ( "github.com/ChainSafe/gossamer/lib/crypto" "github.com/ChainSafe/gossamer/lib/crypto/ed25519" "github.com/ChainSafe/gossamer/lib/keystore" + "github.com/ChainSafe/gossamer/lib/parachain" "github.com/ChainSafe/gossamer/lib/runtime" "github.com/ChainSafe/gossamer/lib/runtime/offchain" "github.com/ChainSafe/gossamer/lib/transaction" @@ -808,7 +809,175 @@ func (in *Instance) GrandpaSubmitReportEquivocationUnsignedExtrinsic( return nil } -func (*Instance) RandomSeed() { +// ParachainHostValidators returns the validator set at the current state. +// The specified validators are responsible for backing parachains for the current state. +func (in *Instance) ParachainHostValidators() ([]parachain.ValidatorID, error) { + encodedValidators, err := in.Exec(runtime.ParachainHostValidators, []byte{}) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + var validatorIDs []parachain.ValidatorID + err = scale.Unmarshal(encodedValidators, &validatorIDs) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return validatorIDs, nil +} + +// ParachainHostValidatorGroups returns the validator groups used during the current session. +// The validators in the groups are referred to by the validator set Id. +func (in *Instance) ParachainHostValidatorGroups() (*parachain.ValidatorGroups, error) { + encodedValidatorGroups, err := in.Exec(runtime.ParachainHostValidatorGroups, []byte{}) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + var validatorGroups parachain.ValidatorGroups + err = scale.Unmarshal(encodedValidatorGroups, &validatorGroups) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return &validatorGroups, nil +} + +// ParachainHostAvailabilityCores returns the availability cores for the current state. +func (in *Instance) ParachainHostAvailabilityCores() (*scale.VaryingDataTypeSlice, error) { + encodedAvailabilityCores, err := in.Exec(runtime.ParachainHostAvailabilityCores, []byte{}) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + availabilityCores, err := parachain.NewAvailabilityCores() + if err != nil { + return nil, fmt.Errorf("new availability cores: %w", err) + } + err = scale.Unmarshal(encodedAvailabilityCores, &availabilityCores) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return &availabilityCores, nil +} + +// ParachainHostCheckValidationOutputs checks the validation outputs of a candidate. +// Returns true if the candidate is valid. +func (in *Instance) ParachainHostCheckValidationOutputs( + parachainID parachain.ParaID, + outputs parachain.CandidateCommitments, +) (bool, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(parachainID) + if err != nil { + return false, fmt.Errorf("encode parachainID: %w", err) + } + err = encoder.Encode(outputs) + if err != nil { + return false, fmt.Errorf("encode outputs: %w", err) + } + + encodedPersistedValidationData, err := in.Exec(runtime.ParachainHostCheckValidationOutputs, buffer.Bytes()) + if err != nil { + return false, fmt.Errorf("exec: %w", err) + } + + var isValid bool + err = scale.Unmarshal(encodedPersistedValidationData, &isValid) + if err != nil { + return false, fmt.Errorf("unmarshalling: %w", err) + } + + return isValid, nil +} + +// ParachainHostSessionIndexForChild returns the session index that is expected at the child of a block. +func (in *Instance) ParachainHostSessionIndexForChild() (parachain.SessionIndex, error) { + encodedSessionIndex, err := in.Exec(runtime.ParachainHostSessionIndexForChild, []byte{}) + if err != nil { + return 0, fmt.Errorf("exec: %w", err) + } + + var sessionIndex parachain.SessionIndex + err = scale.Unmarshal(encodedSessionIndex, &sessionIndex) + if err != nil { + return 0, fmt.Errorf("unmarshalling: %w", err) + } + + return sessionIndex, nil +} + +// ParachainHostCandidatePendingAvailability returns the receipt of a candidate pending availability +// for any parachain assigned to an occupied availability core. +func (in *Instance) ParachainHostCandidatePendingAvailability( + parachainID parachain.ParaID, +) (*parachain.CommittedCandidateReceipt, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(parachainID) + if err != nil { + return nil, fmt.Errorf("encode parachainID: %w", err) + } + + encodedCandidateReceipt, err := in.Exec(runtime.ParachainHostCandidatePendingAvailability, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + var candidateReceipt *parachain.CommittedCandidateReceipt + err = scale.Unmarshal(encodedCandidateReceipt, &candidateReceipt) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return candidateReceipt, nil +} + +// ParachainHostCandidateEvents returns an array of candidate events that occurred within the latest state. +func (in *Instance) ParachainHostCandidateEvents() (*scale.VaryingDataTypeSlice, error) { + encodedCandidateEvents, err := in.Exec(runtime.ParachainHostCandidateEvents, []byte{}) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + candidateEvents, err := parachain.NewCandidateEvents() + if err != nil { + return nil, fmt.Errorf("create new candidate events: %w", err) + } + err = scale.Unmarshal(encodedCandidateEvents, &candidateEvents) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return &candidateEvents, nil +} + +// ParachainHostSessionInfo returns the session info of the given session, if available. +func (in *Instance) ParachainHostSessionInfo(sessionIndex parachain.SessionIndex) (*parachain.SessionInfo, error) { + buffer := bytes.NewBuffer(nil) + encoder := scale.NewEncoder(buffer) + err := encoder.Encode(sessionIndex) + if err != nil { + return nil, fmt.Errorf("encode sessionIndex: %w", err) + } + + encodedSessionInfo, err := in.Exec(runtime.ParachainHostSessionInfo, buffer.Bytes()) + if err != nil { + return nil, fmt.Errorf("exec: %w", err) + } + + var sessionInfo *parachain.SessionInfo + err = scale.Unmarshal(encodedSessionInfo, &sessionInfo) + if err != nil { + return nil, fmt.Errorf("unmarshalling: %w", err) + } + + return sessionInfo, nil +} + +func (in *Instance) RandomSeed() { panic("unimplemented") } func (*Instance) OffchainWorker() {