Repository navigation
feat(node): accept a CLT transfer signed by MetaMask - #26
Merged
Merged
Conversation
…ransaction A wallet can only send a coin by signing a legacy Ethereum transaction (EIP-155). New type WalletTransfer (RLP tag 10) keeps every field that signature covers, so any node can rebuild the signed bytes and check them; its hash is the Ethereum hash. New RPC send_wallet_transaction and get_transaction_by_hash, for the Hub's /rpc. Consensus change, off unless wallet_chain_id and wallet_transfers_from_block are set: without them, or below that block, the type is refused in the pool and in blocks. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_0152exeqGYmUeykE5Z5AsHtm
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.
Requested by Mehran · project thread
📋 Description
Before: MetaMask shows a CLT balance, but the node rejects anything a wallet can send, because a wallet only sends by signing a legacy Ethereum transaction.
After: the node accepts that signed transaction as a new type,
WalletTransfer(RLP tag 10), and applies it exactly like aTransferwith the flattx_fee. Nothing changes until the chain switches it on.How:
transactions/wallet_transfer.rsdecodes the raw EIP-155 legacy transaction, recoversfrom, and keeps every field the signature covers (to, value, gas_price, gas_limit, wallet_chain_id), so any node can rebuild the signed bytes and verify them. Clutch nonce = wallet nonce + 1. Value = wei / 10^12; more than 6 decimals is refused, never rounded. Refused: data, contract creation, typed (EIP-1559) txs, no chain id, highs, non-canonical encoding.gas_price × gas_limitmust covertx_feein wei;wallet_chain_idmust equal the node's.send_wallet_transaction(raw hex →{hash}) andget_transaction_by_hash({transaction, block_index, block_hash}, block fields null while pooled).wallet_chain_id+wallet_transfers_from_block(both or neither; the node refuses to start with one). Unset, or below that block, the type is refused in the pool and in blocks. Every validator must carry the same values before the block. The rule sits onDatabasebecause every validation path holds it.🔗 Related Issues
/rpcside), clutch-deploy (stage config), clutch-explorer, clutch-docs PRs on the same branch name.🎯 Type of Change
🧪 Testing
cargo test -- --test-threads=1, whole suite green)wallet.sendTransactionof 1.25 CLT through/rpcreturned a receipt with status 1, fee 0.001, balances moved; 1 wei refused with the 6-decimals messagetests/wallet_transfer.rs(fixtures signed by ethers, pool → block → lookup by hash, rule off / before activation / other wallet chain id / tampered / insufficient balance, and a peer without the rule refusing the block after an RLP round trip) plus unit tests inwallet_transfer.rs🔒 Security Checklist
wallet_chain_id)✅ Checklist
Merging moves the stage node pin; with no rule in config the stage chain behaves exactly as today. Mainnet is untouched (its pins move by hand).
🤖 Generated with Claude Code
https://claude.ai/code/session_0152exeqGYmUeykE5Z5AsHtm
Generated by Claude Code