mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
include apache licenced fastrlp as reth-rlp (#63)
* include apache licenced fastrlp as reth-rlp * fmt * Include LICENCE and README for reth-rlp
This commit is contained in:
324
Cargo.lock
generated
324
Cargo.lock
generated
@ -22,6 +22,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anes"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.65"
|
version = "1.0.65"
|
||||||
@ -34,7 +40,7 @@ version = "0.1.12"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a941c39708478e8eea39243b5983f1c42d2717b3620ee91f4a52115fd02ac43f"
|
checksum = "a941c39708478e8eea39243b5983f1c42d2717b3620ee91f4a52115fd02ac43f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
"itertools 0.9.0",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -232,6 +238,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cast"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.73"
|
version = "1.0.73"
|
||||||
@ -263,6 +275,33 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"ciborium-ll",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-io"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-ll"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"half",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clang-sys"
|
name = "clang-sys"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -274,6 +313,18 @@ dependencies = [
|
|||||||
"libloading",
|
"libloading",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "3.2.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"clap_lex 0.2.4",
|
||||||
|
"indexmap",
|
||||||
|
"textwrap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.0.14"
|
version = "4.0.14"
|
||||||
@ -283,7 +334,7 @@ dependencies = [
|
|||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
"clap_lex",
|
"clap_lex 0.3.0",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"strsim",
|
"strsim",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
@ -302,6 +353,15 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||||
|
dependencies = [
|
||||||
|
"os_str_bytes",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -357,6 +417,85 @@ dependencies = [
|
|||||||
"build_const",
|
"build_const",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb"
|
||||||
|
dependencies = [
|
||||||
|
"anes",
|
||||||
|
"atty",
|
||||||
|
"cast",
|
||||||
|
"ciborium",
|
||||||
|
"clap 3.2.22",
|
||||||
|
"criterion-plot",
|
||||||
|
"itertools 0.10.5",
|
||||||
|
"lazy_static",
|
||||||
|
"num-traits",
|
||||||
|
"oorandom",
|
||||||
|
"plotters",
|
||||||
|
"rayon",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"tinytemplate",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion-plot"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||||
|
dependencies = [
|
||||||
|
"cast",
|
||||||
|
"itertools 0.10.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crunchy"
|
name = "crunchy"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -491,7 +630,7 @@ version = "17.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b"
|
checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethereum-types",
|
"ethereum-types 0.13.1",
|
||||||
"hex",
|
"hex",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
@ -509,7 +648,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef"
|
checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crunchy",
|
"crunchy",
|
||||||
"fixed-hash",
|
"fixed-hash 0.7.0",
|
||||||
"impl-rlp",
|
"impl-rlp",
|
||||||
"impl-serde",
|
"impl-serde",
|
||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
@ -524,7 +663,7 @@ dependencies = [
|
|||||||
"crc",
|
"crc",
|
||||||
"fastrlp",
|
"fastrlp",
|
||||||
"maplit",
|
"maplit",
|
||||||
"primitive-types",
|
"primitive-types 0.11.1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -535,10 +674,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6"
|
checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethbloom",
|
"ethbloom",
|
||||||
"fixed-hash",
|
"fixed-hash 0.7.0",
|
||||||
"impl-rlp",
|
"impl-rlp",
|
||||||
"impl-serde",
|
"impl-serde",
|
||||||
"primitive-types",
|
"primitive-types 0.11.1",
|
||||||
|
"uint",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ethereum-types"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81224dc661606574f5a0f28c9947d0ee1d93ff11c5f1c4e7272f52e8c0b5483c"
|
||||||
|
dependencies = [
|
||||||
|
"fixed-hash 0.8.0",
|
||||||
|
"primitive-types 0.12.0",
|
||||||
"uint",
|
"uint",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -568,6 +718,12 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ethnum"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2eac3c0b9fa6eb75255ebb42c0ba3e2210d102a66d2795afef6fed668f373311"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "event-listener"
|
name = "event-listener"
|
||||||
version = "2.5.3"
|
version = "2.5.3"
|
||||||
@ -602,7 +758,7 @@ dependencies = [
|
|||||||
"arrayvec",
|
"arrayvec",
|
||||||
"auto_impl",
|
"auto_impl",
|
||||||
"bytes",
|
"bytes",
|
||||||
"ethereum-types",
|
"ethereum-types 0.13.1",
|
||||||
"fastrlp-derive",
|
"fastrlp-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -640,6 +796,17 @@ dependencies = [
|
|||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixed-hash"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"rustc-hex",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -866,6 +1033,12 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "1.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -1057,6 +1230,15 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
@ -1368,6 +1550,15 @@ version = "2.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@ -1509,6 +1700,12 @@ version = "1.15.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oorandom"
|
||||||
|
version = "11.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opaque-debug"
|
name = "opaque-debug"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -1640,6 +1837,34 @@ dependencies = [
|
|||||||
"spki",
|
"spki",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
"plotters-backend",
|
||||||
|
"plotters-svg",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-backend"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-svg"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
|
||||||
|
dependencies = [
|
||||||
|
"plotters-backend",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -1652,13 +1877,23 @@ version = "0.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a"
|
checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fixed-hash",
|
"fixed-hash 0.7.0",
|
||||||
"impl-codec",
|
"impl-codec",
|
||||||
"impl-rlp",
|
"impl-rlp",
|
||||||
"impl-serde",
|
"impl-serde",
|
||||||
"uint",
|
"uint",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "primitive-types"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5cfd65aea0c5fa0bfcc7c9e7ca828c921ef778f43d325325ec84bda371bfa75a"
|
||||||
|
dependencies = [
|
||||||
|
"fixed-hash 0.8.0",
|
||||||
|
"uint",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -1748,6 +1983,30 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -1787,7 +2046,7 @@ dependencies = [
|
|||||||
name = "reth"
|
name = "reth"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap 4.0.14",
|
||||||
"eyre",
|
"eyre",
|
||||||
"reth-primitives",
|
"reth-primitives",
|
||||||
"serde",
|
"serde",
|
||||||
@ -1878,6 +2137,31 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reth-rlp"
|
||||||
|
version = "0.1.2"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"auto_impl",
|
||||||
|
"bytes",
|
||||||
|
"criterion",
|
||||||
|
"ethereum-types 0.14.0",
|
||||||
|
"ethnum",
|
||||||
|
"hex-literal",
|
||||||
|
"reth-rlp",
|
||||||
|
"reth-rlp-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reth-rlp-derive"
|
||||||
|
version = "0.1.1"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reth-rpc"
|
name = "reth-rpc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -1954,7 +2238,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"primitive-types",
|
"primitive-types 0.11.1",
|
||||||
"revm_precompiles",
|
"revm_precompiles",
|
||||||
"rlp",
|
"rlp",
|
||||||
"sha3",
|
"sha3",
|
||||||
@ -1970,7 +2254,7 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
"num",
|
"num",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"primitive-types",
|
"primitive-types 0.11.1",
|
||||||
"ripemd",
|
"ripemd",
|
||||||
"secp256k1",
|
"secp256k1",
|
||||||
"sha2",
|
"sha2",
|
||||||
@ -2444,6 +2728,12 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.37"
|
version = "1.0.37"
|
||||||
@ -2473,6 +2763,16 @@ dependencies = [
|
|||||||
"crunchy",
|
"crunchy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinytemplate"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.21.2"
|
version = "1.21.2"
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
members = [
|
members = [
|
||||||
"bin/reth",
|
"bin/reth",
|
||||||
"crate-template",
|
"crate-template",
|
||||||
|
"crates/common/rlp",
|
||||||
|
"crates/common/rlp-derive",
|
||||||
"crates/db",
|
"crates/db",
|
||||||
"crates/executor",
|
"crates/executor",
|
||||||
"crates/interfaces",
|
"crates/interfaces",
|
||||||
|
|||||||
16
crates/common/rlp-derive/Cargo.toml
Normal file
16
crates/common/rlp-derive/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "reth-rlp-derive"
|
||||||
|
version = "0.1.1"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Procedural macros for fastrlp"
|
||||||
|
repository = "https://github.com/foundry-rs/reth"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bytes = { version = "1", default-features = false }
|
||||||
|
syn = "1"
|
||||||
|
quote = "1"
|
||||||
|
proc-macro2 = "1"
|
||||||
201
crates/common/rlp-derive/LICENCE
Normal file
201
crates/common/rlp-derive/LICENCE
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
3
crates/common/rlp-derive/README.md
Normal file
3
crates/common/rlp-derive/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# RLP derive crate
|
||||||
|
|
||||||
|
forked from erlier Apache licenced fastrlp-derive crate, before it changed licence to GPL.
|
||||||
95
crates/common/rlp-derive/src/de.rs
Normal file
95
crates/common/rlp-derive/src/de.rs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
pub fn impl_decodable(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
|
let body = if let syn::Data::Struct(s) = &ast.data {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
panic!("#[derive(RlpDecodable)] is only defined for structs.");
|
||||||
|
};
|
||||||
|
|
||||||
|
let stmts: Vec<_> =
|
||||||
|
body.fields.iter().enumerate().map(|(i, field)| decodable_field(i, field)).collect();
|
||||||
|
let name = &ast.ident;
|
||||||
|
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||||
|
|
||||||
|
let impl_block = quote! {
|
||||||
|
impl #impl_generics reth_rlp::Decodable for #name #ty_generics #where_clause {
|
||||||
|
fn decode(mut buf: &mut &[u8]) -> Result<Self, reth_rlp::DecodeError> {
|
||||||
|
let b = &mut &**buf;
|
||||||
|
let rlp_head = reth_rlp::Header::decode(b)?;
|
||||||
|
|
||||||
|
if !rlp_head.list {
|
||||||
|
return Err(reth_rlp::DecodeError::UnexpectedString);
|
||||||
|
}
|
||||||
|
|
||||||
|
let started_len = b.len();
|
||||||
|
let this = Self {
|
||||||
|
#(#stmts)*
|
||||||
|
};
|
||||||
|
|
||||||
|
let consumed = started_len - b.len();
|
||||||
|
if consumed != rlp_head.payload_length {
|
||||||
|
return Err(reth_rlp::DecodeError::ListLengthMismatch {
|
||||||
|
expected: rlp_head.payload_length,
|
||||||
|
got: consumed,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
*buf = *b;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
const _: () = {
|
||||||
|
extern crate reth_rlp;
|
||||||
|
#impl_block
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn impl_decodable_wrapper(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
|
let body = if let syn::Data::Struct(s) = &ast.data {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
panic!("#[derive(RlpEncodableWrapper)] is only defined for structs.");
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
body.fields.iter().count(),
|
||||||
|
1,
|
||||||
|
"#[derive(RlpEncodableWrapper)] is only defined for structs with one field."
|
||||||
|
);
|
||||||
|
|
||||||
|
let name = &ast.ident;
|
||||||
|
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||||
|
|
||||||
|
let impl_block = quote! {
|
||||||
|
impl #impl_generics reth_rlp::Decodable for #name #ty_generics #where_clause {
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, reth_rlp::DecodeError> {
|
||||||
|
Ok(Self(reth_rlp::Decodable::decode(buf)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
const _: () = {
|
||||||
|
extern crate reth_rlp;
|
||||||
|
#impl_block
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decodable_field(index: usize, field: &syn::Field) -> TokenStream {
|
||||||
|
let id = if let Some(ident) = &field.ident {
|
||||||
|
quote! { #ident }
|
||||||
|
} else {
|
||||||
|
let index = syn::Index::from(index);
|
||||||
|
quote! { #index }
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! { #id: reth_rlp::Decodable::decode(b)?, }
|
||||||
|
}
|
||||||
152
crates/common/rlp-derive/src/en.rs
Normal file
152
crates/common/rlp-derive/src/en.rs
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
pub fn impl_encodable(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
|
let body = if let syn::Data::Struct(s) = &ast.data {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
panic!("#[derive(RlpEncodable)] is only defined for structs.");
|
||||||
|
};
|
||||||
|
|
||||||
|
let length_stmts: Vec<_> =
|
||||||
|
body.fields.iter().enumerate().map(|(i, field)| encodable_length(i, field)).collect();
|
||||||
|
|
||||||
|
let stmts: Vec<_> =
|
||||||
|
body.fields.iter().enumerate().map(|(i, field)| encodable_field(i, field)).collect();
|
||||||
|
let name = &ast.ident;
|
||||||
|
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||||
|
|
||||||
|
let impl_block = quote! {
|
||||||
|
trait E {
|
||||||
|
fn rlp_header(&self) -> reth_rlp::Header;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl #impl_generics E for #name #ty_generics #where_clause {
|
||||||
|
fn rlp_header(&self) -> reth_rlp::Header {
|
||||||
|
let mut rlp_head = reth_rlp::Header { list: true, payload_length: 0 };
|
||||||
|
#(#length_stmts)*
|
||||||
|
rlp_head
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl #impl_generics reth_rlp::Encodable for #name #ty_generics #where_clause {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
let rlp_head = E::rlp_header(self);
|
||||||
|
return reth_rlp::length_of_length(rlp_head.payload_length) + rlp_head.payload_length;
|
||||||
|
}
|
||||||
|
fn encode(&self, out: &mut dyn reth_rlp::BufMut) {
|
||||||
|
E::rlp_header(self).encode(out);
|
||||||
|
#(#stmts)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
const _: () = {
|
||||||
|
extern crate reth_rlp;
|
||||||
|
#impl_block
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn impl_encodable_wrapper(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
|
let body = if let syn::Data::Struct(s) = &ast.data {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
panic!("#[derive(RlpEncodableWrapper)] is only defined for structs.");
|
||||||
|
};
|
||||||
|
|
||||||
|
let ident = {
|
||||||
|
let fields: Vec<_> = body.fields.iter().collect();
|
||||||
|
if fields.len() == 1 {
|
||||||
|
let field = fields.first().expect("fields.len() == 1; qed");
|
||||||
|
field_ident(0, field)
|
||||||
|
} else {
|
||||||
|
panic!("#[derive(RlpEncodableWrapper)] is only defined for structs with one field.")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = &ast.ident;
|
||||||
|
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||||
|
|
||||||
|
let impl_block = quote! {
|
||||||
|
impl #impl_generics reth_rlp::Encodable for #name #ty_generics #where_clause {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
self.#ident.length()
|
||||||
|
}
|
||||||
|
fn encode(&self, out: &mut dyn reth_rlp::BufMut) {
|
||||||
|
self.#ident.encode(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
const _: () = {
|
||||||
|
extern crate reth_rlp;
|
||||||
|
#impl_block
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn impl_max_encoded_len(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
|
let body = if let syn::Data::Struct(s) = &ast.data {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
panic!("#[derive(RlpEncodable)] is only defined for structs.");
|
||||||
|
};
|
||||||
|
|
||||||
|
let stmts: Vec<_> = body
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, field)| encodable_max_length(index, field))
|
||||||
|
.collect();
|
||||||
|
let name = &ast.ident;
|
||||||
|
|
||||||
|
let impl_block = quote! {
|
||||||
|
unsafe impl reth_rlp::MaxEncodedLen<{ reth_rlp::const_add(reth_rlp::length_of_length(#(#stmts)*), #(#stmts)*) }> for #name {}
|
||||||
|
unsafe impl reth_rlp::MaxEncodedLenAssoc for #name {
|
||||||
|
const LEN: usize = { reth_rlp::const_add(reth_rlp::length_of_length(#(#stmts)*), { #(#stmts)* }) };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
const _: () = {
|
||||||
|
extern crate reth_rlp;
|
||||||
|
#impl_block
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn field_ident(index: usize, field: &syn::Field) -> TokenStream {
|
||||||
|
if let Some(ident) = &field.ident {
|
||||||
|
quote! { #ident }
|
||||||
|
} else {
|
||||||
|
let index = syn::Index::from(index);
|
||||||
|
quote! { #index }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encodable_length(index: usize, field: &syn::Field) -> TokenStream {
|
||||||
|
let ident = field_ident(index, field);
|
||||||
|
|
||||||
|
quote! { rlp_head.payload_length += reth_rlp::Encodable::length(&self.#ident); }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encodable_max_length(index: usize, field: &syn::Field) -> TokenStream {
|
||||||
|
let fieldtype = &field.ty;
|
||||||
|
|
||||||
|
if index == 0 {
|
||||||
|
quote! { <#fieldtype as reth_rlp::MaxEncodedLenAssoc>::LEN }
|
||||||
|
} else {
|
||||||
|
quote! { + <#fieldtype as reth_rlp::MaxEncodedLenAssoc>::LEN }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encodable_field(index: usize, field: &syn::Field) -> TokenStream {
|
||||||
|
let ident = field_ident(index, field);
|
||||||
|
|
||||||
|
let id = quote! { self.#ident };
|
||||||
|
|
||||||
|
quote! { reth_rlp::Encodable::encode(&#id, out); }
|
||||||
|
}
|
||||||
53
crates/common/rlp-derive/src/lib.rs
Normal file
53
crates/common/rlp-derive/src/lib.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//! Derive macro for `#[derive(RlpEncodable, RlpDecodable)]`.
|
||||||
|
//!
|
||||||
|
//! For example of usage see `./tests/rlp.rs`.
|
||||||
|
//!
|
||||||
|
//! This library also supports up to 1 `#[rlp(default)]` in a struct,
|
||||||
|
//! which is similar to [`#[serde(default)]`](https://serde.rs/field-attrs.html#default)
|
||||||
|
//! with the caveat that we use the `Default` value if
|
||||||
|
//! the field deserialization fails, as we don't serialize field
|
||||||
|
//! names and there is no way to tell if it is present or not.
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
mod de;
|
||||||
|
mod en;
|
||||||
|
|
||||||
|
use de::*;
|
||||||
|
use en::*;
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
|
#[proc_macro_derive(RlpEncodable, attributes(rlp))]
|
||||||
|
pub fn encodable(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = syn::parse(input).unwrap();
|
||||||
|
let gen = impl_encodable(&ast);
|
||||||
|
gen.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(RlpEncodableWrapper, attributes(rlp))]
|
||||||
|
pub fn encodable_wrapper(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = syn::parse(input).unwrap();
|
||||||
|
let gen = impl_encodable_wrapper(&ast);
|
||||||
|
gen.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(RlpMaxEncodedLen, attributes(rlp))]
|
||||||
|
pub fn max_encoded_len(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = syn::parse(input).unwrap();
|
||||||
|
let gen = impl_max_encoded_len(&ast);
|
||||||
|
gen.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(RlpDecodable, attributes(rlp))]
|
||||||
|
pub fn decodable(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = syn::parse(input).unwrap();
|
||||||
|
let gen = impl_decodable(&ast);
|
||||||
|
gen.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(RlpDecodableWrapper, attributes(rlp))]
|
||||||
|
pub fn decodable_wrapper(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = syn::parse(input).unwrap();
|
||||||
|
let gen = impl_decodable_wrapper(&ast);
|
||||||
|
gen.into()
|
||||||
|
}
|
||||||
34
crates/common/rlp/Cargo.toml
Normal file
34
crates/common/rlp/Cargo.toml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[package]
|
||||||
|
name = "reth-rlp"
|
||||||
|
version = "0.1.2"
|
||||||
|
edition = "2021"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
description = "Fast RLP serialization library"
|
||||||
|
repository = "https://github.com/foundry-rs/reth"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
arrayvec = { version = "0.7", default-features = false }
|
||||||
|
auto_impl = "1"
|
||||||
|
bytes = { version = "1", default-features = false }
|
||||||
|
ethnum = { version = "1", default-features = false, optional = true }
|
||||||
|
ethereum-types = { version = "0.14", default-features = false, optional = true }
|
||||||
|
reth-rlp-derive = { version = "0.1", path = "../rlp-derive", optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
reth-rlp-test = { path = ".", package = "reth-rlp", features = [
|
||||||
|
"derive",
|
||||||
|
"std",
|
||||||
|
"ethnum",
|
||||||
|
"ethereum-types",
|
||||||
|
] }
|
||||||
|
criterion = "0.4.0"
|
||||||
|
hex-literal = "0.3"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
alloc = []
|
||||||
|
derive = ["reth-rlp-derive"]
|
||||||
|
std = ["alloc"]
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "bench"
|
||||||
|
harness = false
|
||||||
201
crates/common/rlp/LICENCE
Normal file
201
crates/common/rlp/LICENCE
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
3
crates/common/rlp/README.md
Normal file
3
crates/common/rlp/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# RLP encoder decoder crate
|
||||||
|
|
||||||
|
forked from erlier Apache licenced fastrlp crate, before it changed licence to GPL
|
||||||
72
crates/common/rlp/benches/bench.rs
Normal file
72
crates/common/rlp/benches/bench.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 2020 Parity Technologies
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! benchmarking for rlp
|
||||||
|
|
||||||
|
use bytes::BytesMut;
|
||||||
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
|
use ethnum::*;
|
||||||
|
use hex_literal::hex;
|
||||||
|
use reth_rlp::*;
|
||||||
|
|
||||||
|
fn bench_encode(c: &mut Criterion) {
|
||||||
|
c.bench_function("encode_u64", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut out = BytesMut::new();
|
||||||
|
let _ = 0x1023_4567_89ab_cdefu64.encode(&mut out);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
c.bench_function("encode_u256", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut out = BytesMut::new();
|
||||||
|
let uint = U256::from_be_bytes(hex!(
|
||||||
|
"8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0"
|
||||||
|
));
|
||||||
|
uint.encode(&mut out);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
c.bench_function("encode_1000_u64", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut out = BytesMut::new();
|
||||||
|
reth_rlp::encode_list(
|
||||||
|
(0..1000u64).into_iter().collect::<Vec<_>>().as_slice(),
|
||||||
|
&mut out,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_decode(c: &mut Criterion) {
|
||||||
|
c.bench_function("decode_u64", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let data = [0x88, 0x10, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
|
||||||
|
let _ = u64::decode(&mut &data[..]).unwrap();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
c.bench_function("decode_u256", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let data = vec![
|
||||||
|
0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0x09, 0x10, 0x20, 0x30, 0x40,
|
||||||
|
0x50, 0x60, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x12, 0xf0,
|
||||||
|
];
|
||||||
|
let _ = U256::decode(&mut &data[..]).unwrap();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
c.bench_function("decode_1000_u64", |b| {
|
||||||
|
let input = (0..1000u64).into_iter().collect::<Vec<_>>();
|
||||||
|
let mut data = BytesMut::new();
|
||||||
|
reth_rlp::encode_list(input.as_slice(), &mut data);
|
||||||
|
b.iter(|| {
|
||||||
|
let _ = Vec::<u64>::decode(&mut &data[..]).unwrap();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, bench_encode, bench_decode);
|
||||||
|
criterion_main!(benches);
|
||||||
560
crates/common/rlp/src/decode.rs
Normal file
560
crates/common/rlp/src/decode.rs
Normal file
@ -0,0 +1,560 @@
|
|||||||
|
use crate::types::Header;
|
||||||
|
use bytes::{Buf, Bytes, BytesMut};
|
||||||
|
|
||||||
|
pub trait Decodable: Sized {
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
mod alloc_impl {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
impl<T> Decodable for ::alloc::boxed::Box<T>
|
||||||
|
where
|
||||||
|
T: Decodable + Sized,
|
||||||
|
{
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
T::decode(buf).map(::alloc::boxed::Box::new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Decodable for ::alloc::sync::Arc<T>
|
||||||
|
where
|
||||||
|
T: Decodable + Sized,
|
||||||
|
{
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
T::decode(buf).map(::alloc::sync::Arc::new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for ::alloc::string::String {
|
||||||
|
fn decode(from: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
let h = Header::decode(from)?;
|
||||||
|
if h.list {
|
||||||
|
return Err(DecodeError::UnexpectedList)
|
||||||
|
}
|
||||||
|
let mut to = ::alloc::vec::Vec::with_capacity(h.payload_length);
|
||||||
|
to.extend_from_slice(&from[..h.payload_length]);
|
||||||
|
from.advance(h.payload_length);
|
||||||
|
|
||||||
|
Self::from_utf8(to).map_err(|_| DecodeError::Custom("invalid string"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub enum DecodeError {
|
||||||
|
Overflow,
|
||||||
|
LeadingZero,
|
||||||
|
InputTooShort,
|
||||||
|
NonCanonicalSingleByte,
|
||||||
|
NonCanonicalSize,
|
||||||
|
UnexpectedLength,
|
||||||
|
UnexpectedString,
|
||||||
|
UnexpectedList,
|
||||||
|
ListLengthMismatch { expected: usize, got: usize },
|
||||||
|
Custom(&'static str),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for DecodeError {}
|
||||||
|
|
||||||
|
impl core::fmt::Display for DecodeError {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
DecodeError::Overflow => write!(f, "overflow"),
|
||||||
|
DecodeError::LeadingZero => write!(f, "leading zero"),
|
||||||
|
DecodeError::InputTooShort => write!(f, "input too short"),
|
||||||
|
DecodeError::NonCanonicalSingleByte => write!(f, "non-canonical single byte"),
|
||||||
|
DecodeError::NonCanonicalSize => write!(f, "non-canonical size"),
|
||||||
|
DecodeError::UnexpectedLength => write!(f, "unexpected length"),
|
||||||
|
DecodeError::UnexpectedString => write!(f, "unexpected string"),
|
||||||
|
DecodeError::UnexpectedList => write!(f, "unexpected list"),
|
||||||
|
DecodeError::ListLengthMismatch { expected, got } => {
|
||||||
|
write!(f, "list length mismatch: expected {expected}, got {got}")
|
||||||
|
}
|
||||||
|
DecodeError::Custom(err) => write!(f, "{err}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Header {
|
||||||
|
pub fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
if !buf.has_remaining() {
|
||||||
|
return Err(DecodeError::InputTooShort)
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = buf[0];
|
||||||
|
let h: Self = {
|
||||||
|
if b < 0x80 {
|
||||||
|
Self { list: false, payload_length: 1 }
|
||||||
|
} else if b < 0xB8 {
|
||||||
|
buf.advance(1);
|
||||||
|
let h = Self { list: false, payload_length: b as usize - 0x80 };
|
||||||
|
|
||||||
|
if h.payload_length == 1 {
|
||||||
|
if !buf.has_remaining() {
|
||||||
|
return Err(DecodeError::InputTooShort)
|
||||||
|
}
|
||||||
|
if buf[0] < 0x80 {
|
||||||
|
return Err(DecodeError::NonCanonicalSingleByte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h
|
||||||
|
} else if b < 0xC0 {
|
||||||
|
buf.advance(1);
|
||||||
|
let len_of_len = b as usize - 0xB7;
|
||||||
|
if buf.len() < len_of_len {
|
||||||
|
return Err(DecodeError::InputTooShort)
|
||||||
|
}
|
||||||
|
let payload_length = usize::try_from(u64::from_be_bytes(
|
||||||
|
static_left_pad(&buf[..len_of_len]).ok_or(DecodeError::LeadingZero)?,
|
||||||
|
))
|
||||||
|
.map_err(|_| DecodeError::Custom("Input too big"))?;
|
||||||
|
buf.advance(len_of_len);
|
||||||
|
if payload_length < 56 {
|
||||||
|
return Err(DecodeError::NonCanonicalSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { list: false, payload_length }
|
||||||
|
} else if b < 0xF8 {
|
||||||
|
buf.advance(1);
|
||||||
|
Self { list: true, payload_length: b as usize - 0xC0 }
|
||||||
|
} else {
|
||||||
|
buf.advance(1);
|
||||||
|
let list = true;
|
||||||
|
let len_of_len = b as usize - 0xF7;
|
||||||
|
if buf.len() < len_of_len {
|
||||||
|
return Err(DecodeError::InputTooShort)
|
||||||
|
}
|
||||||
|
let payload_length = usize::try_from(u64::from_be_bytes(
|
||||||
|
static_left_pad(&buf[..len_of_len]).ok_or(DecodeError::LeadingZero)?,
|
||||||
|
))
|
||||||
|
.map_err(|_| DecodeError::Custom("Input too big"))?;
|
||||||
|
buf.advance(len_of_len);
|
||||||
|
if payload_length < 56 {
|
||||||
|
return Err(DecodeError::NonCanonicalSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { list, payload_length }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if buf.remaining() < h.payload_length {
|
||||||
|
return Err(DecodeError::InputTooShort)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn static_left_pad<const LEN: usize>(data: &[u8]) -> Option<[u8; LEN]> {
|
||||||
|
if data.len() > LEN {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut v = [0; LEN];
|
||||||
|
|
||||||
|
if data.is_empty() {
|
||||||
|
return Some(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data[0] == 0 {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
|
v[LEN - data.len()..].copy_from_slice(data);
|
||||||
|
Some(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! decode_integer {
|
||||||
|
($t:ty) => {
|
||||||
|
impl Decodable for $t {
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
let h = Header::decode(buf)?;
|
||||||
|
if h.list {
|
||||||
|
return Err(DecodeError::UnexpectedList)
|
||||||
|
}
|
||||||
|
if h.payload_length > (<$t>::BITS as usize / 8) {
|
||||||
|
return Err(DecodeError::Overflow)
|
||||||
|
}
|
||||||
|
if buf.remaining() < h.payload_length {
|
||||||
|
return Err(DecodeError::InputTooShort)
|
||||||
|
}
|
||||||
|
let v = <$t>::from_be_bytes(
|
||||||
|
static_left_pad(&buf[..h.payload_length]).ok_or(DecodeError::LeadingZero)?,
|
||||||
|
);
|
||||||
|
buf.advance(h.payload_length);
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
decode_integer!(usize);
|
||||||
|
decode_integer!(u8);
|
||||||
|
decode_integer!(u16);
|
||||||
|
decode_integer!(u32);
|
||||||
|
decode_integer!(u64);
|
||||||
|
decode_integer!(u128);
|
||||||
|
|
||||||
|
impl Decodable for bool {
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
Ok(match u8::decode(buf)? {
|
||||||
|
0 => false,
|
||||||
|
1 => true,
|
||||||
|
_ => return Err(DecodeError::Custom("invalid bool value, must be 0 or 1")),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethnum")]
|
||||||
|
decode_integer!(ethnum::U256);
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
mod ethereum_types_support {
|
||||||
|
use super::*;
|
||||||
|
use ethereum_types::*;
|
||||||
|
|
||||||
|
macro_rules! fixed_hash_impl {
|
||||||
|
($t:ty) => {
|
||||||
|
impl Decodable for $t {
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
Decodable::decode(buf).map(Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed_hash_impl!(H64);
|
||||||
|
fixed_hash_impl!(H128);
|
||||||
|
fixed_hash_impl!(H160);
|
||||||
|
fixed_hash_impl!(H256);
|
||||||
|
fixed_hash_impl!(H512);
|
||||||
|
fixed_hash_impl!(H520);
|
||||||
|
//TODO fixed_hash_impl!(Bloom);
|
||||||
|
|
||||||
|
macro_rules! fixed_uint_impl {
|
||||||
|
($t:ty, $n_bytes:tt) => {
|
||||||
|
impl Decodable for $t {
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
let h = Header::decode(buf)?;
|
||||||
|
if h.list {
|
||||||
|
return Err(DecodeError::UnexpectedList)
|
||||||
|
}
|
||||||
|
if h.payload_length > $n_bytes {
|
||||||
|
return Err(DecodeError::Overflow)
|
||||||
|
}
|
||||||
|
if buf.remaining() < h.payload_length {
|
||||||
|
return Err(DecodeError::InputTooShort)
|
||||||
|
}
|
||||||
|
let n = <$t>::from_big_endian(
|
||||||
|
&static_left_pad::<$n_bytes>(&buf[..h.payload_length])
|
||||||
|
.ok_or(DecodeError::LeadingZero)?,
|
||||||
|
);
|
||||||
|
buf.advance(h.payload_length);
|
||||||
|
Ok(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed_uint_impl!(U64, 8);
|
||||||
|
fixed_uint_impl!(U128, 16);
|
||||||
|
fixed_uint_impl!(U256, 32);
|
||||||
|
fixed_uint_impl!(U512, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Decodable for [u8; N] {
|
||||||
|
fn decode(from: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
let h = Header::decode(from)?;
|
||||||
|
if h.list {
|
||||||
|
return Err(DecodeError::UnexpectedList)
|
||||||
|
}
|
||||||
|
if h.payload_length != N {
|
||||||
|
return Err(DecodeError::UnexpectedLength)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut to = [0_u8; N];
|
||||||
|
to.copy_from_slice(&from[..N]);
|
||||||
|
from.advance(N);
|
||||||
|
|
||||||
|
Ok(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for BytesMut {
|
||||||
|
fn decode(from: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
let h = Header::decode(from)?;
|
||||||
|
if h.list {
|
||||||
|
return Err(DecodeError::UnexpectedList)
|
||||||
|
}
|
||||||
|
let mut to = BytesMut::with_capacity(h.payload_length);
|
||||||
|
to.extend_from_slice(&from[..h.payload_length]);
|
||||||
|
from.advance(h.payload_length);
|
||||||
|
|
||||||
|
Ok(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for Bytes {
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
BytesMut::decode(buf).map(BytesMut::freeze)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Rlp<'a> {
|
||||||
|
payload_view: &'a [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Rlp<'a> {
|
||||||
|
pub fn new(mut payload: &'a [u8]) -> Result<Self, DecodeError> {
|
||||||
|
let h = Header::decode(&mut payload)?;
|
||||||
|
if !h.list {
|
||||||
|
return Err(DecodeError::UnexpectedString)
|
||||||
|
}
|
||||||
|
|
||||||
|
let payload_view = &payload[..h.payload_length];
|
||||||
|
Ok(Self { payload_view })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_next<T: Decodable>(&mut self) -> Result<Option<T>, DecodeError> {
|
||||||
|
if self.payload_view.is_empty() {
|
||||||
|
return Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(T::decode(&mut self.payload_view)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<E> Decodable for alloc::vec::Vec<E>
|
||||||
|
where
|
||||||
|
E: Decodable,
|
||||||
|
{
|
||||||
|
fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
||||||
|
let h = Header::decode(buf)?;
|
||||||
|
if !h.list {
|
||||||
|
return Err(DecodeError::UnexpectedString)
|
||||||
|
}
|
||||||
|
|
||||||
|
let payload_view = &mut &buf[..h.payload_length];
|
||||||
|
|
||||||
|
let mut to = alloc::vec::Vec::new();
|
||||||
|
while !payload_view.is_empty() {
|
||||||
|
to.push(E::decode(payload_view)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.advance(h.payload_length);
|
||||||
|
|
||||||
|
Ok(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use alloc::vec;
|
||||||
|
use core::fmt::Debug;
|
||||||
|
use ethereum_types::{U128, U256, U512, U64};
|
||||||
|
use ethnum::AsU256;
|
||||||
|
use hex_literal::hex;
|
||||||
|
|
||||||
|
fn check_decode<T, IT>(fixtures: IT)
|
||||||
|
where
|
||||||
|
T: Decodable + PartialEq + Debug,
|
||||||
|
IT: IntoIterator<Item = (Result<T, DecodeError>, &'static [u8])>,
|
||||||
|
{
|
||||||
|
for (expected, mut input) in fixtures {
|
||||||
|
assert_eq!(T::decode(&mut input), expected);
|
||||||
|
if expected.is_ok() {
|
||||||
|
assert_eq!(input, &[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_decode_list<T, IT>(fixtures: IT)
|
||||||
|
where
|
||||||
|
T: Decodable + PartialEq + Debug,
|
||||||
|
IT: IntoIterator<Item = (Result<alloc::vec::Vec<T>, DecodeError>, &'static [u8])>,
|
||||||
|
{
|
||||||
|
for (expected, mut input) in fixtures {
|
||||||
|
assert_eq!(vec::Vec::<T>::decode(&mut input), expected);
|
||||||
|
if expected.is_ok() {
|
||||||
|
assert_eq!(input, &[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rlp_strings() {
|
||||||
|
check_decode::<Bytes, _>(vec![
|
||||||
|
(Ok((&hex!("00")[..]).to_vec().into()), &hex!("00")[..]),
|
||||||
|
(
|
||||||
|
Ok((&hex!("6f62636465666768696a6b6c6d")[..]).to_vec().into()),
|
||||||
|
&hex!("8D6F62636465666768696A6B6C6D")[..],
|
||||||
|
),
|
||||||
|
(Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rlp_fixed_length() {
|
||||||
|
check_decode(vec![
|
||||||
|
(Ok(hex!("6f62636465666768696a6b6c6d")), &hex!("8D6F62636465666768696A6B6C6D")[..]),
|
||||||
|
(Err(DecodeError::UnexpectedLength), &hex!("8C6F62636465666768696A6B6C")[..]),
|
||||||
|
(Err(DecodeError::UnexpectedLength), &hex!("8E6F62636465666768696A6B6C6D6E")[..]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rlp_u64() {
|
||||||
|
check_decode(vec![
|
||||||
|
(Ok(9_u64), &hex!("09")[..]),
|
||||||
|
(Ok(0_u64), &hex!("80")[..]),
|
||||||
|
(Ok(0x0505_u64), &hex!("820505")[..]),
|
||||||
|
(Ok(0xCE05050505_u64), &hex!("85CE05050505")[..]),
|
||||||
|
(Err(DecodeError::Overflow), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("00")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
|
||||||
|
(
|
||||||
|
Err(DecodeError::Overflow),
|
||||||
|
&hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rlp_u256() {
|
||||||
|
check_decode(vec![
|
||||||
|
(Ok(9_u8.as_u256()), &hex!("09")[..]),
|
||||||
|
(Ok(0_u8.as_u256()), &hex!("80")[..]),
|
||||||
|
(Ok(0x0505_u16.as_u256()), &hex!("820505")[..]),
|
||||||
|
(Ok(0xCE05050505_u64.as_u256()), &hex!("85CE05050505")[..]),
|
||||||
|
(Ok(0xFFFFFFFFFFFFFFFFFF7C_u128.as_u256()), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("00")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
|
||||||
|
(
|
||||||
|
Err(DecodeError::Overflow),
|
||||||
|
&hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
#[test]
|
||||||
|
fn rlp_ethereum_types_u64() {
|
||||||
|
check_decode(vec![
|
||||||
|
(Ok(U64::from(9_u8)), &hex!("09")[..]),
|
||||||
|
(Ok(U64::from(0_u8)), &hex!("80")[..]),
|
||||||
|
(Ok(U64::from(0x0505_u16)), &hex!("820505")[..]),
|
||||||
|
(Ok(U64::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]),
|
||||||
|
(Err(DecodeError::Overflow), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("00")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
|
||||||
|
(
|
||||||
|
Err(DecodeError::Overflow),
|
||||||
|
&hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
#[test]
|
||||||
|
fn rlp_ethereum_types_u128() {
|
||||||
|
check_decode(vec![
|
||||||
|
(Ok(U128::from(9_u8)), &hex!("09")[..]),
|
||||||
|
(Ok(U128::from(0_u8)), &hex!("80")[..]),
|
||||||
|
(Ok(U128::from(0x0505_u16)), &hex!("820505")[..]),
|
||||||
|
(Ok(U128::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]),
|
||||||
|
(Ok(U128::from(0xFFFFFFFFFFFFFFFFFF7C_u128)), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("00")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
|
||||||
|
(
|
||||||
|
Err(DecodeError::Overflow),
|
||||||
|
&hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
#[test]
|
||||||
|
fn rlp_ethereum_types_u256() {
|
||||||
|
check_decode(vec![
|
||||||
|
(Ok(U256::from(9_u8)), &hex!("09")[..]),
|
||||||
|
(Ok(U256::from(0_u8)), &hex!("80")[..]),
|
||||||
|
(Ok(U256::from(0x0505_u16)), &hex!("820505")[..]),
|
||||||
|
(Ok(U256::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]),
|
||||||
|
(Ok(U256::from(0xFFFFFFFFFFFFFFFFFF7C_u128)), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
|
||||||
|
(Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("00")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
|
||||||
|
(
|
||||||
|
Err(DecodeError::Overflow),
|
||||||
|
&hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
#[test]
|
||||||
|
fn rlp_ethereum_types_u512() {
|
||||||
|
check_decode(vec![
|
||||||
|
(Ok(U512::from(9_u8)), &hex!("09")[..]),
|
||||||
|
(Ok(U512::from(0_u8)), &hex!("80")[..]),
|
||||||
|
(Ok(U512::from(0x0505_u16)), &hex!("820505")[..]),
|
||||||
|
(Ok(U512::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]),
|
||||||
|
(
|
||||||
|
Ok(U512::from(0xFFFFFFFFFFFFFFFFFF7C_u128)),
|
||||||
|
&hex!("8AFFFFFFFFFFFFFFFFFF7C")[..],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Err(DecodeError::InputTooShort),
|
||||||
|
&hex!("8BFFFFFFFFFFFFFFFFFF7C")[..],
|
||||||
|
),
|
||||||
|
(Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("00")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
|
||||||
|
(Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
|
||||||
|
(Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
|
||||||
|
(
|
||||||
|
Ok(U512::from_dec_str("115792089237316195423570985008687907853269984676653278628940326933415738736640").unwrap()),
|
||||||
|
&hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Err(DecodeError::Overflow),
|
||||||
|
&hex!("B84101000000000000000000000000000000000000008B000000000000000000000000000000000000000000000000000000000000008B000000000000000000000000")[..],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rlp_vectors() {
|
||||||
|
check_decode_list(vec![
|
||||||
|
(Ok(vec![]), &hex!("C0")[..]),
|
||||||
|
(Ok(vec![0xBBCCB5_u64, 0xFFC0B5_u64]), &hex!("C883BBCCB583FFC0B5")[..]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
501
crates/common/rlp/src/encode.rs
Normal file
501
crates/common/rlp/src/encode.rs
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
use crate::types::*;
|
||||||
|
use arrayvec::ArrayVec;
|
||||||
|
use auto_impl::auto_impl;
|
||||||
|
use bytes::{BufMut, Bytes, BytesMut};
|
||||||
|
use core::borrow::Borrow;
|
||||||
|
|
||||||
|
fn zeroless_view(v: &impl AsRef<[u8]>) -> &[u8] {
|
||||||
|
let v = v.as_ref();
|
||||||
|
&v[v.iter().take_while(|&&b| b == 0).count()..]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Header {
|
||||||
|
pub fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
if self.payload_length < 56 {
|
||||||
|
let code = if self.list { EMPTY_LIST_CODE } else { EMPTY_STRING_CODE };
|
||||||
|
out.put_u8(code + self.payload_length as u8);
|
||||||
|
} else {
|
||||||
|
let len_be = self.payload_length.to_be_bytes();
|
||||||
|
let len_be = zeroless_view(&len_be);
|
||||||
|
let code = if self.list { 0xF7 } else { 0xB7 };
|
||||||
|
out.put_u8(code + len_be.len() as u8);
|
||||||
|
out.put_slice(len_be);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn length_of_length(payload_length: usize) -> usize {
|
||||||
|
if payload_length < 56 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
1 + 8 - payload_length.leading_zeros() as usize / 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub const fn const_add(a: usize, b: usize) -> usize {
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub unsafe trait MaxEncodedLen<const LEN: usize>: Encodable {}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub unsafe trait MaxEncodedLenAssoc: Encodable {
|
||||||
|
const LEN: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use this to define length of an encoded entity
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// Invalid value can cause the encoder to crash.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! impl_max_encoded_len {
|
||||||
|
($t:ty, $len:block) => {
|
||||||
|
unsafe impl MaxEncodedLen<{ $len }> for $t {}
|
||||||
|
unsafe impl MaxEncodedLenAssoc for $t {
|
||||||
|
const LEN: usize = $len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[auto_impl(&)]
|
||||||
|
#[cfg_attr(feature = "alloc", auto_impl(Box, Arc))]
|
||||||
|
pub trait Encodable {
|
||||||
|
fn encode(&self, out: &mut dyn BufMut);
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
let mut out = BytesMut::new();
|
||||||
|
self.encode(&mut out);
|
||||||
|
out.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Encodable for &'a [u8] {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
let mut len = self.len();
|
||||||
|
if self.len() != 1 || self[0] >= EMPTY_STRING_CODE {
|
||||||
|
len += length_of_length(self.len());
|
||||||
|
}
|
||||||
|
len
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
if self.len() != 1 || self[0] >= EMPTY_STRING_CODE {
|
||||||
|
Header { list: false, payload_length: self.len() }.encode(out);
|
||||||
|
}
|
||||||
|
out.put_slice(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const LEN: usize> Encodable for [u8; LEN] {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
(self as &[u8]).length()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
(self as &[u8]).encode(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<const LEN: usize> MaxEncodedLenAssoc for [u8; LEN] {
|
||||||
|
const LEN: usize = LEN + length_of_length(LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! encodable_uint {
|
||||||
|
($t:ty) => {
|
||||||
|
#[allow(clippy::cmp_owned)]
|
||||||
|
impl Encodable for $t {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
if *self < <$t>::from(EMPTY_STRING_CODE) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
1 + (<$t>::BITS as usize / 8) - (self.leading_zeros() as usize / 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
if *self == 0 {
|
||||||
|
out.put_u8(EMPTY_STRING_CODE);
|
||||||
|
} else if *self < <$t>::from(EMPTY_STRING_CODE) {
|
||||||
|
out.put_u8(u8::try_from(*self).unwrap());
|
||||||
|
} else {
|
||||||
|
let be = self.to_be_bytes();
|
||||||
|
let be = zeroless_view(&be);
|
||||||
|
out.put_u8(EMPTY_STRING_CODE + be.len() as u8);
|
||||||
|
out.put_slice(be);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! max_encoded_len_uint {
|
||||||
|
($t:ty) => {
|
||||||
|
impl_max_encoded_len!($t, {
|
||||||
|
length_of_length(<$t>::MAX.to_be_bytes().len()) + <$t>::MAX.to_be_bytes().len()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
encodable_uint!(usize);
|
||||||
|
max_encoded_len_uint!(usize);
|
||||||
|
|
||||||
|
encodable_uint!(u8);
|
||||||
|
max_encoded_len_uint!(u8);
|
||||||
|
|
||||||
|
encodable_uint!(u16);
|
||||||
|
max_encoded_len_uint!(u16);
|
||||||
|
|
||||||
|
encodable_uint!(u32);
|
||||||
|
max_encoded_len_uint!(u32);
|
||||||
|
|
||||||
|
encodable_uint!(u64);
|
||||||
|
max_encoded_len_uint!(u64);
|
||||||
|
|
||||||
|
encodable_uint!(u128);
|
||||||
|
max_encoded_len_uint!(u128);
|
||||||
|
|
||||||
|
impl Encodable for bool {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
(*self as u8).length()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
(*self as u8).encode(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_max_encoded_len!(bool, { <u8 as MaxEncodedLenAssoc>::LEN });
|
||||||
|
|
||||||
|
#[cfg(feature = "ethnum")]
|
||||||
|
mod ethnum_support {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
encodable_uint!(ethnum::U256);
|
||||||
|
impl_max_encoded_len!(ethnum::U256, { length_of_length(32) + 32 });
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
mod ethereum_types_support {
|
||||||
|
use super::*;
|
||||||
|
use ethereum_types::*;
|
||||||
|
|
||||||
|
macro_rules! fixed_hash_impl {
|
||||||
|
($t:ty) => {
|
||||||
|
impl Encodable for $t {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
self.0.length()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||||
|
self.0.encode(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl_max_encoded_len!($t, { length_of_length(<$t>::len_bytes()) + <$t>::len_bytes() });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed_hash_impl!(H64);
|
||||||
|
fixed_hash_impl!(H128);
|
||||||
|
fixed_hash_impl!(H160);
|
||||||
|
fixed_hash_impl!(H256);
|
||||||
|
fixed_hash_impl!(H512);
|
||||||
|
fixed_hash_impl!(H520);
|
||||||
|
//TODO fixed_hash_impl!(Bloom);
|
||||||
|
|
||||||
|
macro_rules! fixed_uint_impl {
|
||||||
|
($t:ty, $n_bytes:tt) => {
|
||||||
|
impl Encodable for $t {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
if *self < <$t>::from(EMPTY_STRING_CODE) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
1 + $n_bytes - (self.leading_zeros() as usize / 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||||
|
let mut temp_arr = [0u8; $n_bytes];
|
||||||
|
self.to_big_endian(&mut temp_arr[..]);
|
||||||
|
// cut the leading zeros after converting to big endian
|
||||||
|
let sliced = &temp_arr[(self.leading_zeros() / 8) as usize..];
|
||||||
|
sliced.encode(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed_uint_impl!(U64, 8);
|
||||||
|
fixed_uint_impl!(U128, 16);
|
||||||
|
fixed_uint_impl!(U256, 32);
|
||||||
|
fixed_uint_impl!(U512, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! slice_impl {
|
||||||
|
($t:ty) => {
|
||||||
|
impl $crate::Encodable for $t {
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
(&self[..]).length()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, out: &mut dyn bytes::BufMut) {
|
||||||
|
(&self[..]).encode(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
mod alloc_support {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
impl<T> Encodable for ::alloc::vec::Vec<T>
|
||||||
|
where
|
||||||
|
T: Encodable,
|
||||||
|
{
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
list_length(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
encode_list(self, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for ::alloc::string::String {
|
||||||
|
fn encode(&self, out: &mut dyn BufMut) {
|
||||||
|
self.as_bytes().encode(out);
|
||||||
|
}
|
||||||
|
fn length(&self) -> usize {
|
||||||
|
self.as_bytes().length()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slice_impl!(Bytes);
|
||||||
|
slice_impl!(BytesMut);
|
||||||
|
|
||||||
|
fn rlp_list_header<E, K>(v: &[K]) -> Header
|
||||||
|
where
|
||||||
|
E: Encodable + ?Sized,
|
||||||
|
K: Borrow<E>,
|
||||||
|
{
|
||||||
|
let mut h = Header { list: true, payload_length: 0 };
|
||||||
|
for x in v {
|
||||||
|
h.payload_length += x.borrow().length();
|
||||||
|
}
|
||||||
|
h
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_length<E, K>(v: &[K]) -> usize
|
||||||
|
where
|
||||||
|
E: Encodable,
|
||||||
|
K: Borrow<E>,
|
||||||
|
{
|
||||||
|
let payload_length = rlp_list_header(v).payload_length;
|
||||||
|
length_of_length(payload_length) + payload_length
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode_list<E, K>(v: &[K], out: &mut dyn BufMut)
|
||||||
|
where
|
||||||
|
E: Encodable + ?Sized,
|
||||||
|
K: Borrow<E>,
|
||||||
|
{
|
||||||
|
let h = rlp_list_header(v);
|
||||||
|
h.encode(out);
|
||||||
|
for x in v {
|
||||||
|
x.borrow().encode(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode_fixed_size<E: MaxEncodedLen<LEN>, const LEN: usize>(v: &E) -> ArrayVec<u8, LEN> {
|
||||||
|
let mut out = ArrayVec::from([0_u8; LEN]);
|
||||||
|
|
||||||
|
let mut s = out.as_mut_slice();
|
||||||
|
|
||||||
|
v.encode(&mut s);
|
||||||
|
|
||||||
|
let final_len = LEN - s.len();
|
||||||
|
out.truncate(final_len);
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use alloc::vec;
|
||||||
|
use bytes::BytesMut;
|
||||||
|
use hex_literal::hex;
|
||||||
|
|
||||||
|
fn encoded<T: Encodable>(t: T) -> BytesMut {
|
||||||
|
let mut out = BytesMut::new();
|
||||||
|
t.encode(&mut out);
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encoded_list<T: Encodable + Clone>(t: &[T]) -> BytesMut {
|
||||||
|
let mut out1 = BytesMut::new();
|
||||||
|
encode_list(t, &mut out1);
|
||||||
|
|
||||||
|
let v = t.to_vec();
|
||||||
|
assert_eq!(out1.len(), v.length());
|
||||||
|
|
||||||
|
let mut out2 = BytesMut::new();
|
||||||
|
v.encode(&mut out2);
|
||||||
|
assert_eq!(out1, out2);
|
||||||
|
|
||||||
|
out1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rlp_strings() {
|
||||||
|
assert_eq!(encoded(hex!(""))[..], hex!("80")[..]);
|
||||||
|
assert_eq!(encoded(hex!("7B"))[..], hex!("7b")[..]);
|
||||||
|
assert_eq!(encoded(hex!("80"))[..], hex!("8180")[..]);
|
||||||
|
assert_eq!(encoded(hex!("ABBA"))[..], hex!("82abba")[..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u8_fixtures() -> impl IntoIterator<Item = (u8, &'static [u8])> {
|
||||||
|
vec![
|
||||||
|
(0, &hex!("80")[..]),
|
||||||
|
(1, &hex!("01")[..]),
|
||||||
|
(0x7F, &hex!("7F")[..]),
|
||||||
|
(0x80, &hex!("8180")[..]),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c<T, U: From<T>>(
|
||||||
|
it: impl IntoIterator<Item = (T, &'static [u8])>,
|
||||||
|
) -> impl Iterator<Item = (U, &'static [u8])> {
|
||||||
|
it.into_iter().map(|(k, v)| (k.into(), v))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u16_fixtures() -> impl IntoIterator<Item = (u16, &'static [u8])> {
|
||||||
|
c(u8_fixtures()).chain(vec![(0x400, &hex!("820400")[..])])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u32_fixtures() -> impl IntoIterator<Item = (u32, &'static [u8])> {
|
||||||
|
c(u16_fixtures())
|
||||||
|
.chain(vec![(0xFFCCB5, &hex!("83ffccb5")[..]), (0xFFCCB5DD, &hex!("84ffccb5dd")[..])])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u64_fixtures() -> impl IntoIterator<Item = (u64, &'static [u8])> {
|
||||||
|
c(u32_fixtures()).chain(vec![
|
||||||
|
(0xFFCCB5DDFF, &hex!("85ffccb5ddff")[..]),
|
||||||
|
(0xFFCCB5DDFFEE, &hex!("86ffccb5ddffee")[..]),
|
||||||
|
(0xFFCCB5DDFFEE14, &hex!("87ffccb5ddffee14")[..]),
|
||||||
|
(0xFFCCB5DDFFEE1483, &hex!("88ffccb5ddffee1483")[..]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u128_fixtures() -> impl IntoIterator<Item = (u128, &'static [u8])> {
|
||||||
|
c(u64_fixtures()).chain(vec![(
|
||||||
|
0x10203E405060708090A0B0C0D0E0F2,
|
||||||
|
&hex!("8f10203e405060708090a0b0c0d0e0f2")[..],
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethnum")]
|
||||||
|
fn u256_fixtures() -> impl IntoIterator<Item = (ethnum::U256, &'static [u8])> {
|
||||||
|
c(u128_fixtures()).chain(vec![(
|
||||||
|
ethnum::U256::from_str_radix(
|
||||||
|
"0100020003000400050006000700080009000A0B4B000C000D000E01",
|
||||||
|
16,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
&hex!("9c0100020003000400050006000700080009000a0b4b000c000d000e01")[..],
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
fn eth_u64_fixtures() -> impl IntoIterator<Item = (ethereum_types::U64, &'static [u8])> {
|
||||||
|
c(u64_fixtures()).chain(vec![
|
||||||
|
(
|
||||||
|
ethereum_types::U64::from_str_radix("FFCCB5DDFF", 16).unwrap(),
|
||||||
|
&hex!("85ffccb5ddff")[..],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ethereum_types::U64::from_str_radix("FFCCB5DDFFEE", 16).unwrap(),
|
||||||
|
&hex!("86ffccb5ddffee")[..],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ethereum_types::U64::from_str_radix("FFCCB5DDFFEE14", 16).unwrap(),
|
||||||
|
&hex!("87ffccb5ddffee14")[..],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ethereum_types::U64::from_str_radix("FFCCB5DDFFEE1483", 16).unwrap(),
|
||||||
|
&hex!("88ffccb5ddffee1483")[..],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
fn eth_u128_fixtures() -> impl IntoIterator<Item = (ethereum_types::U128, &'static [u8])> {
|
||||||
|
c(u128_fixtures()).chain(vec![(
|
||||||
|
ethereum_types::U128::from_str_radix("10203E405060708090A0B0C0D0E0F2", 16).unwrap(),
|
||||||
|
&hex!("8f10203e405060708090a0b0c0d0e0f2")[..],
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
fn eth_u256_fixtures() -> impl IntoIterator<Item = (ethereum_types::U256, &'static [u8])> {
|
||||||
|
c(u128_fixtures()).chain(vec![(
|
||||||
|
ethereum_types::U256::from_str_radix(
|
||||||
|
"0100020003000400050006000700080009000A0B4B000C000D000E01",
|
||||||
|
16,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
&hex!("9c0100020003000400050006000700080009000a0b4b000c000d000e01")[..],
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
fn eth_u512_fixtures() -> impl IntoIterator<Item = (ethereum_types::U512, &'static [u8])> {
|
||||||
|
c(eth_u256_fixtures()).chain(vec![(
|
||||||
|
ethereum_types::U512::from_str_radix(
|
||||||
|
"0100020003000400050006000700080009000A0B4B000C000D000E010100020003000400050006000700080009000A0B4B000C000D000E01",
|
||||||
|
16,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
&hex!("b8380100020003000400050006000700080009000A0B4B000C000D000E010100020003000400050006000700080009000A0B4B000C000D000E01")[..],
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! uint_rlp_test {
|
||||||
|
($fixtures:expr) => {
|
||||||
|
for (input, output) in $fixtures {
|
||||||
|
assert_eq!(encoded(input), output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rlp_uints() {
|
||||||
|
uint_rlp_test!(u8_fixtures());
|
||||||
|
uint_rlp_test!(u16_fixtures());
|
||||||
|
uint_rlp_test!(u32_fixtures());
|
||||||
|
uint_rlp_test!(u64_fixtures());
|
||||||
|
uint_rlp_test!(u128_fixtures());
|
||||||
|
#[cfg(feature = "ethnum")]
|
||||||
|
uint_rlp_test!(u256_fixtures());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ethereum-types")]
|
||||||
|
#[test]
|
||||||
|
fn rlp_eth_uints() {
|
||||||
|
uint_rlp_test!(eth_u64_fixtures());
|
||||||
|
uint_rlp_test!(eth_u128_fixtures());
|
||||||
|
uint_rlp_test!(eth_u256_fixtures());
|
||||||
|
uint_rlp_test!(eth_u512_fixtures());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rlp_list() {
|
||||||
|
assert_eq!(encoded_list::<u64>(&[]), &hex!("c0")[..]);
|
||||||
|
assert_eq!(encoded_list(&[0xFFCCB5_u64, 0xFFC0B5_u64]), &hex!("c883ffccb583ffc0b5")[..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
crates/common/rlp/src/lib.rs
Normal file
22
crates/common/rlp/src/lib.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
mod decode;
|
||||||
|
mod encode;
|
||||||
|
mod types;
|
||||||
|
|
||||||
|
pub use bytes::BufMut;
|
||||||
|
|
||||||
|
pub use decode::{Decodable, DecodeError, Rlp};
|
||||||
|
pub use encode::{
|
||||||
|
const_add, encode_fixed_size, encode_list, length_of_length, list_length, Encodable,
|
||||||
|
MaxEncodedLen, MaxEncodedLenAssoc,
|
||||||
|
};
|
||||||
|
pub use types::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "derive")]
|
||||||
|
pub use reth_rlp_derive::{
|
||||||
|
RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper, RlpMaxEncodedLen,
|
||||||
|
};
|
||||||
8
crates/common/rlp/src/types.rs
Normal file
8
crates/common/rlp/src/types.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#[derive(Clone, Default, PartialEq)]
|
||||||
|
pub struct Header {
|
||||||
|
pub list: bool,
|
||||||
|
pub payload_length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const EMPTY_STRING_CODE: u8 = 0x80;
|
||||||
|
pub const EMPTY_LIST_CODE: u8 = 0xC0;
|
||||||
92
crates/common/rlp/tests/rlp.rs
Normal file
92
crates/common/rlp/tests/rlp.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
use bytes::{Bytes, BytesMut};
|
||||||
|
use ethnum::U256;
|
||||||
|
use hex_literal::hex;
|
||||||
|
use reth_rlp::{DecodeError, *};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)]
|
||||||
|
struct Item {
|
||||||
|
a: Bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable, RlpMaxEncodedLen)]
|
||||||
|
struct Test4Numbers {
|
||||||
|
a: u8,
|
||||||
|
b: u64,
|
||||||
|
c: U256,
|
||||||
|
d: U256,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, RlpEncodableWrapper, RlpDecodableWrapper)]
|
||||||
|
pub struct W(Test4Numbers);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, RlpEncodable)]
|
||||||
|
struct Test4NumbersGenerics<'a, D: Encodable> {
|
||||||
|
a: u8,
|
||||||
|
b: u64,
|
||||||
|
c: &'a U256,
|
||||||
|
d: &'a D,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encoded<T: Encodable>(t: &T) -> BytesMut {
|
||||||
|
let mut out = BytesMut::new();
|
||||||
|
t.encode(&mut out);
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_encode_item() {
|
||||||
|
let item = Item { a: b"dog".to_vec().into() };
|
||||||
|
|
||||||
|
let expected = vec![0xc4, 0x83, b'd', b'o', b'g'];
|
||||||
|
let out = encoded(&item);
|
||||||
|
assert_eq!(&*out, expected);
|
||||||
|
|
||||||
|
let decoded = Decodable::decode(&mut &*expected).expect("decode failure");
|
||||||
|
assert_eq!(item, decoded);
|
||||||
|
|
||||||
|
let item = Test4Numbers {
|
||||||
|
a: 0x05,
|
||||||
|
b: 0xdeadbeefbaadcafe,
|
||||||
|
c: U256::from_be_bytes(hex!(
|
||||||
|
"56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
|
||||||
|
)),
|
||||||
|
d: U256::from_be_bytes(hex!(
|
||||||
|
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected = hex!("f84c0588deadbeefbaadcafea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").to_vec();
|
||||||
|
let out = encoded(&item);
|
||||||
|
assert_eq!(&*out, expected);
|
||||||
|
|
||||||
|
let out = reth_rlp::encode_fixed_size(&item);
|
||||||
|
assert_eq!(&*out, expected);
|
||||||
|
|
||||||
|
let decoded = Decodable::decode(&mut &*expected).unwrap();
|
||||||
|
assert_eq!(item, decoded);
|
||||||
|
|
||||||
|
let mut rlp_view = Rlp::new(&*expected).unwrap();
|
||||||
|
assert_eq!(rlp_view.get_next().unwrap(), Some(item.a));
|
||||||
|
assert_eq!(rlp_view.get_next().unwrap(), Some(item.b));
|
||||||
|
assert_eq!(rlp_view.get_next().unwrap(), Some(item.c));
|
||||||
|
assert_eq!(rlp_view.get_next().unwrap(), Some(item.d));
|
||||||
|
assert_eq!(rlp_view.get_next::<Bytes>().unwrap(), None);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
encoded(&Test4NumbersGenerics { a: item.a, b: item.b, c: &item.c, d: &item.d }),
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(encoded(&W(item)), expected);
|
||||||
|
assert_eq!(W::decode(&mut &*expected).unwrap().0, decoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_decode_sideeffect() {
|
||||||
|
let fixture = hex!("f84d0588deadbeefbaadcafea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
||||||
|
let mut sl: &[u8] = &fixture;
|
||||||
|
|
||||||
|
assert_eq!(Test4Numbers::decode(&mut sl), Err(DecodeError::InputTooShort));
|
||||||
|
|
||||||
|
assert_eq!(sl.len(), fixture.len());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user