Skip to content

Commit 61defb1

Browse files
authored
Merge pull request #4 from darkdrag00nv2/serialize_signing_info
Implement support for encoding transactions along with signing info
2 parents 1a81a96 + 2900b7f commit 61defb1

File tree

3 files changed

+86
-19
lines changed

3 files changed

+86
-19
lines changed

__tests__/transaction.mjs

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ import { expect } from "@jest/globals";
66
const can = await getActor(false, "evm_utils");
77

88
test("create_transaction", async () => {
9+
let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
10+
let ten_thousand_as_bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 16];
11+
912
let item = {
1013
Legacy: {
1114
to: ethers.utils.arrayify(ethers.utils.hexlify("0xe94f1fa4f27d9d288ffea234bb62e1fbc086ca0c")),
12-
value: 0,
15+
value: arr,
1316
data: [],
1417
sign: [],
1518
chain_id: 1,
16-
nonce: 1,
17-
gas_limit: 10_000,
18-
gas_price: 10_000
19+
nonce: arr,
20+
gas_limit: ten_thousand_as_bytes,
21+
gas_price: ten_thousand_as_bytes
1922
}
2023
};
2124

@@ -47,29 +50,82 @@ test("create_transaction", async () => {
4750
expect(msgHash).toBe(hash);
4851
});
4952

53+
test("encode_signed_transaction", async () => {
54+
let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
55+
let ten_thousand_as_bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 16];
56+
57+
let item = {
58+
Legacy: {
59+
to: ethers.utils.arrayify(ethers.utils.hexlify("0xe94f1fa4f27d9d288ffea234bb62e1fbc086ca0c")),
60+
value: arr,
61+
data: [],
62+
sign: [
63+
{
64+
r: ethers.utils.arrayify(ethers.utils.hexlify("0xde8ef039a601ad81d0882568e503fd7d865d8e6e03c35f635b301263ce7e00c2")),
65+
s: ethers.utils.arrayify(ethers.utils.hexlify("0x770ceb3615e121d5fa712de1d9b5b27c64dc7ee0610d19307210a6de4b347ad9")),
66+
v: 38,
67+
from: [],
68+
hash: arr
69+
}
70+
],
71+
chain_id: 1,
72+
nonce: arr,
73+
gas_limit: ten_thousand_as_bytes,
74+
gas_price: ten_thousand_as_bytes
75+
}
76+
};
77+
78+
let encoded = await can.encode_signed_transaction(item);
79+
let tx = ethers.utils.parseTransaction(encoded.Ok[0]); //First value is tx
80+
81+
let hash = ethers.utils.hexlify(encoded.Ok[1]);
82+
83+
let signing_tx = {
84+
chainId: tx.chainId,
85+
data: tx.data,
86+
to: tx.to,
87+
gasLimit: tx.gasLimit,
88+
gasPrice: tx.gasPrice,
89+
nonce: tx.nonce,
90+
type: tx.type,
91+
value: tx.value
92+
};
93+
let signature_like = {
94+
r: ethers.utils.hexlify(item.Legacy.sign[0].r),
95+
s: ethers.utils.hexlify(item.Legacy.sign[0].s),
96+
v: item.Legacy.sign[0].v
97+
};
98+
99+
const raw = ethers.utils.serializeTransaction(signing_tx, signature_like); // returns RLP encoded tx
100+
const msgHash = ethers.utils.keccak256(raw);
101+
102+
expect(tx.to.toLocaleLowerCase()).toBe("0xe94f1fa4f27d9d288ffea234bb62e1fbc086ca0c");
103+
expect(tx.nonce).toStrictEqual(1);
104+
expect(tx.gasLimit).toStrictEqual(BigNumber.from(10_000));
105+
expect(tx.gasPrice).toStrictEqual(BigNumber.from(10_000));
106+
expect(tx.chainId).toStrictEqual(item.Legacy.chain_id);
107+
108+
expect(msgHash).toBe(hash);
109+
});
50110

51111
test("parse_transaction", async () => {
52112
let ser = {
53-
to: "0xe94f1fa4f27d9d288ffea234bb62e1fbc086ca0c",
54-
value: 0,
55-
data: [],
56-
chainId: 1,
57-
nonce: 1,
58-
gasLimit: 10_000,
59-
gasPrice: 10_000
113+
to: "0xe94f1fa4f27d9d288ffea234bb62e1fbc086ca0c",
114+
value: 0,
115+
data: [],
116+
chainId: 1,
117+
nonce: 1,
118+
gasPrice: BigNumber.from(10_000),
119+
gasLimit: 1
60120
};
61121

62122
let raw_tx = ethers.utils.serializeTransaction(ser);
63123

64-
console.log(raw_tx);
65-
66124
let decoded = await can.parse_transaction(ethers.utils.arrayify(raw_tx));
67125

68126
expect(decoded.Ok.Legacy).not.toBeUndefined();
69-
expect(decoded.Ok.Legacy.gas_limit).toBe(10_000n);
70-
expect(decoded.Ok.Legacy.gas_price).toBe(10_000n);
71-
expect(decoded.Ok.Legacy.nonce).toBe(1n);
72-
expect(decoded.Ok.Legacy.chain_id).toBe(1n);
127+
expect(BigNumber.from(decoded.Ok.Legacy.gas_limit)).toStrictEqual(BigNumber.from(1));
128+
expect(BigNumber.from(decoded.Ok.Legacy.gas_price)).toStrictEqual(BigNumber.from(10_000));
129+
expect(BigNumber.from(decoded.Ok.Legacy.nonce)).toStrictEqual(BigNumber.from(1));
130+
expect(BigNumber.from(decoded.Ok.Legacy.chain_id)).toStrictEqual(BigNumber.from(1));
73131
});
74-
75-

candid/utils.did

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ type TransactionLegacy = record {
6060
};
6161
service : {
6262
create_transaction : (Transaction) -> (Result) query;
63+
encode_signed_transaction : (Transaction) -> (Result) query;
6364
is_valid_public : (vec nat8) -> (Result_1) query;
6465
is_valid_signature : (vec nat8) -> (Result_1) query;
6566
keccak256 : (vec nat8) -> (vec nat8) query;

src/evm_utils/src/transaction.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ fn create_transaction(data: Transaction) -> Result<(Vec<u8>, U256), String> {
1616
Ok((raw.to_vec(), hash))
1717
}
1818

19+
/// Encodes transaction in rlp, including the signature data
20+
#[query]
21+
#[candid_method(query)]
22+
fn encode_signed_transaction(data: Transaction) -> Result<(Vec<u8>, U256), String> {
23+
let raw = data.encode(false);
24+
let hash = keccak256(&[&raw]);
25+
26+
Ok((raw.to_vec(), hash))
27+
}
28+
1929
/// Parses raw transaction, supports Legacy, EIP1559, EIP2930
2030
#[query]
2131
#[candid_method(query)]

0 commit comments

Comments
 (0)