feat(evm-core): secp256k1 derivation, EIP-55 addresses, signing - #233
Open
Lost-Z wants to merge 1 commit into
Open
feat(evm-core): secp256k1 derivation, EIP-55 addresses, signing#233Lost-Z wants to merge 1 commit into
Lost-Z wants to merge 1 commit into
Conversation
Adds BIP-44 m/44'/60'/0'/0/i derivation, keccak-256 address encoding with EIP-55 checksum validation, and low-s normalised signing (EIP-2). Seals reuse octo-crypto with a chain-scoped AAD context so an EVM key cannot be opened in a Stellar context. Verified against BIP-32 vectors 1-2 and the full EIP-55 example set. Adds an ADR in docs/architecture.md for the k256+sha3 vs. alloy-primitives crate-selection decision (MSRV 1.84.1 and cargo-deny surface). Closes Octo-Protocol-org#217
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
crates/evm-core(octo-evm-core): the EVM counterpart ofocto-wallet-core, providing the secp256k1 key/address/signing primitives this epic's later crates build on.derive.rs: BIP-32/BIP-44 secp256k1 derivation atm/44'/60'/0'/0/{index}from the same BIP-39 mnemonic type already used for Stellar — note the non-hardenedchange/address_indextail (unlike SEP-0005's all-hardened path). Module docs spell out the consequence prominently: a leaked non-hardened child private key + the account xpub recovers the whole sub-tree, which feat(store): EVM per-customer deposit addresses via HD derivation #220 and feat(wallet): EVM deposit sweep engine #224 need to build around.address.rs: keccak-256 → 20-byte address, EIP-55 mixed-case checksum encode/validate (accepts all-lower, all-upper, correct mixed-case; rejects a wrong mixed-case checksum without ever lowercasing before comparing, so the typo-detection property is preserved).signer.rs: sign a 32-byte digest →(r, s, v)with EIP-2 low-s normalisation, plus signer-address recovery. Mirrorswallet-core/src/signer.rs's "no raw-XDR oracle" posture — it signs a caller-supplied digest, not an arbitrary/variable-length payload.chain_adapter.rs:EvmAdapter+ a localchain_conformance_suitestand-in for feat(chain): Introduce the octo-chain adapter trait and refactor Stellar behind it #213'sChainAdaptertrait (feat(chain): Introduce the octo-chain adapter trait and refactor Stellar behind it #213 hadn't landed yet — see the module docs for the exact swap-over plan once it does).octo-cryptofor sealing unchanged (no second encryption scheme); the AAD context is"octo:eip155:<chain>", so a sealed EVM key cannot be opened under a Stellar context or a different EVM chain's context.docs/architecture.mdfor the crate-selection decision (k256 + sha3 + a from-scratch BIP-32 walk, vs.alloy-primitives), covering the MSRV 1.84.1 constraint and thecargo denylicense/bans surface.Security-sensitive: full lint wall (
#![forbid(unsafe_code)], deniesunwrap/expect/panic/lossy casts outside tests), constant-time scalar validation in the BIP-32 walk, zeroize-on-drop for seeds and derived secrets.Test plan
cargo test -p octo-evm-core— 32 tests: BIP-32 Test Vectors 1 & 2 (decoded from the spec's own base58checkxprvstrings, not hand-transcribed), the full EIP-55 spec example set plus negative (bad-checksum) cases, a mnemonic→address vector cross-checked against independent Pythoneth-account/eth-keysand Nodeethers.jsv6 output, signature vectors with an explicit low-s assertion, round-trip sign→recover, zeroize-on-drop for both the seed and a derived secret, and seal/open context-isolation (EVM↔Stellar, and EVM chain↔chain).cargo clippy -p octo-evm-core --all-targets -- -D warnings(default features and--features test-fixtures) — clean.cargo fmt --check— clean.cargo clippy --workspace --all-targets --locked -- -D warningsandcargo test --workspace --locked— clean, no regressions elsewhere.cargo deny check licenses bans sources— no new license/ban issues from this crate's dependencies (k256,sha3,subtle,bs58).licensesreports one pre-existing failure (webpki-roots'sCDLA-Permissive-2.0, pulled transitively viareqwest/sqlx, already present onmainbefore this PR);advisoriescurrently can't run at all in this environment due to a CVSS-4.0 parsing incompatibility between the availablecargo-deny0.17 (the newest build compatible with the 1.84.1 MSRV pin) and a current RUSTSEC entry — both pre-existing environment/tooling issues, unrelated to this change.Closes #217