Skip to content

Commit bc095c2

Browse files
authored
feat: slot and keylet api (#33)
* wip * keylet account * wip * wip * wip * wip * wip * wip * wip * fix nightly version at nightly-2024-10-17 * a * wip * fixfloat Xahau/xahaud#351 * wip * wip
1 parent 1d46607 commit bc095c2

24 files changed

+540
-197
lines changed

.github/workflows/build_hooks_rs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: "Use Rust nightly"
2121
uses: actions-rust-lang/setup-rust-toolchain@v1
2222
with:
23-
toolchain: "nightly"
23+
toolchain: "nightly-2024-10-17"
2424
target: "wasm32-unknown-unknown"
2525
components: "clippy,rustfmt"
2626
override: true

.github/workflows/lint_hooks_rs.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
- name: "Use Rust nightly"
1818
uses: actions-rust-lang/setup-rust-toolchain@v1
1919
with:
20-
toolchain: "nightly"
20+
toolchain: "nightly-2024-10-17"
2121
target: "wasm32-unknown-unknown"
2222
components: "clippy,rustfmt"
2323
override: true
@@ -39,9 +39,9 @@ jobs:
3939
- name: "Check Rust format in hooks-rs"
4040
run: |
4141
cd hooks-rs
42-
cargo +nightly fmt --all -- --check
42+
cargo fmt --all -- --check
4343
4444
- name: "Run Clippy lints in hooks-rs"
4545
run: |
4646
cd hooks-rs
47-
cargo +nightly clippy --all -- -D warnings
47+
cargo clippy --all -- -D warnings

.github/workflows/test_integration_hooks_rs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: "Use Rust nightly"
1919
uses: actions-rust-lang/setup-rust-toolchain@v1
2020
with:
21-
toolchain: "nightly"
21+
toolchain: "nightly-2024-10-17"
2222
target: "wasm32-unknown-unknown"
2323
components: "clippy,rustfmt"
2424
override: true

.github/workflows/udeps.yml

+5-4
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ jobs:
1212
- name: "Checkout source code"
1313
uses: "actions/checkout@v4"
1414

15-
- name: "Setup nightly toolchain"
16-
uses: "actions-rs/toolchain@v1"
15+
- name: "Use Rust nightly"
16+
uses: actions-rust-lang/setup-rust-toolchain@v1
1717
with:
18-
toolchain: "nightly"
19-
profile: "minimal"
18+
toolchain: "nightly-2024-10-17"
19+
target: "wasm32-unknown-unknown"
20+
components: "clippy,rustfmt"
2021
override: true
2122

2223
- uses: "Swatinem/rust-cache@v2"

README.md

+15-7
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ Float
134134
- [x] `float_negate`
135135
- [x] `float_compare`
136136
- [x] `float_sum`
137-
- [ ] `float_sto`
137+
- [x] `float_sto`
138138
- [x] `float_sto_set`
139139
- [x] `float_invert`
140140
- [x] `float_divide`
@@ -182,10 +182,10 @@ Originating transaction
182182
Utilities
183183

184184
- [x] `util_raddr`
185-
- [ ] `util_accid`
185+
- [x] `util_accid`
186186
- [ ] `util_verify`
187187
- [ ] `util_sha512h`
188-
- [ ] `util_keylet`
188+
- [x] `util_keylet`
189189

190190
Hook context
191191

@@ -208,23 +208,31 @@ Serialization
208208

209209
Slot
210210

211-
- [ ] `slot`
211+
- [x] `slot`
212212
- [ ] `slot_clear`
213213
- [ ] `slot_count`
214-
- [ ] `slot_set`
214+
- [x] `slot_set`
215215
- [ ] `slot_size`
216216
- [ ] `slot_subarray`
217-
- [ ] `slot_subfield`
217+
- [x] `slot_subfield`
218218
- [ ] `slot_type`
219219
- [ ] `xpop_slot`
220-
- [ ] `slot_float`
220+
- [x] `slot_float`
221221

222222
</details>
223223

224224
## C bindings
225225

226226
The latest header files can be found at https://github.com/XRPLF/hook-macros
227227

228+
## Debugging
229+
230+
- Using the debug stream in combination with `trace` API will be helpful. The debug stream is in the format of `wss://xahau-test.net/debugstream/{r-address}`. For example, wss://xahau-test.net/debugstream/rBDwqnirUMhMaYwzGCP1wqju51crjcBCVf.
231+
232+
## Rust nightly version
233+
234+
Due to an upstream dependency `wasm-bindgen-test` not being up to date with the latest Rust nightly, the Rust toolchain version must not go higher than `nightly-2024-10-17`.
235+
228236
## Credits
229237

230238
- This is a fork of [otov4its/xrpl-hooks](https://github.com/otov4its/xrpl-hooks) which has been unmaintained for a long time.

hooks-rs-template/rust-toolchain.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
[toolchain]
2-
channel = "nightly"
2+
channel = "nightly-2024-10-17"
3+
targets = ["wasm32-unknown-unknown"]

hooks-rs-template/tests/setup.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export class TestUtils {
9696
}
9797

9898
static async buildHook(hookName: string): Promise<iHook> {
99-
await exec("cargo +nightly build --release");
99+
await exec("cargo build --release");
100100
const hook = createHookPayload(
101101
0,
102102
// Add hook code after this

hooks-rs/examples/float.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,12 @@ pub extern "C" fn hook(_: u32) -> i64 {
109109
.unwrap_line_number();
110110
// 1.663822854409434e+29
111111
let b = XFL::new(14, 1663822854409434).unwrap_line_number();
112-
// -5.957877192508556e-31
113-
let expected_division_result = XFL::new(
114-
-46,
115-
// TODO: Not sure if https://richardah.github.io/xfl-tools/ is giving a wrong
116-
// float number because it's javascript, or if this is a bug in xrpld (low chance tho).
117-
// Originally it shows 5957877192508556, but trace_float of the result shows 5957877192508580.
118-
// For now we'll just use the result from trace_float, but need to confirm what's going on
119-
5957877192508580,
120-
)
121-
.unwrap_line_number()
122-
.neg()
123-
.unwrap_line_number();
112+
// TODO: is this right?
113+
// -5.957877192508581e-31
114+
let expected_division_result = XFL::new(-46, 5957877192508581)
115+
.unwrap_line_number()
116+
.neg()
117+
.unwrap_line_number();
124118
if (a / b).unwrap_line_number() != expected_division_result {
125119
rollback(b"", line!().into());
126120
}

hooks-rs/examples/keylet_account.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![feature(maybe_uninit_uninit_array)]
2+
#![no_std]
3+
#![no_main]
4+
5+
use hooks_rs::*;
6+
7+
#[no_mangle]
8+
pub extern "C" fn cbak(_: u32) -> i64 {
9+
0
10+
}
11+
12+
// Example: https://github.com/Xahau/TreasuryHook/blob/ac8e2f7db4b687450d9ca1cba412bfac3b1a87bc/treasuryInvoke.c#L150-L153
13+
#[no_mangle]
14+
pub extern "C" fn hook(_: u32) -> i64 {
15+
// Every hook needs to import guard function
16+
// and use it at least once
17+
max_iter(1);
18+
// https://explorer.xahau-test.net/r3zEReqN3Ge3g1GXUThuVSrn4dM8xpoA7i
19+
// 579CA1B8B51227C2E40AB3217D9421EFB13B1364
20+
let account_id: [u8; ACC_ID_LEN] = [
21+
0x57, 0x9C, 0xA1, 0xB8, 0xB5, 0x12, 0x27, 0xC2, 0xE4, 0x0A, 0xB3, 0x21, 0x7D, 0x94, 0x21,
22+
0xEF, 0xB1, 0x3B, 0x13, 0x64,
23+
];
24+
let keylet_payload = KeyletAccount::new(&account_id).build();
25+
let account_keylet = util_keylet(keylet_payload).unwrap_line_number();
26+
27+
let _ = trace(b"keylet", &account_keylet, DataRepr::AsHex);
28+
29+
// Check at https://richardah.github.io/xrpl-keylet-tools/
30+
// by inserting r3zEReqN3Ge3g1GXUThuVSrn4dM8xpoA7i into the account field
31+
// to get 0061355E27663861169420D62A5955FECE7FB519121F8CDC15963FD1561653531F9C
32+
//
33+
// Cannot do this because Rust compiled down to wasm produces an unguarded loop
34+
// TODO: if we want to make this possible, we might need to modify LLVM
35+
// but we don't do it now because the scope becomes too large
36+
// const EXPECTED_KEYLET: [u8; 34] = [
37+
// 0x00, 0x61, 0x35, 0x5E, 0x27, 0x66, 0x38, 0x61, 0x16, 0x94, 0x20, 0xD6, 0x2A, 0x59, 0x55,
38+
// 0xFE, 0xCE, 0x7F, 0xB5, 0x19, 0x12, 0x1F, 0x8C, 0xDC, 0x15, 0x96, 0x3F, 0xD1, 0x56, 0x16,
39+
// 0x53, 0x31, 0xF9, 0xC,
40+
// ];
41+
//
42+
// Check in TS test file
43+
accept(&account_keylet, 0);
44+
}

hooks-rs/examples/slot_account.rs

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#![feature(maybe_uninit_uninit_array)]
2+
#![no_std]
3+
#![no_main]
4+
5+
use hooks_rs::*;
6+
7+
const ACCOUNT_SLOT_ID: u32 = 1;
8+
const ACCOUNT_BALANCE_SLOT_ID: u32 = 3;
9+
10+
#[no_mangle]
11+
pub extern "C" fn cbak(_: u32) -> i64 {
12+
0
13+
}
14+
15+
// Example: https://github.com/Xahau/TreasuryHook/blob/ac8e2f7db4b687450d9ca1cba412bfac3b1a87bc/treasuryInvoke.c#L150-L153
16+
#[no_mangle]
17+
pub extern "C" fn hook(_: u32) -> i64 {
18+
// Every hook needs to import guard function
19+
// and use it at least once
20+
max_iter(1);
21+
// https://explorer.xahau-test.net/r3zEReqN3Ge3g1GXUThuVSrn4dM8xpoA7i
22+
// 579CA1B8B51227C2E40AB3217D9421EFB13B1364
23+
let account_id: [u8; ACC_ID_LEN] = [
24+
0x57, 0x9C, 0xA1, 0xB8, 0xB5, 0x12, 0x27, 0xC2, 0xE4, 0x0A, 0xB3, 0x21, 0x7D, 0x94, 0x21,
25+
0xEF, 0xB1, 0x3B, 0x13, 0x64,
26+
];
27+
let keylet_payload = KeyletAccount::new(&account_id).build();
28+
let account_keylet = util_keylet(keylet_payload).unwrap_line_number();
29+
30+
// Will throw if account does not exist, but we know the account exists, so it shouldn't throw
31+
slot_set(&account_keylet, ACCOUNT_SLOT_ID).unwrap_line_number();
32+
33+
// Does not exist on Xahau testnet
34+
// Check existence on https://explorer.xahau-test.net/rDAFKjBukJ6r197ZPH7W5QkJDqVQLZhxud
35+
let nonexistent_account_id: [u8; ACC_ID_LEN] = [
36+
0x8d, 0xff, 0x79, 0x78, 0xae, 0xb4, 0x94, 0x45, 0xc7, 0xcf, 0x8c, 0x93, 0x3a, 0x4a, 0xdf,
37+
0xa5, 0x23, 0x14, 0x06, 0xfa,
38+
];
39+
let nonexistent_account_keylet =
40+
util_keylet(KeyletAccount::new(&nonexistent_account_id).build()).unwrap_line_number();
41+
42+
match slot_set(&nonexistent_account_keylet, 2) {
43+
Ok(_) => {
44+
// This should not happen
45+
rollback(
46+
b"Should not be able to set slot for nonexistent account",
47+
-2,
48+
);
49+
}
50+
Err(e) => {
51+
// This is expected
52+
if e != Error::DoesntExist {
53+
// This should not happen
54+
rollback(
55+
b"Should not be able to set slot for nonexistent account",
56+
-3,
57+
);
58+
}
59+
}
60+
}
61+
62+
// First way to get the account balance
63+
slot_subfield(ACCOUNT_SLOT_ID, FieldId::Balance, ACCOUNT_BALANCE_SLOT_ID).unwrap_line_number();
64+
let account_balance_slot = slot::<XFL_LEN>(ACCOUNT_BALANCE_SLOT_ID).unwrap_line_number();
65+
// This should be 1000000000000000*10^(-6)
66+
let xfl_balance_0 = XFL::from_sto(&account_balance_slot).unwrap_line_number();
67+
let i64_balance_0 = xfl_balance_0.to_int64(0, false).unwrap_line_number();
68+
69+
// Another way to get the account balance
70+
// See https://github.com/Xahau/xahaud/blob/0b675465b4e038e6080146043ad7fb2bfaf1a53e/src/ripple/app/hook/impl/applyHook.cpp#L2790-L2797
71+
// balance is multiplied by 10^-6 (drops decimals) again for some reason when using slot_float
72+
// so this should be 1000000000000000*10^(-12)
73+
let xfl_balance_1 = slot_float(ACCOUNT_BALANCE_SLOT_ID).unwrap_line_number();
74+
75+
// 10 * (10^5) = 10^6
76+
let mul_factor = XFL::new(5, 10).unwrap_line_number();
77+
let adjusted_xfl_balance_1 = (xfl_balance_1 * mul_factor).unwrap_line_number();
78+
79+
let _ = trace_float(b"mul_factor", mul_factor);
80+
let _ = trace_float(b"xfl_balance_0", xfl_balance_0);
81+
let _ = trace_float(b"adjusted_xfl_balance_1", adjusted_xfl_balance_1);
82+
83+
// Assert same (equality is overloaded)
84+
if xfl_balance_0 != adjusted_xfl_balance_1 {
85+
rollback(b"xfl_balance_0 != adjusted_xfl_balance_1", -4);
86+
}
87+
88+
accept(b"passing", i64_balance_0);
89+
}

0 commit comments

Comments
 (0)