Skip to content

Commit

Permalink
rlp: decode long hex (#46)
Browse files Browse the repository at this point in the history
* rlp: decode long hex

* abi: fix abi free
  • Loading branch information
zzzzzzch authored Jul 11, 2024
1 parent 3efa6cf commit c58f530
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 29 deletions.
34 changes: 32 additions & 2 deletions src/abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,38 @@ int eth_abi_free(struct eth_abi *abi) {
if (abi == NULL)
return -1;

free(abi->cframe);
abi->cframe = NULL;
if (abi->cframe != NULL) {
struct ethc_abi_frame *frame = abi->cframe;
while (frame) {
int i;
struct ethc_abi_frame *curr = frame;

if (frame->buf != NULL) {
if (frame->buf->buf != NULL) {
free(frame->buf->buf);
frame->buf->buf = NULL;
}
free(frame->buf);
frame->buf = NULL;
}

for (i = 0; i < frame->dybuflen; i++) {
struct ethc_abi_buf *dybuf = frame->dybufs[i];
if (dybuf != NULL) {
if (dybuf->buf != NULL) {
free(dybuf->buf);
dybuf->buf = NULL;
}
free(dybuf);
dybuf = NULL;
}
}

frame = frame->pframe;
free(curr);
curr = NULL;
}
}
return 1;
}

Expand Down
67 changes: 40 additions & 27 deletions src/rlp.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ int eth_rlp_array(struct eth_rlp *rlp) {
if (eth_rlp_len(rlp, NULL, &base) <= 0)
return -1;

if (base != 0xc0 && base != 0xf7)
return -1;

return 1;
}

Expand Down Expand Up @@ -165,7 +162,7 @@ int eth_rlp_len(struct eth_rlp *rlp, size_t *len, uint8_t *base) {
if (head <= 0x7F) {
llen = 1;
bbase = 0;
} else if (head <= 0xB7 || head <= 0xF7) {
} else if (head <= 0xB7 || (head >= 0xC0 && head <= 0xF7)) {
bbase = head <= 0xB7 ? 0x80 : 0xC0;
llen = head - bbase;
cframe->offset++;
Expand All @@ -174,19 +171,20 @@ int eth_rlp_len(struct eth_rlp *rlp, size_t *len, uint8_t *base) {
llen = head - bbase;

if (llen <= 1) {
llen = cframe->buf[cframe->offset++];
cframe->offset += llen + 1;
llen = cframe->buf[cframe->offset++];
} else if (llen <= 2) {
cframe->offset += llen + 2;
llen = cframe->buf[cframe->offset++] << 0x04;
llen |= llen | cframe->buf[cframe->offset++];
cframe->offset += llen + 2;
} else if (*len <= 4) {
cframe->offset = llen + 4;
llen = cframe->buf[cframe->offset++] << 0x18;
llen |= cframe->buf[cframe->offset++] << 0x10;
llen |= cframe->buf[cframe->offset++] << 0x08;
llen |= cframe->buf[cframe->offset++];
cframe->offset = llen + 4;
} else if (*len <= 8) {
cframe->offset += 8;
llen = (size_t)cframe->buf[cframe->offset++] << 0x38;
llen |= (size_t)cframe->buf[cframe->offset++] << 0x30;
llen |= (size_t)cframe->buf[cframe->offset++] << 0x28;
Expand All @@ -195,7 +193,6 @@ int eth_rlp_len(struct eth_rlp *rlp, size_t *len, uint8_t *base) {
llen |= cframe->buf[cframe->offset++] << 0x10;
llen |= cframe->buf[cframe->offset++] << 0x08;
llen |= cframe->buf[cframe->offset++];
cframe->offset += 8;
} else {
return -1;
}
Expand Down Expand Up @@ -248,9 +245,6 @@ int eth_rlp_bytes(struct eth_rlp *rlp, uint8_t **bytes, size_t *len) {
if (eth_rlp_len(rlp, len, &base) <= 0)
return -1;

if (base != 0x00 && base != 0x80)
return -1;

buf = (uint8_t*)malloc(sizeof(uint8_t) * (*len));
if (buf == NULL)
return -1;
Expand Down Expand Up @@ -296,8 +290,11 @@ int eth_rlp_hex(struct eth_rlp *rlp, char **hex, int *len) {
if (eth_rlp_bytes(rlp, &buf, &hsize) <= 0)
return -1;

if ((hsize = (size_t)eth_hex_from_bytes(hex, buf, hsize)) <= 0)
if (hsize == 0) {
*hex = "0";
} else if ((hsize = (size_t)eth_hex_from_bytes(hex, buf, hsize)) <= 0) {
return -1;
}

if (len != NULL)
*len = hsize;
Expand Down Expand Up @@ -326,7 +323,11 @@ int eth_rlp_uint8(struct eth_rlp *rlp, uint8_t *d) {
if (eth_rlp_bytes(rlp, &bytes, &blen) <= 0)
return -1;

*d = *bytes;
if (blen == 0) {
*d = 0;
} else {
*d = *bytes;
}
free(bytes);
return 1;
}
Expand All @@ -352,8 +353,12 @@ int eth_rlp_uint16(struct eth_rlp *rlp, uint16_t *d) {
if (eth_rlp_bytes(rlp, &bytes, &blen) <= 0)
return -1;

*d = bytes[0] << 0x08;
*d += bytes[1];
if (blen == 0) {
*d = 0;
} else {
*d = bytes[0] << 0x08;
*d += bytes[1];
}

free(bytes);
return 1;
Expand Down Expand Up @@ -382,10 +387,14 @@ int eth_rlp_uint32(struct eth_rlp *rlp, uint32_t *d) {
if (eth_rlp_bytes(rlp, &bytes, &blen) <= 0)
return -1;

*d = bytes[0] << 0x18;
*d |= bytes[1] << 0x10;
*d |= bytes[2] << 0x08;
*d |= bytes[3];
if (blen == 0) {
*d = 0;
} else {
*d = bytes[0] << 0x18;
*d |= bytes[1] << 0x10;
*d |= bytes[2] << 0x08;
*d |= bytes[3];
}
free(bytes);
return 1;
}
Expand Down Expand Up @@ -417,14 +426,18 @@ int eth_rlp_uint64(struct eth_rlp *rlp, uint64_t *d) {
if (eth_rlp_bytes(rlp, &bytes, &blen) <= 0)
return -1;

*d = (uint64_t) bytes[0] << 0x38;
*d |= (uint64_t)bytes[1] << 0x30;
*d |= (uint64_t)bytes[2] << 0x28;
*d |= (uint64_t)bytes[3] << 0x20;
*d |= bytes[4] << 0x18;
*d |= bytes[5] << 0x10;
*d |= bytes[6] << 0x8;
*d |= bytes[7];
if (blen == 0) {
*d = 0;
} else {
*d = (uint64_t) bytes[0] << 0x38;
*d |= (uint64_t)bytes[1] << 0x30;
*d |= (uint64_t)bytes[2] << 0x28;
*d |= (uint64_t)bytes[3] << 0x20;
*d |= bytes[4] << 0x18;
*d |= bytes[5] << 0x10;
*d |= bytes[6] << 0x8;
*d |= bytes[7];
}
free(bytes);
return 1;
}
Expand Down
1 change: 1 addition & 0 deletions test/run-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ int main() {
test_eth_rlp_address();
test_eth_rlp_to_hex();
test_eth_rlp_to_bytes();
test_eth_rlp_decode_eip1559_tx();
test_eth_abi_mpint();

done_testing();
Expand Down
62 changes: 62 additions & 0 deletions test/test-eth-rlp.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,65 @@ void test_eth_rlp_to_bytes(void) {
cmp_mem(bout, bytes, boutlen);
ok(boutlen == 3);
}

void test_eth_rlp_decode_eip1559_tx(void) {
// https://sepolia.etherscan.io/tx/0xd116c294d3eb46d5db8602ff38f0aae414fa7950747e20cdefe5982b7bd567f9
// This tx is EIP-1559 format, and the Txtype prefix `0x02` has been stripped
char *hex =
"f8d583aa36a78180843b9aca00851bf08eb000835b8d80942a21bf63839e571c2fc819"
"373296e0b50b4d6ad480b8648340f54900000000000000000000000066c444632ae2840a"
"a6cd3daa435f359f547ef9d30000000000000000000000005683c35fbbe9811340fba97f"
"aea8ef5c33f28be000000000000000000000000000000000000000000000000000000000"
"0016e360c001a099c06b4f79b805ae7be2dcd21191e470362c9d66b7cfea90b185015893"
"a1477ea03c16ce20c94c5ee0598154007a67fae010769fe3db29a1e40ac9532a91835a0"
"c";

// tx field
char *abi_hex;
char *to_addr;
char *value;
char *max_priority_fee_per_gas;
char *max_fee_per_gas;
char *gas_limit;
char *chain_id_hex;
uint64_t nonce = 0;
uint8_t v = 0;
char *r;
char *s;
size_t rlp0len, rlp1len, siglen = 32;

// decode tx
struct eth_rlp rlp;
ok(eth_rlp_from_hex(&rlp, hex, -1) == 1);
ok(eth_rlp_array(&rlp) == 1);
ok(eth_rlp_hex(&rlp, &chain_id_hex, NULL) == 1);
ok(eth_rlp_uint(&rlp, &nonce));
ok(eth_rlp_hex(&rlp, &max_priority_fee_per_gas, NULL));
ok(eth_rlp_hex(&rlp, &max_fee_per_gas, NULL));
ok(eth_rlp_hex(&rlp, &gas_limit, NULL));
ok(eth_rlp_address(&rlp, &to_addr));
ok(eth_rlp_hex(&rlp, &value, NULL));
ok(eth_rlp_hex(&rlp, &abi_hex, NULL));
ok(eth_rlp_array(&rlp)); // access list
ok(eth_rlp_array_end(&rlp));
ok(eth_rlp_uint8(&rlp, &v));
ok(eth_rlp_hex(&rlp, &r, NULL));
ok(eth_rlp_hex(&rlp, &s, NULL));
ok(eth_rlp_array_end(&rlp));

// check
is(chain_id_hex, "aa36a7");
ok(nonce == 0x80);
is(max_priority_fee_per_gas, "3b9aca00");
is(max_fee_per_gas, "1bf08eb000");
is(gas_limit, "5b8d80");
is(to_addr, "2a21bf63839e571c2fc819373296e0b50b4d6ad4");
is(value, "0");
is(abi_hex,
"8340f54900000000000000000000000066c444632ae2840aa6cd3daa435f359f547ef9d30"
"000000000000000000000005683c35fbbe9811340fba97faea8ef5c33f28be00000000000"
"00000000000000000000000000000000000000000000000016e360");
ok(v == 1);
is(r, "99c06b4f79b805ae7be2dcd21191e470362c9d66b7cfea90b185015893a1477e");
is(s, "3c16ce20c94c5ee0598154007a67fae010769fe3db29a1e40ac9532a91835a0c");
}
1 change: 1 addition & 0 deletions test/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ void test_eth_rlp_bytes(void);
void test_eth_rlp_hex(void);
void test_eth_rlp_to_hex(void);
void test_eth_rlp_to_bytes(void);
void test_eth_rlp_decode_eip1559_tx(void);

0 comments on commit c58f530

Please sign in to comment.