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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.65"
|
||||
@ -34,7 +40,7 @@ version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a941c39708478e8eea39243b5983f1c42d2717b3620ee91f4a52115fd02ac43f"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"itertools 0.9.0",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -232,6 +238,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
@ -263,6 +275,33 @@ dependencies = [
|
||||
"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]]
|
||||
name = "clang-sys"
|
||||
version = "1.4.0"
|
||||
@ -274,6 +313,18 @@ dependencies = [
|
||||
"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]]
|
||||
name = "clap"
|
||||
version = "4.0.14"
|
||||
@ -283,7 +334,7 @@ dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"clap_lex 0.3.0",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
@ -302,6 +353,15 @@ dependencies = [
|
||||
"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]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.0"
|
||||
@ -357,6 +417,85 @@ dependencies = [
|
||||
"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]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
@ -491,7 +630,7 @@ version = "17.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b"
|
||||
dependencies = [
|
||||
"ethereum-types",
|
||||
"ethereum-types 0.13.1",
|
||||
"hex",
|
||||
"once_cell",
|
||||
"regex",
|
||||
@ -509,7 +648,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
"fixed-hash",
|
||||
"fixed-hash 0.7.0",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"tiny-keccak",
|
||||
@ -524,7 +663,7 @@ dependencies = [
|
||||
"crc",
|
||||
"fastrlp",
|
||||
"maplit",
|
||||
"primitive-types",
|
||||
"primitive-types 0.11.1",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
@ -535,10 +674,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6"
|
||||
dependencies = [
|
||||
"ethbloom",
|
||||
"fixed-hash",
|
||||
"fixed-hash 0.7.0",
|
||||
"impl-rlp",
|
||||
"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",
|
||||
]
|
||||
|
||||
@ -568,6 +718,12 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethnum"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eac3c0b9fa6eb75255ebb42c0ba3e2210d102a66d2795afef6fed668f373311"
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.3"
|
||||
@ -602,7 +758,7 @@ dependencies = [
|
||||
"arrayvec",
|
||||
"auto_impl",
|
||||
"bytes",
|
||||
"ethereum-types",
|
||||
"ethereum-types 0.13.1",
|
||||
"fastrlp-derive",
|
||||
]
|
||||
|
||||
@ -640,6 +796,17 @@ dependencies = [
|
||||
"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]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@ -866,6 +1033,12 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
@ -1057,6 +1230,15 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.3"
|
||||
@ -1368,6 +1550,15 @@ version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@ -1509,6 +1700,12 @@ version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
@ -1640,6 +1837,34 @@ dependencies = [
|
||||
"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]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
@ -1652,13 +1877,23 @@ version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a"
|
||||
dependencies = [
|
||||
"fixed-hash",
|
||||
"fixed-hash 0.7.0",
|
||||
"impl-codec",
|
||||
"impl-rlp",
|
||||
"impl-serde",
|
||||
"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]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.2.1"
|
||||
@ -1748,6 +1983,30 @@ dependencies = [
|
||||
"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]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
@ -1787,7 +2046,7 @@ dependencies = [
|
||||
name = "reth"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap 4.0.14",
|
||||
"eyre",
|
||||
"reth-primitives",
|
||||
"serde",
|
||||
@ -1878,6 +2137,31 @@ dependencies = [
|
||||
"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]]
|
||||
name = "reth-rpc"
|
||||
version = "0.1.0"
|
||||
@ -1954,7 +2238,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"hashbrown",
|
||||
"num_enum",
|
||||
"primitive-types",
|
||||
"primitive-types 0.11.1",
|
||||
"revm_precompiles",
|
||||
"rlp",
|
||||
"sha3",
|
||||
@ -1970,7 +2254,7 @@ dependencies = [
|
||||
"hashbrown",
|
||||
"num",
|
||||
"once_cell",
|
||||
"primitive-types",
|
||||
"primitive-types 0.11.1",
|
||||
"ripemd",
|
||||
"secp256k1",
|
||||
"sha2",
|
||||
@ -2444,6 +2728,12 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
@ -2473,6 +2763,16 @@ dependencies = [
|
||||
"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]]
|
||||
name = "tokio"
|
||||
version = "1.21.2"
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
members = [
|
||||
"bin/reth",
|
||||
"crate-template",
|
||||
"crates/common/rlp",
|
||||
"crates/common/rlp-derive",
|
||||
"crates/db",
|
||||
"crates/executor",
|
||||
"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