From f54e59e61be4144398f6b6754875154a4db7888f Mon Sep 17 00:00:00 2001 From: Shreyash Date: Sat, 12 Jul 2025 22:23:10 +0530 Subject: [PATCH 1/3] feat: add mnemonic signer for hardware wallet support (Fix #6) --- .github/workflows/release.yml | 13 +- README.md | 112 ++++++++---- Screenshot 2025-07-12 205643.png | Bin 0 -> 11438 bytes Screenshot 2025-07-12 205709.png | Bin 0 -> 18209 bytes go.mod | 4 + go.sum | 23 ++- scripts/sign_mnemonic.go | 299 +++++++++++++++++++++++++++++++ 7 files changed, 416 insertions(+), 35 deletions(-) create mode 100644 Screenshot 2025-07-12 205643.png create mode 100644 Screenshot 2025-07-12 205709.png create mode 100644 scripts/sign_mnemonic.go diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0dc28a2..2d53830 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,21 +34,30 @@ jobs: fi go build -o $PECTRA_BINARY_NAME cmd/main.go - # Build signer + # Build private key signer SIGNER_BINARY_NAME="signer" if [ "${{ matrix.goos }}" = "windows" ]; then SIGNER_BINARY_NAME="${SIGNER_BINARY_NAME}.exe" fi go build -o $SIGNER_BINARY_NAME scripts/sign.go + # Build mnemonic signer + MNEMONIC_SIGNER_BINARY_NAME="sign-mnemonic" + if [ "${{ matrix.goos }}" = "windows" ]; then + MNEMONIC_SIGNER_BINARY_NAME="${MNEMONIC_SIGNER_BINARY_NAME}.exe" + fi + go build -o $MNEMONIC_SIGNER_BINARY_NAME scripts/sign_mnemonic.go + # Create dist directory and move binaries mkdir -p dist if [ "${{ matrix.goos }}" = "windows" ]; then mv $PECTRA_BINARY_NAME "dist/pectra-cli-${{ matrix.goos }}-${{ matrix.goarch }}.exe" mv $SIGNER_BINARY_NAME "dist/signer-${{ matrix.goos }}-${{ matrix.goarch }}.exe" + mv $MNEMONIC_SIGNER_BINARY_NAME "dist/sign-mnemonic-${{ matrix.goos }}-${{ matrix.goarch }}.exe" else mv $PECTRA_BINARY_NAME "dist/pectra-cli-${{ matrix.goos }}-${{ matrix.goarch }}" mv $SIGNER_BINARY_NAME "dist/signer-${{ matrix.goos }}-${{ matrix.goarch }}" + mv $MNEMONIC_SIGNER_BINARY_NAME "dist/sign-mnemonic-${{ matrix.goos }}-${{ matrix.goarch }}" fi - name: Create Release @@ -58,4 +67,4 @@ jobs: files: dist/* generate_release_notes: true env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index 18869d7..5acdb7a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A powerful airgapped CLI tool for executing Ethereum validator operations including consolidation, switching, and both partial and full withdrawals with seamless batching enabled by EIP-7702. -# Background +## Background The Pectra upgrade (Prague + Electra) introduces key validator enhancements: consolidation allows merging multiple validators into one to simplify management and reduce overhead; switch enables validators to update their BLS keys, supporting strategies like autocompounding without needing to exit and re-enter; and execution layer exits allow validators to exit directly via the execution layer, streamlining the exit process and enabling better integration with smart contracts and tooling. @@ -28,15 +28,19 @@ Moreover, the CLI is designed to be airgapped, ensuring security by allowing use ## Installation -1. Ensure you have Go (version 1.21+ recommended, as per `.github/workflows/release.yml` line 18) installed on your system. -2. Clone the repository (if you haven't already). -3. Build the CLI tool: +1. Ensure you have Go (version 1.21+ recommended, as per .github/workflows/release.yml line 18) installed on your system. +2. Clone the repository (if you haven't already). +3. Build the CLI tool and mnemonic signer: ```bash + # Build main CLI go build -o pectra-cli ./cmd/main.go + + # Build mnemonic signer + go build -o sign-mnemonic scripts/sign_mnemonic.go ``` - - This will create an executable file named `pectra-cli` in the current directory. + + This will create two executables: pectra-cli and sign-mnemonic in the current directory. ## Deployed Contracts - Mainnet - [0x17c11FDdADac2b341F2455aFe988fec4c3ba26e3](https://etherscan.io/address/0x17c11FDdADac2b341F2455aFe988fec4c3ba26e3) @@ -44,9 +48,9 @@ Moreover, the CLI is designed to be airgapped, ensuring security by allowing use ## Configuration -Create a JSON configuration file named `config.json` in the same directory as the `pectra-cli` executable. You can use `sample_config.json` as a template. +Create a JSON configuration file named config.json in the same directory as the pectra-cli executable. You can use sample_config.json as a template. -**Example `config.json`:** +**Example config.json:** ```json { @@ -98,17 +102,52 @@ Create a JSON configuration file named `config.json` in the same directory as th ## Private Key Handling -Use the `--airgapped` or `-a` to run the CLI in airgapped mode; alternatively, omit the flag to sign directly in the CLI by providing the private key. The CLI will securely prompt you to enter it at runtime when an operation is initiated. -(See `internal/config/config.go` lines 88-114) +The CLI supports multiple secure signing methods: + +### 1. Airgapped Mode (Recommended) +Use the `--airgapped` or `-a` flag to generate unsigned transactions that can be signed later: + +```bash +./pectra-cli switch -c config.json -a +``` + +This creates an `unsigned_txn.json` file that can be signed using either: + +#### A) Private Key Signing +```bash +go run scripts/sign.go unsigned_txn.json +``` + +#### B) Mnemonic Phrase Signing +```bash +./sign-mnemonic unsigned_txn.json +``` + +The mnemonic signer will prompt for: +- Your BIP-39 seed phrase (12, 15, 18, 21, or 24 words) +- Derivation path (default: m/44'/60'/0'/0/0) + +Supported derivation paths: +- Standard Ethereum: m/44'/60'/0'/0/0 (default) +- Ledger Live: m/44'/60'/0'/0/0 +- MEW/MyCrypto: m/44'/60'/0'/0 +- Custom accounts: m/44'/60'/0'/0/[index] + +### 2. Direct Signing +For convenience, you can sign directly by providing the private key when prompted (not recommended for production use): + +```bash +./pectra-cli switch -c config.json +``` -⚠️ Ensure that correct private keys are provided for the validators — otherwise, transactions will succeed but no validator operation will occur, wasting gas.

+⚠ Ensure that correct private keys are provided for the validators — otherwise, transactions will succeed but no validator operation will occur, wasting gas.

## 📜 ABI Dependency -The CLI requires the Pectra batch contract's ABI. Place the `abi.json` file in the same directory as the `pectra-cli` executable. +The CLI requires the Pectra batch contract's ABI. Place the abi.json file in the same directory as the pectra-cli executable. (The ABI is loaded from `./abi.json` as seen in `cmd/main.go` line 49)

-## ⚠️ Unset Delegation +## ⚠ Unset Delegation > It is HIGHLY recommended to unset delegation after performing any operation. This helps with restoration of EOA functionality and prevents the address from being used as a smart contract. @@ -132,49 +171,55 @@ To get a gist of the CLI, run: ./pectra-cli --help ``` -Replace `` with one of the operations listed below and `config.json` with the path to your configuration file. +Replace with one of the operations listed below and config.json with the path to your configuration file. Add the `-a` or `--airgapped` flag to run the CLI in airgapped mode. ### Switch Validators -Updates deposit credentials for the validators specified in `config.json` under the `switch` section. You can switch up to 200 validators in a single batch. +Updates deposit credentials for the validators specified in config.json under the switch section. You can switch up to 200 validators in a single batch. ```bash ./pectra-cli switch -c config.json ``` -⚠️ Do not switch a validator that has already been switched — the transaction will succeed but the switch won't take effect, wasting gas.

+⚠ Do not switch a validator that has already been switched — the transaction will succeed but the switch won't take effect, wasting gas.

### Consolidate Validators -Consolidates funds from `sourceValidators` to `targetValidator` as specified in `config.json` under the `consolidate` section. You can consolidate from up to 63 source validators into one target validator. +Consolidates funds from sourceValidators to targetValidator as specified in config.json under the consolidate section. You can consolidate from up to 63 source validators into one target validator. ```bash ./pectra-cli consolidate -c config.json ``` -⚠️ Do not use exited validators as source or target — transactions will succeed but consolidation won't occur, wasting gas.

+⚠ Do not use exited validators as source or target — transactions will succeed but consolidation won't occur, wasting gas.

### Execution Layer (EL) Exit -Performs partial or full exits for validators specified in `config.json` under the `elExit` section. You can exit up to 200 validators in a single batch. +Performs partial or full exits for validators specified in config.json under the elExit section. You can exit up to 200 validators in a single batch. ```bash ./pectra-cli el-exit -c config.json ``` -⚠️ Do not attempt to exit a validator that has already exited — the transaction will succeed but no exit will occur, wasting gas.

+⚠ Do not attempt to exit a validator that has already exited — the transaction will succeed but no exit will occur, wasting gas.

### Signing and Broadcast for airgapped mode -To sign an unsigned transaction, use `scripts/sign.go` on the `unsigned_txn.json` file — this will generate a `signed_txn.json`. +After generating an unsigned transaction in airgapped mode, you have two signing options: +#### Option 1: Sign with Private Key ```bash go run scripts/sign.go unsigned_txn.json ``` -Once signed, use the CLI's broadcast command to submit the `signed_txn.json` to the network. +#### Option 2: Sign with Mnemonic Phrase +```bash +./sign-mnemonic unsigned_txn.json +``` + +Both methods will generate a signed_txn.json file. Broadcast it using: ```bash ./pectra-cli broadcast -c config.json -f signed_txn.json @@ -183,31 +228,36 @@ Once signed, use the CLI's broadcast command to submit the `signed_txn.json` to ## 📝 Important Notes - **Validator Public Keys**: All validator public keys in the `config.json` file must be in hexadecimal format, without the "0x" prefix. -- **Transaction Fees**: The fee required per validator for each operation (switch, consolidate, EL exit) is automatically fetched from the smart contract functions (`getConsolidationFee`, `getExitFee`). This fee is in Wei. The total transaction `value` sent will be `(number of validators) * (fee per validator)`. +- **Transaction Fees**: The fee required per validator for each operation (switch, consolidate, EL exit) is automatically fetched from the smart contract functions (`getConsolidationFee`, `getExitFee`). This fee is in Wei. The total transaction value sent will be `(number of validators) * (fee per validator)`. (Fee fetching logic: `cmd/main.go` lines 67-74, 78-79, 91-92, 105-106) and `internal/utils/utils.go` lines 98-125 - **Execution Layer (EL) Exits**: - - The `amount` specified in the `elExit.validators` section of `config.json` is in **Gwei** (1 ETH = 1,000,000,000 Gwei). + - The amount specified in the `elExit.validators` section of `config.json` is in **Gwei** (1 ETH = 1,000,000,000 Gwei). (See `internal/utils/utils.go` for usage notes, and `internal/operations/partialexit.go` lines 41-49 for handling) - - For a **full exit**, set `amount` to `0` (or `0.0`) and `confirmFullExit` to `true`. - - For a **partial exit**, specify the desired `amount` in Gwei (e.g., `10.0` for 10 Gwei) and ensure `confirmFullExit` is `false`. + - For a **full exit**, set amount to `0` (or `0.0`) and `confirmFullExit` to `true`. + - For a **partial exit**, specify the desired amount in Gwei (e.g., `10.0` for 10 Gwei) and ensure `confirmFullExit` is `false`. - **Transaction Authorization**: This tool utilizes EIP-7702 SetCode transaction authorization for its operations. (See `internal/transaction/transaction.go` lines 18-61) +- **Mnemonic Security**: When using the mnemonic signer: + - Never share your seed phrase + - Run the signer on an airgapped machine when possible + - Verify the derived address matches your expected wallet address + - Consider using a dedicated account for validator operations
+ ## Sample Output (The CLI provides informative output during its execution, including connection status, fees, transaction hashes, and success/failure messages.) ### Sample Output for airgapped mode -![Sample Airgapped Output](https://i.imgur.com/CfKpNsN.png) -
-![Sample Signing Output](https://i.imgur.com/M9GGQB0.png) -
+![Sample Airgapped Output](https://i.postimg.cc/nhVbfmWV/Screenshot-2025-07-12-205709.png) +![Sample Private key Signing Output](https://i.postimg.cc/yYcY80nF/Screenshot-2025-07-12-205643.png) +![Sample Mnemonic phrase Signing Output](https://i.postimg.cc/XqtBF3yX/Screenshot-2025-07-12-210006.png) ![Sample Broadcast Output](https://i.imgur.com/nIEZDl8.png)
### Sample Output for non-airgapped mode ![Sample Non Airgapped Output](https://i.imgur.com/L2wpleY.png) -_(Note: The sample output images might show older field names or values; refer to the current configuration guidelines.)_ +(Note: The sample output images might show older field names or values; refer to the current configuration guidelines.)
diff --git a/Screenshot 2025-07-12 205643.png b/Screenshot 2025-07-12 205643.png new file mode 100644 index 0000000000000000000000000000000000000000..8d50b784288bb81ed88ed5c9a3ff74f40237792a GIT binary patch literal 11438 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 literal 0 HcmV?d00001 diff --git a/Screenshot 2025-07-12 205709.png b/Screenshot 2025-07-12 205709.png new file mode 100644 index 0000000000000000000000000000000000000000..7e14d957bbb6e895148da151dcc26c57c638412d GIT binary patch literal 18209 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 literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod index e301901..740f35b 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,8 @@ require ( github.com/ethereum/go-ethereum v1.15.11 github.com/fatih/color v1.18.0 github.com/holiman/uint256 v1.3.2 + github.com/tyler-smith/go-bip32 v1.0.0 + github.com/tyler-smith/go-bip39 v1.1.0 github.com/urfave/cli/v2 v2.27.6 golang.org/x/term v0.30.0 ) @@ -18,6 +20,8 @@ require ( ) require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/bits-and-blooms/bitset v1.20.0 // indirect diff --git a/go.sum b/go.sum index 6a16180..00d3c05 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= @@ -14,6 +18,8 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= @@ -38,6 +44,7 @@ github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOV github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= @@ -172,6 +179,7 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= @@ -182,20 +190,28 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= -github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -207,6 +223,7 @@ golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= @@ -219,5 +236,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/scripts/sign_mnemonic.go b/scripts/sign_mnemonic.go new file mode 100644 index 0000000..7e62992 --- /dev/null +++ b/scripts/sign_mnemonic.go @@ -0,0 +1,299 @@ +package main + +import ( + "crypto/ecdsa" + "encoding/hex" + "encoding/json" + "fmt" + "log" + "os" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" + "github.com/fatih/color" + "github.com/tyler-smith/go-bip32" + "github.com/tyler-smith/go-bip39" + "golang.org/x/term" +) + +const ( + // Default derivation path for Ethereum accounts + defaultDerivationPath = "m/44'/60'/0'/0/0" +) + +func main() { + color.Green("Pectra CLI - Mnemonic-based Transaction Signer") + color.Cyan("This tool signs transactions using a mnemonic phrase (seed phrase)") + fmt.Println() + + // Get mnemonic from user + mnemonic, err := getMnemonic() + if err != nil { + log.Fatalf("Failed to get mnemonic: %v", err) + } + + // Get derivation path from user + derivationPath, err := getDerivationPath() + if err != nil { + log.Fatalf("Failed to get derivation path: %v", err) + } + + // Derive private key from mnemonic + privateKey, address, err := derivePrivateKeyFromMnemonic(mnemonic, derivationPath) + if err != nil { + log.Fatalf("Failed to derive private key from mnemonic: %v", err) + } + + color.Green("Derived address: %s", address) + fmt.Println() + + // Determine input filename + inputFile := "unsigned_txn.json" + if len(os.Args) > 1 { + inputFile = os.Args[1] + } + + color.Cyan("Reading unsigned transaction from: %s", inputFile) + + // Read the unsigned transaction from file + data, err := os.ReadFile(inputFile) + if err != nil { + log.Fatalf("Failed to read %s: %v", inputFile, err) + } + + var txData struct { + UnsignedTransaction string `json:"unsignedTransaction"` + ChainId string `json:"chainId"` + } + + if err := json.Unmarshal(data, &txData); err != nil { + log.Fatalf("Failed to parse JSON: %v", err) + } + + hexTx := txData.UnsignedTransaction + + // Remove 0x prefix if present + if len(hexTx) > 2 && hexTx[0:2] == "0x" { + hexTx = hexTx[2:] + } + + // Decode hex to bytes + txBytes, err := hex.DecodeString(hexTx) + if err != nil { + log.Fatalf("Failed to decode hex string: %v", err) + } + + // Decode transaction + tx := new(types.Transaction) + err = rlp.DecodeBytes(txBytes, tx) + if err != nil { + log.Fatalf("Failed to decode transaction: %v", err) + } + + color.Cyan("Transaction details:") + color.White(" Hash: %s", tx.Hash().Hex()) + color.White(" Chain ID: %s", tx.ChainId().String()) + color.White(" To: %s", tx.To().Hex()) + color.White(" Value: %s Wei", tx.Value().String()) + color.White(" Gas: %d", tx.Gas()) + fmt.Println() + + // Confirm signing + if !confirmSigning() { + color.Yellow("Transaction signing cancelled by user") + return + } + + // Sign the authorization + color.Cyan("Signing authorization...") + signedAuthorization, err := types.SignSetCode(privateKey, tx.SetCodeAuthorizations()[0]) + if err != nil { + log.Fatalf("Failed to sign the authorization: %v", err) + } + + // Update the transaction with signed authorization + tx.SetCodeAuthorizations()[0] = signedAuthorization + + // Sign the transaction + color.Cyan("Signing transaction...") + signedTx, err := types.SignTx(tx, types.LatestSignerForChainID(tx.ChainId()), privateKey) + if err != nil { + log.Fatalf("Failed to sign the transaction: %v", err) + } + + // Encode the signed transaction + signedTxBytes, err := rlp.EncodeToBytes(signedTx) + if err != nil { + log.Fatalf("Failed to encode signed transaction: %v", err) + } + + // Write the signed transaction to a file + signedData := map[string]string{ + "signedTransaction": hex.EncodeToString(signedTxBytes), + } + + jsonData, err := json.MarshalIndent(signedData, "", " ") + if err != nil { + log.Fatalf("Failed to marshal to JSON: %v", err) + } + + outputFile := "signed_txn.json" + if err := os.WriteFile(outputFile, jsonData, 0644); err != nil { + log.Fatalf("Failed to write to %s: %v", outputFile, err) + } + + color.Green("Transaction successfully signed!") + color.Green("Signed transaction written to: %s", outputFile) + color.Cyan("You can now broadcast this transaction using: ./pectra-cli broadcast -f %s -c config.json", outputFile) +} + +// getMnemonic securely prompts the user for their mnemonic phrase +func getMnemonic() (string, error) { + color.Cyan("Please enter your mnemonic phrase (12, 15, 18, 21, or 24 words):") + color.Yellow("Note: The mnemonic will not be displayed for security. Just type/paste and press Enter.") + fmt.Print("> ") + + // Read mnemonic without echoing to terminal + bytePassword, err := term.ReadPassword(int(os.Stdin.Fd())) + if err != nil { + return "", fmt.Errorf("failed to read mnemonic: %w", err) + } + fmt.Println() + + mnemonic := strings.TrimSpace(string(bytePassword)) + + // Basic validation + words := strings.Fields(mnemonic) + if len(words) < 12 || len(words) > 24 { + return "", fmt.Errorf("invalid mnemonic length: expected 12-24 words, got %d", len(words)) + } + + // Validate mnemonic using BIP-39 + if !bip39.IsMnemonicValid(mnemonic) { + return "", fmt.Errorf("invalid mnemonic phrase") + } + + return mnemonic, nil +} + +// getDerivationPath prompts the user for a derivation path or uses the default +func getDerivationPath() (string, error) { + color.Cyan("Enter derivation path (or press Enter for default: %s):", defaultDerivationPath) + color.Yellow("Common paths:") + color.Yellow(" Ethereum (default): m/44'/60'/0'/0/0") + color.Yellow(" Ledger Live: m/44'/60'/0'/0/0") + color.Yellow(" MEW/MyCrypto: m/44'/60'/0'/0") + color.Yellow(" Custom account index: m/44'/60'/0'/0/[index]") + fmt.Print("> ") + + var input string + _, err := fmt.Scanln(&input) + if err != nil && err.Error() != "unexpected newline" { + return "", fmt.Errorf("failed to read derivation path: %w", err) + } + + input = strings.TrimSpace(input) + if input == "" { + return defaultDerivationPath, nil + } + + // Basic validation for derivation path format + if !strings.HasPrefix(input, "m/") { + return "", fmt.Errorf("derivation path must start with 'm/'") + } + + return input, nil +} + +// derivePrivateKeyFromMnemonic derives a private key from a mnemonic using the specified derivation path +func derivePrivateKeyFromMnemonic(mnemonic, derivationPath string) (*ecdsa.PrivateKey, string, error) { + // Generate seed from mnemonic + seed := bip39.NewSeed(mnemonic, "") + + // Create master key + masterKey, err := bip32.NewMasterKey(seed) + if err != nil { + return nil, "", fmt.Errorf("failed to create master key: %w", err) + } + + // Parse and apply derivation path + path, err := parseDerivationPath(derivationPath) + if err != nil { + return nil, "", fmt.Errorf("failed to parse derivation path: %w", err) + } + + key := masterKey + for _, index := range path { + key, err = key.NewChildKey(index) + if err != nil { + return nil, "", fmt.Errorf("failed to derive child key: %w", err) + } + } + + // Convert to ECDSA private key + privateKey, err := crypto.ToECDSA(key.Key) + if err != nil { + return nil, "", fmt.Errorf("failed to convert to ECDSA private key: %w", err) + } + + // Get the Ethereum address + address := crypto.PubkeyToAddress(privateKey.PublicKey).Hex() + + return privateKey, address, nil +} + +// parseDerivationPath parses a derivation path string into uint32 indexes +func parseDerivationPath(path string) ([]uint32, error) { + if !strings.HasPrefix(path, "m/") { + return nil, fmt.Errorf("derivation path must start with 'm/'") + } + + path = path[2:] + if path == "" { + return []uint32{}, nil + } + + parts := strings.Split(path, "/") + indexes := make([]uint32, len(parts)) + + for i, part := range parts { + var index uint64 + var err error + + if strings.HasSuffix(part, "'") { + part = part[:len(part)-1] + index, err = strconv.ParseUint(part, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid derivation path component: %s", part) + } + index += 0x80000000 + } else { + index, err = strconv.ParseUint(part, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid derivation path component: %s", part) + } + } + + indexes[i] = uint32(index) + } + + return indexes, nil +} + +// confirmSigning asks the user to confirm they want to sign the transaction +func confirmSigning() bool { + color.Yellow("Are you sure you want to sign this transaction? (y/N): ") + fmt.Print("> ") + + var response string + _, err := fmt.Scanln(&response) + if err != nil { + return false + } + + response = strings.ToLower(strings.TrimSpace(response)) + return response == "y" || response == "yes" +} \ No newline at end of file From 371f5fc487c340c0eeb7a440d9deadd0658cf047 Mon Sep 17 00:00:00 2001 From: Shreyash Naik <77315155+shrxyeh@users.noreply.github.com> Date: Sun, 27 Jul 2025 19:08:39 +0530 Subject: [PATCH 2/3] Delete Screenshot 2025-07-12 205643.png --- Screenshot 2025-07-12 205643.png | Bin 11438 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Screenshot 2025-07-12 205643.png diff --git a/Screenshot 2025-07-12 205643.png b/Screenshot 2025-07-12 205643.png deleted file mode 100644 index 8d50b784288bb81ed88ed5c9a3ff74f40237792a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11438 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 From 30fd18db4d8920f2cdc17cebb42d5a16a0dc5956 Mon Sep 17 00:00:00 2001 From: Shreyash Naik <77315155+shrxyeh@users.noreply.github.com> Date: Sun, 27 Jul 2025 19:08:58 +0530 Subject: [PATCH 3/3] Delete Screenshot 2025-07-12 205709.png --- Screenshot 2025-07-12 205709.png | Bin 18209 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Screenshot 2025-07-12 205709.png diff --git a/Screenshot 2025-07-12 205709.png b/Screenshot 2025-07-12 205709.png deleted file mode 100644 index 7e14d957bbb6e895148da151dcc26c57c638412d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18209 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