Skip to content

Commit 933f7f8

Browse files
safrole traces: RAW kv state + bootstrap service implementation (#12)
1. safrole - traces: RAW kv state + state_snapshots: dev-friendly C1-C15 state To support JAM implementers to derive each others state roots, extending to service related storage keys, here we publish a keyvals state trace format with a full range of 0x00..00 to 0xFF..FF in `traces` while leaving developer-friendly `state_snapshots` that focus on the C1-C15. With both state dumps, we can have teams collaborate: * deriving the stateroot from key-value pair combinations (which match the blocks parent state root) in `traces` * making sure values in `traces` correspond to the JAM codec encoding of the data in `state_snapshots` 2. Implementation of bootstrap service code * `main.rs` contains an implementation of the above bootstrap service, which is included in the [genesis state](../../../traces/safrole/genesis.json) - The `refine` service expects a `codehash` (32 bytes) starting at `0xFEFF0004` - The `accumulate` does a `new` and then a `write` * `bootstrapblob.pvm` has the disassembleable code (see below `polkatool`) with "magic bytes" * `bootstrap.pvm` has the JAM-ready code blob (no magic bytes). We used `polkatool` to do this, with [PR #190](paritytech/polkavm#190) actually mapping `main.rs` into the above. See links: [Building JAM Services in Rust](https://forum.polkadot.network/t/building-jam-services-in-rust/10161) for background Our test does the following: * submits a few service code blobs (fib, trib, megatron) in 3 work packages using the bootstrap service "0" * for each work package, we retrieve the new service indexes left by the `write` after "rho" is cleared (the service has been accumulated) * our test then runs work packages through fib + trib. Our next goal is to do ordered accumulation with queues.
1 parent 36137aa commit 933f7f8

File tree

342 files changed

+24665
-4965
lines changed

Some content is hidden

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

342 files changed

+24665
-4965
lines changed

services/jam-duna/bootstrap/README.md

+66-34
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,75 @@
1212
5. Validators (who will author a block _soon_ in a smart implementation, or all validators in a _lazy_ implementation) then request the actual preimage from N6 with **[CE143: Preimage Request](https://github.com/zdave-parity/jam-np/blob/main/simple.md#ce-143-preimage-request)** with the Preimage Hash received previously and receive the preimage from N6, checking against the Hash, and if it matches, forms (42, 242 bytes of code hashing to the preimage `0x1234...4321`). This will be aggregated with other preimages and included in ${\bf E}_P$. Alice can check new blocks as they are proposed / finalized for inclusion of her preimage and/or look in storage $C(255, 42)$ for the newly created service.
1313
6. Alice's service is available for everyone to submit work packages against at the new serviceID (e.g. 42).
1414

15-
### Sketch of bootstrap service code
15+
### Implementation of bootstrap service code
1616

17-
This is a sketch of what the genesis bootstrap service described above. This has not been tested yet but we believe this can be executed against.
17+
* `main.rs` contains an implementation of the above bootstrap service, which is included in the [genesis state](../../../traces/safrole/genesis.json)
18+
- The `refine` service expects a `codehash` (32 bytes) starting at `0xFEFF0004`
19+
- The `accumulate` does a `new` and then a `write`
20+
* `bootstrapblob.pvm` has the disassembleable code (see below `polkatool`) with "magic bytes"
21+
* `bootstrap.pvm` has the JAM-ready code blob (no magic bytes). We used `polkatool` to do this, with [PR #190](https://github.com/paritytech/polkavm/pull/190) actually mapping `main.rs` into the above. See links: [Building JAM Services in Rust](https://forum.polkadot.network/t/building-jam-services-in-rust/10161) for background
1822

19-
Notes:
20-
* `refine` has `codehash` expecting 32 byte payload starting at `0xFEFF0004` because there is 4 bytes of 0 right before the payload ${\bf y}$
21-
* `accumulate` does a `new` and then a `write`
23+
24+
Our test does the following:
25+
* submits a few service code blobs (fib, trib, megatron) in 3 work packages using the bootstrap service "0"
26+
* for each work package, we retrieve the new service indexes left by the `write` after "rho" is cleared (the service has been accumulated)
27+
* our test then runs work packages through fib + trib. Our next goal is to do ordered accumulation with queues.
2228

2329

2430
```
25-
pub @refine:
26-
a10 = 0xFEFF0004 // preceded by $s$
27-
a11 = 32 // output is 32 bytes, containing the code hash eg 0x1234...4321
28-
trap
29-
30-
pub @accumulate:
31-
a7 = 0xFEFF0000 // input is the output of @refine
32-
a8 = 0 // Figure out sane values of this
33-
a9 = 0x2000
34-
a10 = 0x1000
35-
a11 = 0x3000
36-
a12 = 0x4000
37-
ecalli 9 // new will output a new service key to a7
38-
39-
// write storage key (0) with new service key value copied from a7 into 0xFEFE0004
40-
u32 [0xFEFE0000] = 0 // key
41-
u32 [0xFEFE0004] = a7 // value
42-
a7 = 0xFEFE0000 // key is 0
43-
a8 = 4 // key is 4 bytes
44-
a9 = 0xFEFE0004 // value is the new serviceID
45-
a10 = 4 // value is 4 bytes
46-
ecalli 3
47-
trap
48-
49-
pub @authorization:
50-
fallthrough
51-
52-
pub @on_transfer:
53-
fallthrough
31+
# cargo run -p polkatool disassemble ~/go/src/github.com/jam-duna/jamtestnet/services/jam-duna/bootstrap/bootstrapblob.pvm --show-raw-bytes
32+
warning: /root/go/src/github.com/colorfulnotion/polkavm/Cargo.toml: unused manifest key: workspace.lints.rust.unexpected_cfgs.check-cfg
33+
Finished dev [unoptimized + debuginfo] target(s) in 0.06s
34+
Running `target/debug/polkatool disassemble /root/go/src/github.com/jam-duna/jamtestnet/services/jam-duna/bootstrap/bootstrapblob.pvm --show-raw-bytes`
35+
// RO data = 0/0 bytes
36+
// RW data = 0/0 bytes
37+
// Stack size = 4096 bytes
38+
// Jump table entry point size = 0 bytes
39+
// RO data = []
40+
// RW data = []
41+
// Instructions = 34
42+
// Code size = 115 bytes
43+
44+
: @0
45+
0: 05 11 00 00 00 jump @4
46+
: @1
47+
5: 05 10 00 00 00 jump @5
48+
: @2
49+
10: 05 18 00 00 00 jump @6
50+
: @3
51+
15: 05 60 jump @7
52+
: @4 [export #0: 'is_authorized']
53+
17: 04 07 a0 = 0x0
54+
19: 13 00 ret
55+
: @5 [export #1: 'refine']
56+
21: 04 0a 04 00 ff fe a3 = 0xfeff0004
57+
27: 04 0b 20 a4 = 0x20
58+
30: 04 07 a0 = 0x0
59+
32: 13 00 ret
60+
: @6 [export #2: 'accumulate']
61+
34: 02 11 f8 sp = sp - 8
62+
37: 03 10 04 u32 [sp + 4] = ra
63+
40: 03 15 u32 [sp] = s0
64+
42: 04 05 00 00 ff fe s0 = 0xfeff0000
65+
48: 04 07 00 00 ff fe a0 = 0xfeff0000
66+
54: 04 08 ce 00 a1 = 0xce
67+
58: 04 09 00 20 a2 = 0x2000
68+
62: 04 0a 00 10 a3 = 0x1000
69+
66: 04 0b 00 30 a4 = 0x3000
70+
70: 04 0c 00 40 a5 = 0x4000
71+
74: 4e 09 ecalli 9 // 'new'
72+
76: 0d 05 u32 [s0 + 0] = 0
73+
78: 03 57 04 u32 [s0 + 4] = a0
74+
81: 04 09 04 00 ff fe a2 = 0xfeff0004
75+
87: 04 07 00 00 ff fe a0 = 0xfeff0000
76+
93: 04 08 04 a1 = 0x4
77+
96: 04 0a 04 a3 = 0x4
78+
99: 4e 03 ecalli 3 // 'write'
79+
101: 01 10 04 ra = u32 [sp + 4]
80+
104: 01 15 s0 = u32 [sp]
81+
106: 02 11 08 sp = sp + 0x8
82+
109: 13 00 ret
83+
: @7 [export #3: 'on_transfer']
84+
111: 04 07 a0 = 0x0
85+
113: 13 00 ret
5486
```
148 Bytes
Binary file not shown.
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RO data = 0/0 bytes
2+
// RW data = 0/0 bytes
3+
// Stack size = 4096 bytes
4+
// Jump table entry point size = 0 bytes
5+
// RO data = []
6+
// RW data = []
7+
// Instructions = 34
8+
// Code size = 115 bytes
9+
10+
: @0
11+
0: 05 11 00 00 00 jump @4
12+
: @1
13+
5: 05 10 00 00 00 jump @5
14+
: @2
15+
10: 05 18 00 00 00 jump @6
16+
: @3
17+
15: 05 60 jump @7
18+
: @4 [export #0: 'is_authorized']
19+
17: 04 07 a0 = 0x0
20+
19: 13 00 ret
21+
: @5 [export #1: 'refine']
22+
21: 04 0a 04 00 ff fe a3 = 0xfeff0004
23+
27: 04 0b 20 a4 = 0x20
24+
30: 04 07 a0 = 0x0
25+
32: 13 00 ret
26+
: @6 [export #2: 'accumulate']
27+
34: 02 11 f8 sp = sp - 8
28+
37: 03 10 04 u32 [sp + 4] = ra
29+
40: 03 15 u32 [sp] = s0
30+
42: 04 05 00 00 ff fe s0 = 0xfeff0000
31+
48: 04 07 00 00 ff fe a0 = 0xfeff0000
32+
54: 04 08 ce 00 a1 = 0xce
33+
58: 04 09 00 20 a2 = 0x2000
34+
62: 04 0a 00 10 a3 = 0x1000
35+
66: 04 0b 00 30 a4 = 0x3000
36+
70: 04 0c 00 40 a5 = 0x4000
37+
74: 4e 09 ecalli 9 // 'new'
38+
76: 0d 05 u32 [s0 + 0] = 0
39+
78: 03 57 04 u32 [s0 + 4] = a0
40+
81: 04 09 04 00 ff fe a2 = 0xfeff0004
41+
87: 04 07 00 00 ff fe a0 = 0xfeff0000
42+
93: 04 08 04 a1 = 0x4
43+
96: 04 0a 04 a3 = 0x4
44+
99: 4e 03 ecalli 3 // 'write'
45+
101: 01 10 04 ra = u32 [sp + 4]
46+
104: 01 15 s0 = u32 [sp]
47+
106: 02 11 08 sp = sp + 0x8
48+
109: 13 00 ret
49+
: @7 [export #3: 'on_transfer']
50+
111: 04 07 a0 = 0x0
51+
113: 13 00 ret
250 Bytes
Binary file not shown.

services/jam-duna/bootstrap/main.rs

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
extern crate alloc;
5+
6+
use alloc::vec::Vec;
7+
use simplealloc::SimpleAlloc;
8+
9+
#[global_allocator]
10+
static ALLOCATOR: SimpleAlloc<4096> = SimpleAlloc::new();
11+
12+
#[panic_handler]
13+
fn panic(_info: &core::panic::PanicInfo) -> ! {
14+
unsafe {
15+
core::arch::asm!("unimp", options(noreturn));
16+
}
17+
}
18+
19+
#[polkavm_derive::polkavm_import]
20+
extern "C" {
21+
#[polkavm_import(index = 0)]
22+
pub fn gas() -> i64;
23+
#[polkavm_import(index = 1)]
24+
pub fn lookup(service: u32, hash_ptr: *const u8, out: *mut u8, out_len: u32) -> u32;
25+
#[polkavm_import(index = 2)]
26+
pub fn read(service: u32, key_ptr: *const u8, key_len: u32, out: *mut u8, out_len: u32) -> u32;
27+
28+
29+
// #[polkavm_import(index = 3)]
30+
// pub fn write(key_ptr: *const u8, key_len: u32, value: *const u8, value_len: u32) -> u32;
31+
32+
#[polkavm_import(index = 3)]
33+
pub fn write(ko: u32, kz: u32, bo: u32, bz: u32) -> u32;
34+
35+
36+
#[polkavm_import(index = 4)]
37+
pub fn info(service: u32, out: *mut u8) -> u32;
38+
#[polkavm_import(index = 5)]
39+
pub fn empower(m: u32, a: u32, v: u32, o: u32, n: u32) -> u32;
40+
#[polkavm_import(index = 6)]
41+
pub fn assign(c: u32, out: *mut u8) -> u32;
42+
#[polkavm_import(index = 7)]
43+
pub fn designate(out: *mut u8) -> u32;
44+
#[polkavm_import(index = 8)]
45+
pub fn checkpoint() -> u64;
46+
47+
// #[polkavm_import(index = 9)]
48+
// pub fn new(service: u32, hash_ptr: *const u8, out: *mut u8, out_len: u32) -> u32;
49+
50+
#[polkavm_import(index = 9)]
51+
pub fn new(o: u32, l: u32, gl: u32, gh: u32, ml: u32, mh: u32) -> u32;
52+
53+
54+
55+
#[polkavm_import(index = 10)]
56+
pub fn upgrade(out: *const u8, g: u64, m: u64) -> u32;
57+
#[polkavm_import(index = 11)]
58+
pub fn transfer(d: u32, a: u64, g: u64, out: *mut u8) -> u32;
59+
#[polkavm_import(index = 12)]
60+
pub fn quit(d: u32, a: u64, g: u64, out: *mut u8) -> u32;
61+
#[polkavm_import(index = 13)]
62+
pub fn solicit(hash_ptr: *const u8, z: u32) -> u32;
63+
#[polkavm_import(index = 14)]
64+
pub fn forget(hash_ptr: *const u8, z: u32) -> u32;
65+
#[polkavm_import(index = 15)]
66+
pub fn historical_lookup(service: u32, hash_ptr: *const u8, out: *mut u8, out_len: u32) -> u32;
67+
#[polkavm_import(index = 16)]
68+
pub fn import(import_index: u32, out: *mut u8, out_len: u32) -> u32;
69+
#[polkavm_import(index = 17)]
70+
pub fn export(out: *const u8, out_len: u32) -> u32;
71+
#[polkavm_import(index = 18)]
72+
pub fn machine(out: *const u8, out_len: u32) -> u32;
73+
#[polkavm_import(index = 19)]
74+
pub fn peek(out: *const u8, out_len: u32, i: u32) -> u32;
75+
#[polkavm_import(index = 20)]
76+
pub fn poke(n: u32, a: u32, b: u32, l: u32) -> u32;
77+
#[polkavm_import(index = 21)]
78+
pub fn invoke(n: u32, out: *mut u8) -> u32;
79+
#[polkavm_import(index = 22)]
80+
pub fn expunge(n: u32) -> u32;
81+
#[polkavm_import(index = 99)]
82+
pub fn blake2b(data: *const u8, data_len: u32, hash_ptr: *mut u8) -> u32;
83+
#[polkavm_import(index = 100)]
84+
pub fn blake2s(data: *const u8, data_len: u32, hash_ptr: *mut u8) -> u32;
85+
#[polkavm_import(index = 101)]
86+
pub fn ecrecover(h: *const u8, v: *const u8, r: *const u8, s: *const u8, out: *mut u8) -> u32;
87+
#[polkavm_import(index = 102)]
88+
pub fn sha2_256(data: *const u8, data_len: u32, hash_ptr: *mut u8) -> u32;
89+
}
90+
91+
#[polkavm_derive::polkavm_export]
92+
extern "C" fn is_authorized() -> u32 {
93+
0
94+
}
95+
96+
#[polkavm_derive::polkavm_export]
97+
extern "C" fn refine() -> u32 {
98+
unsafe {
99+
core::arch::asm!(
100+
"li a3, 0xFEFF0004",
101+
"li a4, 0x20",
102+
);
103+
}
104+
0
105+
}
106+
107+
#[polkavm_derive::polkavm_export]
108+
extern "C" fn accumulate() -> u32 {
109+
let mut omega_7: u32 = 0xFEFF0000;
110+
let omega_8: u32 = 206;
111+
let omega_9: u32 = 0x2000;
112+
let omega_10: u32 = 0x1000;
113+
let omega_11: u32 = 0x3000;
114+
let omega_12: u32 = 0x4000;
115+
116+
let result = unsafe { new(omega_7, omega_8, omega_9, omega_10, omega_11, omega_12) };
117+
118+
unsafe {
119+
let ptr1 = 0xFEFF0000 as *mut u32;
120+
*ptr1 = 0;
121+
122+
let ptr2 = 0xFEFF0004 as *mut u32;
123+
*ptr2 = result;
124+
}
125+
126+
let mut omega_7: u32 = 0xFEFF0000;
127+
let omega_8: u32 = 4;
128+
let omega_9: u32 = 0xFEFF0004;
129+
let omega_10: u32 = 4;
130+
131+
let result = unsafe { write(omega_7, omega_8, omega_9, omega_10) };
132+
omega_7 = result;
133+
result
134+
}
135+
136+
#[polkavm_derive::polkavm_export]
137+
extern "C" fn on_transfer() -> u32 {
138+
0
139+
}

traces/safrole/genesis.bin

827 Bytes
Binary file not shown.

traces/safrole/genesis.json

+64-299
Large diffs are not rendered by default.
-304 Bytes
Binary file not shown.
-2.6 KB
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-2.6 KB
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.

traces/safrole/jam_duna/blocks/349446_5.json

-25
This file was deleted.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-2.6 KB
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-304 Bytes
Binary file not shown.
-2.82 KB
Binary file not shown.

0 commit comments

Comments
 (0)