Implementation layout
The interface follows the BankNode Bitcoin project, preserving the same operational model across chains.
three-headed-bot.js- entry point, peer HTTP(S), DKG, and signing orchestration.crypto_backend.js- cryptographic backend, Ethereum transaction building, and validation.tg_backend.js- Telegram polling, commands, and approval flow.node-{1,2,3}.config.example.json- three node configurations in the Bitcoin-compatible format.data/- each node's local secret share and persisted signing parameters.
Cryptographic model
- Three participants independently create a secp256k1 contribution, a Shamir 2-of-3 share, a Feldman VSS commitment, and a 3072-bit Paillier key pair.
- Threshold signing uses the corrected BitGo GG18 scheme with MtA, Paillier modulus challenge, range proofs, proof of share possession, and verifiable
V/AandU/Tcommitment stages. - The result is a standard Ethereum low-S signature in
r || s || yParityformat, compatible withethers.recoverAddress, geth, and EVM tooling. - Final 32-byte transaction digests are signed without an additional SHA-256 operation.
/signand/multisignapply EIP-191hashMessagebefore signing.- EIP-1559 and ERC-20 transactions are locally reconstructed and the recovered address is verified before broadcast.
Determinism and recovery
Each node's public contribution is derived deterministically from crypto.masterSeed_fix, the Telegram wallet key, and fixed parameters using HMAC-SHA512. Repeating DKG with the same fixed fields reproduces the same Ethereum address.
Paillier keys, Shamir polynomials, and signing nonces are generated by the system CSPRNG and differ on every run. Losing one share file is tolerated; losing any two shares requires a new DKG.
Installation
Node.js 20 or newer is required.
npm ci
npm run check
npm test
The full test creates real 3072-bit Paillier keys for all three participants and completes a 2-of-3 Ethereum signature. The auxiliary RSA modulus is reduced to 512 bits only in tests for speed; runtime always calls generateNtilde(3072).
Copy each .config.example.json file to .config.json and replace every PASTE_* and REPLACE_* value. Set telegram.botToken, telegram.allowedGroupId, and a unique crypto.masterSeed_fix containing at least 32 bytes.
npm start -- node-1.config.example.json
npm start -- node-2.config.example.json
npm start -- node-3.config.example.json
The default Ethereum peer ports are 6661, 6662, and 6663.
Production deployment
- Deploy the three nodes on separate machines and in separate security domains.
- Configure
http.tls.certPemandhttp.tls.keyPem. - Use HTTPS peer URLs and certificates signed by a system-trusted CA.
- Restrict inter-node ports to participant addresses with network ACLs.
- Store
data/*.dbon encrypted storage with separate backups and access controls. - Set
runtime.environmenttoproductionand retain the pinnedpackage-lock.json.
During /create, all nodes generate reusable 3072-bit Ntilde signing parameters in parallel and persist them locally. Setup stages allow up to 60 minutes for slower processors; ordinary signing requests retain shorter timeouts.
Set runtime.logLevel to debug to inspect RPC calls, approvals, peer requests, challenge handling, and MPC signing rounds.
Telegram commands
Commands are accepted only from allowedGroupId and must be addressed to the bot.
/create@bot [user_id2 user_id3]
/address@bot
/balance@bot [address]
/tokenbalance@bot <token_contract> [owner]
/usdtbalance@bot [owner]
/utxo@bot
/status@bot
/sign@bot <message>
/signhash@bot <32-byte-hex>
/send@bot <to> <amount_wei> [max_fee_gwei]
/tokensend@bot <token_contract> <to> <amount_tokens> [max_fee_gwei]
/usdtsend@bot <to> <amount_usdt> [max_fee_gwei]
/multisign@bot <id2> <id3> <message>
/multisignhash@bot <id2> <id3> <32-byte-hex>
/multisend@bot <id2> <id3> <to> <amount_wei> [max_fee_gwei]
/multitokensend@bot <id2> <id3> <token_contract> <to> <amount_tokens> [max_fee_gwei]
/usdtmultisend@bot <id2> <id3> <to> <amount_usdt> [max_fee_gwei]
/approve@bot
/reject@bot
Transaction behavior
ETH transfers
/send and /multisend build EIP-1559 transactions, estimate gas, threshold-sign unsignedHash, verify the recovered address locally, and only then submit the raw transaction to an RPC node.
An amount_wei value of zero enables send-all mode. The system reserves the maximum EIP-1559 fee and signs the actual transferable balance.
ERC-20 and USDT
Token commands verify contract code, decimals, token balance, simulation results, and available ETH for gas. Amounts are converted to base units without floating-point arithmetic.
The USDT aliases use the fixed Ethereum Mainnet contract 0xdAC17F958D2ee523a2206206994597C13D831ec7 and operate only when ethereum.chainId = 1.
Approval flow
Before every signature, the second signer publishes the digest and operation description. Personal mode requires approval through the second node's bot; group mode requires approval from one of the two additional Telegram identities.
Network and storage
- Peer configuration uses
index_fix,id,ip, andport. - Production peer authentication relies on restricted network access and CA-validated HTTPS.
- Secret DKG shares are transmitted directly to the recipient, never through the coordinator.
- Database writes use a temporary file followed by atomic rename; POSIX file mode is
0600. - RPC providers are used in order with automatic failover.
License and audit
The project is MIT-licensed. The pinned cryptographic dependency stack uses @bitgo/[email protected], @bitgo/[email protected], and [email protected]. The package override must be retained to prevent an unintended dependency and license change.
AI-assisted security review
The Ethereum threshold ECDSA implementation and its integration controls were reviewed with Claude Mythos and GPT-5.6 as AI-assisted analysis tools. This review does not replace an independent professional security audit.