Skip to content

Commit c9a9654

Browse files
authored
feat: parachain compatibility (#412)
* modules * `aura-ext` * block executor * `parachain-system` * api * `collect_collation_info` * `validate_block` * internal trie representation for `io.Storage` and `io.TransactionBroker`
1 parent 095050b commit c9a9654

File tree

175 files changed

+7388
-267
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

175 files changed

+7388
-267
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ start-network:
175175
cd ../../../..; \
176176
WASMTIME_BACKTRACE_DETAILS=1 RUST_LOG=runtime=trace ./target/release/node-template --dev --execution=wasm
177177

178+
parachain-build:
179+
cp $(BUILD_PATH)/parachain.wasm polkadot-sdk/cumulus/polkadot-parachain/src/chain_spec/runtime.wasm; \
180+
cd polkadot-sdk; \
181+
cargo build --release -p polkadot-parachain-bin
182+
178183
# gossamer node configuration
179184
CHAIN_SPEC_PLAIN = ../testdata/chain-spec/plain.json
180185
CHAIN_SPEC_UPDATED = ../testdata/chain-spec/plain-updated.json

api/benchmarking/module.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ type Module struct {
2828
logger log.RuntimeLogger
2929
}
3030

31-
func New(systemIndex sc.U8, modules []primitives.Module, decoder types.RuntimeDecoder, logger log.RuntimeLogger) Module {
31+
func New(systemIndex sc.U8, modules []primitives.Module, decoder types.RuntimeDecoder, storage io.Storage, transactionBroker io.TransactionBroker, logger log.RuntimeLogger) Module {
3232
systemModule := primitives.MustGetModule(systemIndex, modules).(system.Module)
3333

3434
return Module{
3535
modules: modules,
3636
systemModule: systemModule,
3737
decoder: decoder,
38-
transactional: support.NewTransactional[primitives.PostDispatchInfo](logger),
38+
transactional: support.NewTransactional[primitives.PostDispatchInfo](storage, transactionBroker, logger),
3939
memUtils: utils.NewMemoryTranslator(),
4040
hashing: io.NewHashing(),
4141
logger: logger,

api/collect_collation_info/module.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package collect_collation_info
2+
3+
import (
4+
"bytes"
5+
6+
sc "github.com/LimeChain/goscale"
7+
"github.com/LimeChain/gosemble/constants/metadata"
8+
"github.com/LimeChain/gosemble/frame/parachain_system"
9+
"github.com/LimeChain/gosemble/primitives/hashing"
10+
"github.com/LimeChain/gosemble/primitives/log"
11+
primitives "github.com/LimeChain/gosemble/primitives/types"
12+
"github.com/LimeChain/gosemble/utils"
13+
)
14+
15+
const (
16+
ApiModuleName = "CollectCollationInfo"
17+
apiVersion = 2
18+
)
19+
20+
// Module implements the CollectCollationInfo Runtime API definition.
21+
//
22+
// For more information about API definition, see:
23+
// https://github.com/paritytech/polkadot-sdk/blob/master/cumulus/primitives/core/src/lib.rs#L378
24+
type Module struct {
25+
parachainSystem parachain_system.Module
26+
memUtils utils.WasmMemoryTranslator
27+
logger log.RuntimeLogger
28+
}
29+
30+
func New(parachainSystem parachain_system.Module, logger log.RuntimeLogger) Module {
31+
return Module{
32+
memUtils: utils.NewMemoryTranslator(),
33+
parachainSystem: parachainSystem,
34+
logger: logger,
35+
}
36+
}
37+
38+
// Name returns the name of the api module
39+
func (m Module) Name() string {
40+
return ApiModuleName
41+
}
42+
43+
// Item returns the first 8 bytes of the Blake2b hash of the name and version of the api module.
44+
func (m Module) Item() primitives.ApiItem {
45+
hash := hashing.MustBlake2b8([]byte(ApiModuleName))
46+
return primitives.NewApiItem(hash, apiVersion)
47+
}
48+
49+
// CollectCollationInfo returns the collation information by the header of a built block.
50+
// It takes two arguments:
51+
// - dataPtr: Pointer to the data in the Wasm memory.
52+
// - dataLen: Length of the data.
53+
// which represent the SCALE-encoded block header.
54+
// Returns a pointer-size of the SCALE-encoded collation information.
55+
func (m Module) CollectCollationInfo(dataPtr int32, dataLen int32) int64 {
56+
b := m.memUtils.GetWasmMemorySlice(dataPtr, dataLen)
57+
buffer := bytes.NewBuffer(b)
58+
59+
header, err := primitives.DecodeHeader(buffer)
60+
if err != nil {
61+
m.logger.Critical(err.Error())
62+
}
63+
64+
collationInfo, err := m.parachainSystem.CollectCollationInfo(header)
65+
if err != nil {
66+
m.logger.Critical(err.Error())
67+
}
68+
69+
return m.memUtils.BytesToOffsetAndSize(collationInfo.Bytes())
70+
}
71+
72+
func (m Module) Metadata() primitives.RuntimeApiMetadata {
73+
methods := sc.Sequence[primitives.RuntimeApiMethodMetadata]{
74+
primitives.RuntimeApiMethodMetadata{
75+
Name: "collect_collation_info",
76+
Inputs: sc.Sequence[primitives.RuntimeApiMethodParamMetadata]{
77+
primitives.RuntimeApiMethodParamMetadata{
78+
Name: "header",
79+
Type: sc.ToCompact(metadata.Header),
80+
},
81+
},
82+
Output: sc.ToCompact(metadata.TypesParachainValidationResult),
83+
Docs: sc.Sequence[sc.Str]{"Returns the collation information by the block header."},
84+
},
85+
}
86+
87+
return primitives.RuntimeApiMetadata{
88+
Name: ApiModuleName,
89+
Methods: methods,
90+
Docs: sc.Sequence[sc.Str]{" The collect collation info api."},
91+
}
92+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package collect_collation_info
2+
3+
import (
4+
"errors"
5+
"io"
6+
"testing"
7+
8+
"github.com/ChainSafe/gossamer/lib/common"
9+
sc "github.com/LimeChain/goscale"
10+
"github.com/LimeChain/gosemble/constants/metadata"
11+
"github.com/LimeChain/gosemble/mocks"
12+
"github.com/LimeChain/gosemble/primitives/log"
13+
"github.com/LimeChain/gosemble/primitives/parachain"
14+
primitives "github.com/LimeChain/gosemble/primitives/types"
15+
"github.com/stretchr/testify/assert"
16+
)
17+
18+
var (
19+
dataPtr = int32(0)
20+
dataLen = int32(1)
21+
ptrAndSize = int64(6)
22+
23+
parentHash = common.MustHexToHash("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355c").ToBytes()
24+
stateRoot = common.MustHexToHash("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355b").ToBytes()
25+
extrinsicsRoot = common.MustHexToHash("0x3aa96b0149b6ca3688878bdbd19464448624136398e3ce45b9e755d3ab61355a").ToBytes()
26+
header = primitives.Header{
27+
ParentHash: primitives.Blake2bHash{
28+
FixedSequence: sc.BytesToFixedSequenceU8(parentHash)},
29+
Number: 5,
30+
StateRoot: primitives.H256{FixedSequence: sc.BytesToFixedSequenceU8(stateRoot)},
31+
ExtrinsicsRoot: primitives.H256{FixedSequence: sc.BytesToFixedSequenceU8(extrinsicsRoot)},
32+
Digest: primitives.NewDigest(sc.Sequence[primitives.DigestItem]{}),
33+
}
34+
collationInfo = parachain.CollationInfo{
35+
UpwardMessages: sc.Sequence[parachain.UpwardMessage]{},
36+
HorizontalMessages: sc.Sequence[parachain.OutboundHrmpMessage]{},
37+
ValidationCode: sc.Option[sc.Sequence[sc.U8]]{},
38+
ProcessedDownwardMessages: 0,
39+
HrmpWatermark: 0,
40+
HeadData: sc.Sequence[sc.U8]{},
41+
}
42+
errPanic = errors.New("panic")
43+
)
44+
45+
var (
46+
mockParachainSystemModule *mocks.ParachainSystemModule
47+
mockMemoryUtils *mocks.MemoryTranslator
48+
)
49+
50+
func Test_Module_Name(t *testing.T) {
51+
target := setup()
52+
53+
result := target.Name()
54+
55+
assert.Equal(t, ApiModuleName, result)
56+
}
57+
58+
func Test_Module_Item(t *testing.T) {
59+
target := setup()
60+
61+
hexName := common.MustBlake2b8([]byte(ApiModuleName))
62+
expect := primitives.NewApiItem(hexName, apiVersion)
63+
64+
result := target.Item()
65+
66+
assert.Equal(t, expect, result)
67+
}
68+
69+
func Test_Module_CollectCollationInfo(t *testing.T) {
70+
target := setup()
71+
72+
mockMemoryUtils.On("GetWasmMemorySlice", dataPtr, dataLen).Return(header.Bytes())
73+
mockParachainSystemModule.On("CollectCollationInfo", header).Return(collationInfo, nil)
74+
mockMemoryUtils.On("BytesToOffsetAndSize", collationInfo.Bytes()).Return(ptrAndSize)
75+
76+
result := target.CollectCollationInfo(dataPtr, dataLen)
77+
78+
assert.Equal(t, ptrAndSize, result)
79+
mockMemoryUtils.AssertCalled(t, "GetWasmMemorySlice", dataPtr, dataLen)
80+
mockParachainSystemModule.AssertCalled(t, "CollectCollationInfo", header)
81+
mockMemoryUtils.AssertCalled(t, "BytesToOffsetAndSize", collationInfo.Bytes())
82+
}
83+
84+
func Test_Module_CollectCollationInfo_Header_Panics(t *testing.T) {
85+
target := setup()
86+
87+
mockMemoryUtils.On("GetWasmMemorySlice", dataPtr, dataLen).Return([]byte{})
88+
89+
assert.PanicsWithValue(t,
90+
io.EOF.Error(),
91+
func() { target.CollectCollationInfo(dataPtr, dataLen) },
92+
)
93+
94+
mockMemoryUtils.AssertCalled(t, "GetWasmMemorySlice", dataPtr, dataLen)
95+
}
96+
97+
func Test_Module_CollectCollationInfo_Panics(t *testing.T) {
98+
target := setup()
99+
100+
expectedErr := errors.New("panic")
101+
102+
mockMemoryUtils.On("GetWasmMemorySlice", dataPtr, dataLen).Return(header.Bytes())
103+
mockParachainSystemModule.On("CollectCollationInfo", header).Return(collationInfo, expectedErr)
104+
105+
assert.PanicsWithValue(t,
106+
errPanic.Error(),
107+
func() { target.CollectCollationInfo(dataPtr, dataLen) },
108+
)
109+
110+
mockMemoryUtils.AssertCalled(t, "GetWasmMemorySlice", dataPtr, dataLen)
111+
mockParachainSystemModule.On("CollectCollationInfo", header).Return(collationInfo, expectedErr)
112+
}
113+
114+
func Test_Module_Metadata(t *testing.T) {
115+
target := setup()
116+
117+
expect := primitives.RuntimeApiMetadata{
118+
Name: ApiModuleName,
119+
Methods: sc.Sequence[primitives.RuntimeApiMethodMetadata]{
120+
primitives.RuntimeApiMethodMetadata{
121+
Name: "collect_collation_info",
122+
Inputs: sc.Sequence[primitives.RuntimeApiMethodParamMetadata]{
123+
primitives.RuntimeApiMethodParamMetadata{
124+
Name: "header",
125+
Type: sc.ToCompact(metadata.Header),
126+
},
127+
},
128+
Output: sc.ToCompact(metadata.TypesParachainValidationResult),
129+
Docs: sc.Sequence[sc.Str]{"Returns the collation information by the block header."},
130+
},
131+
},
132+
Docs: sc.Sequence[sc.Str]{" The collect collation info api."},
133+
}
134+
135+
assert.Equal(t, expect, target.Metadata())
136+
}
137+
138+
func setup() Module {
139+
mockParachainSystemModule = new(mocks.ParachainSystemModule)
140+
mockMemoryUtils = new(mocks.MemoryTranslator)
141+
142+
target := New(mockParachainSystemModule, log.NewLogger())
143+
target.memUtils = mockMemoryUtils
144+
145+
return target
146+
}

api/genesis_builder/module.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ func (m Module) CreateDefaultConfig() int64 {
6767
m.logger.Critical(err.Error())
6868
}
6969

70+
if len(gcJsonBytes) == 0 {
71+
continue
72+
}
73+
7074
// gcJsonBytes[1:len(gcJsonBytes)-1] trims first and last characters which represent start and end of the json
7175
// CreateDefaultConfig returns a valid json (e.g. {"system":{}}), and here we need it as a json field
7276
gcs = append(gcs, string(gcJsonBytes[1:len(gcJsonBytes)-1]))

api/genesis_builder/module_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ func Test_CreateDefaultConfig(t *testing.T) {
5656
mockMemoryUtils.AssertCalled(t, "BytesToOffsetAndSize", genesisSequence)
5757
}
5858

59+
func Test_CreateDefaultConfig_Empty(t *testing.T) {
60+
genesisSequence := sc.BytesToSequenceU8([]byte("{}"))
61+
setup()
62+
mockModule.On("CreateDefaultConfig").Return([]byte{}, nil)
63+
mockMemoryUtils.On("BytesToOffsetAndSize", genesisSequence.Bytes()).Return(int64(0))
64+
65+
target.CreateDefaultConfig()
66+
67+
mockModule.AssertCalled(t, "CreateDefaultConfig")
68+
mockMemoryUtils.AssertCalled(t, "BytesToOffsetAndSize", genesisSequence.Bytes())
69+
}
70+
5971
func Test_CreateDefaultConfig_Error(t *testing.T) {
6072
setup()
6173
mockModule.On("CreateDefaultConfig").Return(genesis, errors.New("err"))

api/metadata/module.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,24 @@ func (m Module) basicTypes() sc.Sequence[primitives.MetadataType] {
281281
primitives.NewMetadataTypeDefinitionComposite(sc.Sequence[primitives.MetadataTypeDefinitionField]{
282282
primitives.NewMetadataTypeDefinitionField(metadata.TypesFixedSequence32U8)})),
283283

284+
primitives.NewMetadataTypeWithParam(metadata.TypesOptionH256, "Option<H256>", sc.Sequence[sc.Str]{"Option"}, primitives.NewMetadataTypeDefinitionVariant(
285+
sc.Sequence[primitives.MetadataDefinitionVariant]{
286+
primitives.NewMetadataDefinitionVariant(
287+
"None",
288+
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
289+
optionNoneIdx,
290+
""),
291+
primitives.NewMetadataDefinitionVariant(
292+
"Some",
293+
sc.Sequence[primitives.MetadataTypeDefinitionField]{
294+
primitives.NewMetadataTypeDefinitionField(metadata.TypesH256),
295+
},
296+
optionSomeIdx,
297+
""),
298+
}),
299+
primitives.NewMetadataTypeParameter(metadata.TypesH256, "T"),
300+
),
301+
284302
primitives.NewMetadataType(
285303
metadata.TypesCompactU128,
286304
"compact U128",
@@ -861,6 +879,24 @@ func (m Module) basicTypes() sc.Sequence[primitives.MetadataType] {
861879
primitives.NewMetadataTypeParameter(metadata.TypesSequenceU8, "T"),
862880
),
863881

882+
primitives.NewMetadataTypeWithParam(metadata.TypesOptionU32, "Option<U32>", sc.Sequence[sc.Str]{"Option"}, primitives.NewMetadataTypeDefinitionVariant(
883+
sc.Sequence[primitives.MetadataDefinitionVariant]{
884+
primitives.NewMetadataDefinitionVariant(
885+
"None",
886+
sc.Sequence[primitives.MetadataTypeDefinitionField]{},
887+
optionNoneIdx,
888+
""),
889+
primitives.NewMetadataDefinitionVariant(
890+
"Some",
891+
sc.Sequence[primitives.MetadataTypeDefinitionField]{
892+
primitives.NewMetadataTypeDefinitionField(metadata.PrimitiveTypesU32),
893+
},
894+
optionSomeIdx,
895+
""),
896+
}),
897+
primitives.NewMetadataTypeParameter(metadata.PrimitiveTypesU32, "T"),
898+
),
899+
864900
primitives.NewMetadataType(metadata.TypesSequenceSequenceU8, "[][]byte", primitives.NewMetadataTypeDefinitionSequence(sc.ToCompact(metadata.TypesSequenceU8))),
865901

866902
primitives.NewMetadataType(
@@ -904,6 +940,31 @@ func (m Module) basicTypes() sc.Sequence[primitives.MetadataType] {
904940
},
905941
),
906942
),
943+
primitives.NewMetadataTypeWithPath(
944+
metadata.TypesParachainOutboundHrmpMessage,
945+
"parachain primitives outbound hrmp messages",
946+
sc.Sequence[sc.Str]{"parachain", "primitives", "OutboundHrmpMessages"},
947+
primitives.NewMetadataTypeDefinitionComposite(sc.Sequence[primitives.MetadataTypeDefinitionField]{
948+
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU32, "id", "Id"),
949+
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.TypesSequenceU8, "data", "Data"),
950+
}),
951+
),
952+
primitives.NewMetadataType(metadata.TypesParachainOutboundHrmpMessages,
953+
"[]OutboundHrmpMessage",
954+
primitives.NewMetadataTypeDefinitionSequence(sc.ToCompact(metadata.TypesParachainOutboundHrmpMessage)),
955+
),
956+
primitives.NewMetadataTypeWithPath(
957+
metadata.TypesParachainValidationResult,
958+
"parachain primitives validationResult", sc.Sequence[sc.Str]{"parachain", "primitives", "ValidationResult"},
959+
primitives.NewMetadataTypeDefinitionComposite(sc.Sequence[primitives.MetadataTypeDefinitionField]{
960+
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.TypesSequenceSequenceU8, "upward_messages", "UpdwardMessages"),
961+
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.TypesParachainOutboundHrmpMessages, "horizontal_messages", "HorizontalMessages"),
962+
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.TypesOptionSequenceU8, "validation_code", "ValidationCode"),
963+
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU32, "processed_downward_messages", "ProcessedDownwardMessages"),
964+
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.PrimitiveTypesU32, "hrmp_watermark", "HrmpWatermark"),
965+
primitives.NewMetadataTypeDefinitionFieldWithNames(metadata.TypesSequenceU8, "head_data", "HeadData"),
966+
}),
967+
),
907968

908969
// 161
909970
primitives.NewMetadataType(

0 commit comments

Comments
 (0)