diff --git a/package.json b/package.json index 899f06b..a86dce7 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "license": "MIT", "dependencies": { "@chainsafe/bls-js": "^0.1.5", + "@chainsafe/ssz": "^0.5.1", "dotenv": "^8.0.0", "ethers": "^4.0.33", "ganache-cli": "^6.5.0" diff --git a/start.js b/start.js index e9ebcff..80844ee 100644 --- a/start.js +++ b/start.js @@ -3,6 +3,10 @@ const ethers = require('ethers'); const fs = require('fs'); const keypair = require('@chainsafe/bls-js/lib/keypair'); const privateKey = require('@chainsafe/bls-js/lib/privateKey'); +const bls = require('@chainsafe/bls-js'); +const sha256 = require('js-sha256'); +const ssz = require('@chainsafe/ssz'); +const BN = require('bn.js'); // Deposit contract data const deposit_contract_bytecode = "0x740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052341561009857600080fd5b6101406000601f818352015b600061014051602081106100b757600080fd5b600260c052602060c020015460208261016001015260208101905061014051602081106100e357600080fd5b600260c052602060c020015460208261016001015260208101905080610160526101609050602060c0825160208401600060025af161012157600080fd5b60c0519050606051600161014051018060405190131561014057600080fd5b809190121561014e57600080fd5b6020811061015b57600080fd5b600260c052602060c02001555b81516001018083528114156100a4575b505061124d56600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052600015610277575b6101605261014052600061018052610140516101a0526101c060006008818352015b61018051600860008112156100da578060000360020a82046100e1565b8060020a82025b905090506101805260ff6101a051166101e052610180516101e0516101805101101561010c57600080fd5b6101e0516101805101610180526101a0517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86000811215610155578060000360020a820461015c565b8060020a82025b905090506101a0525b81516001018083528114156100bd575b50506018600860208206610200016020828401111561019357600080fd5b60208061022082610180600060046015f15050818152809050905090508051602001806102c0828460006004600a8704601201f16101d057600080fd5b50506102c05160206001820306601f82010390506103206102c0516008818352015b826103205111156102025761021e565b6000610320516102e001535b81516001018083528114156101f2575b50505060206102a05260406102c0510160206001820306601f8201039050610280525b6000610280511115156102535761026f565b602061028051036102a001516020610280510361028052610241565b610160515650005b63863a311b600051141561050957341561029057600080fd5b6000610140526101405161016052600154610180526101a060006020818352015b60016001610180511614156103325760006101a051602081106102d357600080fd5b600060c052602060c02001546020826102400101526020810190506101605160208261024001015260208101905080610240526102409050602060c0825160208401600060025af161032457600080fd5b60c0519050610160526103a0565b6000610160516020826101c00101526020810190506101a0516020811061035857600080fd5b600260c052602060c02001546020826101c0010152602081019050806101c0526101c09050602060c0825160208401600060025af161039657600080fd5b60c0519050610160525b61018060026103ae57600080fd5b60028151048152505b81516001018083528114156102b1575b505060006101605160208261046001015260208101905061014051610160516101805163806732896102e05260015461030052610300516006580161009b565b506103605260006103c0525b6103605160206001820306601f82010390506103c0511015156104355761044e565b6103c05161038001526103c0516020016103c052610413565b61018052610160526101405261036060088060208461046001018260208501600060046012f150508051820191505060006018602082066103e0016020828401111561049957600080fd5b60208061040082610140600060046015f150508181528090509050905060188060208461046001018260208501600060046014f150508051820191505080610460526104609050602060c0825160208401600060025af16104f957600080fd5b60c051905060005260206000f350005b63621fd130600051141561061c57341561052257600080fd5b63806732896101405260015461016052610160516006580161009b565b506101c0526000610220525b6101c05160206001820306601f82010390506102205110151561056d57610586565b610220516101e00152610220516020016102205261054b565b6101c0805160200180610280828460006004600a8704601201f16105a957600080fd5b50506102805160206001820306601f82010390506102e0610280516008818352015b826102e05111156105db576105f7565b60006102e0516102a001535b81516001018083528114156105cb575b5050506020610260526040610280510160206001820306601f8201039050610260f350005b63c47e300d60005114156110c857605060043560040161014037603060043560040135111561064a57600080fd5b60406024356004016101c037602060243560040135111561066a57600080fd5b608060443560040161022037606060443560040135111561068a57600080fd5b63ffffffff6001541061069c57600080fd5b633b9aca006102e0526102e0516106b257600080fd5b6102e05134046102c052633b9aca006102c05110156106d057600080fd5b603061014051146106e057600080fd5b60206101c051146106f057600080fd5b6060610220511461070057600080fd5b610140610360525b6103605151602061036051016103605261036061036051101561072a57610708565b6380673289610380526102c0516103a0526103a0516006580161009b565b50610400526000610460525b6104005160206001820306601f8201039050610460511015156107765761078f565b6104605161042001526104605160200161046052610754565b610340610360525b61036051526020610360510361036052610140610360511015156107ba57610797565b610400805160200180610300828460006004600a8704601201f16107dd57600080fd5b5050610140610480525b61048051516020610480510161048052610480610480511015610809576107e7565b63806732896104a0526001546104c0526104c0516006580161009b565b50610520526000610580525b6105205160206001820306601f8201039050610580511015156108545761086d565b6105805161054001526105805160200161058052610832565b610460610480525b610480515260206104805103610480526101406104805110151561089857610875565b6105208051602001806105a0828460006004600a8704601201f16108bb57600080fd5b505060a06106205261062051610660526101408051602001806106205161066001828460006004600a8704601201f16108f357600080fd5b505061062051610660015160206001820306601f8201039050610620516106600161060081516040818352015b83610600511015156109315761094e565b6000610600516020850101535b8151600101808352811415610920575b50505050602061062051610660015160206001820306601f82010390506106205101016106205261062051610680526101c08051602001806106205161066001828460006004600a8704601201f16109a557600080fd5b505061062051610660015160206001820306601f8201039050610620516106600161060081516020818352015b83610600511015156109e357610a00565b6000610600516020850101535b81516001018083528114156109d2575b50505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106a0526103008051602001806106205161066001828460006004600a8704601201f1610a5757600080fd5b505061062051610660015160206001820306601f8201039050610620516106600161060081516020818352015b8361060051101515610a9557610ab2565b6000610600516020850101535b8151600101808352811415610a84575b50505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106c0526102208051602001806106205161066001828460006004600a8704601201f1610b0957600080fd5b505061062051610660015160206001820306601f8201039050610620516106600161060081516060818352015b8361060051101515610b4757610b64565b6000610600516020850101535b8151600101808352811415610b36575b50505050602061062051610660015160206001820306601f820103905061062051010161062052610620516106e0526105a08051602001806106205161066001828460006004600a8704601201f1610bbb57600080fd5b505061062051610660015160206001820306601f8201039050610620516106600161060081516020818352015b8361060051101515610bf957610c16565b6000610600516020850101535b8151600101808352811415610be8575b50505050602061062051610660015160206001820306601f8201039050610620510101610620527f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c561062051610660a160006107005260006101406030806020846107c001018260208501600060046016f150508051820191505060006010602082066107400160208284011115610cad57600080fd5b60208061076082610700600060046015f15050818152809050905090506010806020846107c001018260208501600060046013f1505080518201915050806107c0526107c09050602060c0825160208401600060025af1610d0d57600080fd5b60c0519050610720526000600060406020820661086001610220518284011115610d3657600080fd5b606080610880826020602088068803016102200160006004601bf1505081815280905090509050602060c0825160208401600060025af1610d7657600080fd5b60c0519050602082610a600101526020810190506000604060206020820661092001610220518284011115610daa57600080fd5b606080610940826020602088068803016102200160006004601bf15050818152809050905090506020806020846109e001018260208501600060046015f1505080518201915050610700516020826109e0010152602081019050806109e0526109e09050602060c0825160208401600060025af1610e2757600080fd5b60c0519050602082610a6001015260208101905080610a6052610a609050602060c0825160208401600060025af1610e5e57600080fd5b60c0519050610840526000600061072051602082610b000101526020810190506101c0602080602084610b0001018260208501600060046015f150508051820191505080610b0052610b009050602060c0825160208401600060025af1610ec457600080fd5b60c0519050602082610c800101526020810190506000610300600880602084610c0001018260208501600060046012f15050805182019150506000601860208206610b800160208284011115610f1957600080fd5b602080610ba082610700600060046015f1505081815280905090509050601880602084610c0001018260208501600060046014f150508051820191505061084051602082610c0001015260208101905080610c0052610c009050602060c0825160208401600060025af1610f8c57600080fd5b60c0519050602082610c8001015260208101905080610c8052610c809050602060c0825160208401600060025af1610fc357600080fd5b60c0519050610ae0526001805460018254011015610fe057600080fd5b6001815401815550600154610d0052610d2060006020818352015b60016001610d005116141561103057610ae051610d20516020811061101f57600080fd5b600060c052602060c02001556110c4565b6000610d20516020811061104357600080fd5b600060c052602060c0200154602082610d40010152602081019050610ae051602082610d4001015260208101905080610d4052610d409050602060c0825160208401600060025af161109457600080fd5b60c0519050610ae052610d0060026110ab57600080fd5b60028151048152505b8151600101808352811415610ffb575b5050005b60006000fd5b61017f61124d0361017f60003961017f61124d036000f3"; @@ -104,10 +108,12 @@ provider.listAccounts().then(function(result){ }); +let contractAddress; // Deploy deposit contract, precompiled, save its address into a file async function deployDepositContract(pk) { let factory = new ethers.ContractFactory(deposit_contract_abi, deposit_contract_bytecode, new ethers.Wallet(pk, provider)); - let contract = await factory.deploy(); + let contract = await factory.deploy(); + contractAddress = contract.address; console.log("Contract will be generated at " + contract.address + " when TX " + contract.deployTransaction.hash) + " is mined."; fs.writeFile("deploy/keys/deposit_contract.txt", contract.address, function(err) { @@ -146,7 +152,6 @@ async function makeValidatorDeposits() { console.log("Generating keys for " + Object.keys(mykeys).length + " pre-provided accounts"); for (var key in mykeys) { if (mykeys.hasOwnProperty(key)) { - console.log("Generating for account " + key); let pkWallet = new ethers.Wallet(mykeys[key]); pk = pkWallet.privateKey; @@ -172,28 +177,54 @@ async function makeValidatorDeposits() { }); console.log("Starting validator deposits"); + let contract = new ethers.Contract(contractAddress, deposit_contract_abi, provider); accountMasterList.forEach(function(item) { - // @TODO - //let signer = provider.getSigner(item.address); - /* - 1. Generate bls/eth2 privkey and pubkey for signing (random). This gives me the signing pubkey of 48 bytes length. - 2. Generate bls/eth2 privkey and pubkey for withdrawal (random) - 3. Put the deposit data together: pubkey is the signing pubkey, withdrawal credentials is the sha256 hash of the withdrawal pubkey (32 bytes), but the first byte of the hash is replaced with the prefix (currently 0 for version 0), breaking the hash, while signature is technically bls_sign(signing_privkey, signing_root(deposit_data)) but due to the circular dependency the signature here is actually ignored (!!) which is not detailed in the spec, and can be nothing, null, or random data. - 4. Signature for Deposit call is then again bls_sign(signing_privkey, signing_root(deposit_data)) which should produce 96 bytes. - */ + // 48 byte public key for signing + let signkeys = new keypair.Keypair(privateKey.PrivateKey.fromHexString(item.bls_key_sign)); + let sign_pubkey = signkeys.publicKey.toBytesCompressed(); + let sign_prikey = signkeys.privateKey.toBytes(); - // Example simple tx - // signer.sendTransaction({ - // to: accounts[0], - // value: ethers.utils.parseEther('15.0') - // }).then(function(txReceipt) { - // provider.getBalance(accounts[0]).then(console.log); - // }.bind(accounts)); + // 48 byte public key for withdrawing + let withdraw_pubkey = new keypair.Keypair(privateKey.PrivateKey.fromHexString(item.bls_key_withdraw)).publicKey.toHexString(); + + // Withdrawal credentials is the sha256 hash of the withdrawal pubkey (32 bytes), but the first byte of the hash is replaced with the prefix (currently 0 for version 0) + //let withdrawal_credentials = "00" + sha256.sha256(withdraw_pubkey).slice(2); // 32 byte output + let withdrawal_credentials = Buffer.from(sha256.arrayBuffer(withdraw_pubkey)) + + // Signature is technically bls_sign(signing_privkey, signing_root(deposit_data)) but due to the circular dependency the signature here is actually ignored (!!) and can be nothing, null, or random data. + let signature_dd = Buffer.alloc(5); + + // Put it together somehow + let depositData = { + pubkey: sign_pubkey, + withdrawalCredentials: withdrawal_credentials, + signature: signature_dd, + amount: new BN("32000000000") + } + + console.log(depositData); + console.log(sign_prikey); + + // Signature for Deposit call, should be identical to signature of deposit data 🤔 ¯\_(ツ)_/¯ + let signature_d = bls.default.sign(sign_prikey, ssz.signingRoot(depositData, { + fields: [ + ["pubkey", "bytes48"], + ["withdrawalCredentials", "bytes32"], + ["amount", "uint64"], + ["signature", "bytes96"], + ], + })); + + // A signer is needed to sign a transaction from a given account + let signer = provider.getSigner(item.address); + contract.connect(signer); + let tx = contract.deposit(sign_pubkey, withdrawalCredentials, signature_d); + + console.log("Validator " + item.address + " is depositing 32 ether to the deposit contract at " + contractAddress + " via TX " + tx.hash); + tx.wait(); }); - - const server = ganache.server(startupOptions); server.listen(8545, function(err, blockchain) { // The server starts, you can connect to it with RPC now. diff --git a/yarn.lock b/yarn.lock index 76789b2..28c59f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@chainsafe/amcl/-/amcl-0.1.0.tgz#8a49445402561e3dcf9d536b78e2dc225b159b22" integrity sha512-XzVLRxAqkkFeLA9T3ro1gn8llV3y6FIN38bRgmp5HvOJyfBprotKa6973J7BL7X566R6uztoNweK8ng40G08tw== +"@chainsafe/bit-utils@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@chainsafe/bit-utils/-/bit-utils-0.1.3.tgz#d29a69c161526fda8bf0880da3d62a4a7100e169" + integrity sha512-0OhFBmsMleMH1NaSC2dO3D3PieJxSJBEqgGHhjoBCf8gc/BP4LHN2OLdMxRjbJK8gduDrwKRHdeGZ34pkgM5ew== + "@chainsafe/bls-js@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@chainsafe/bls-js/-/bls-js-0.1.5.tgz#00fed1ef879aa4668092e7010fa21f5bf19f569e" @@ -17,6 +22,29 @@ js-sha256 "^0.9.0" secure-random "^1.1.1" +"@chainsafe/ssz@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.5.1.tgz#5d8fa0d00ee7d91fc5de914a843bd47125213c6a" + integrity sha512-heJsVhB7hCWubCHqCaYrctv7IuzCQkAWduwJleCSv9K2EXBcEmDeKPg4DQ/b9cQyXQbn2hwEuSDcMcQESwaIfA== + dependencies: + "@chainsafe/bit-utils" "^0.1.3" + "@types/bn.js" "^4.11.4" + assert "^1.4.1" + bcrypto "^4.1.0" + bn.js "^4.11.8" + +"@types/bn.js@^4.11.4": + version "4.11.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.5.tgz#40e36197433f78f807524ec623afcf0169ac81dc" + integrity sha512-AEAZcIZga0JgVMHNtl1CprA/hXX7/wPt79AgR4XqaDt7jyj3QWYw6LPoOiznPtugDmlubUnAahMs2PFxGcQrng== + dependencies: + "@types/node" "*" + +"@types/node@*": + version "12.6.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.8.tgz#e469b4bf9d1c9832aee4907ba8a051494357c12c" + integrity sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg== + "@types/node@^10.3.2": version "10.14.13" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.13.tgz#ac786d623860adf39a3f51d629480aacd6a6eec7" @@ -45,7 +73,17 @@ assert@^1.4.1: object-assign "^4.1.1" util "0.10.3" -bn.js@4.11.8, bn.js@^4.4.0: +bcrypto@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bcrypto/-/bcrypto-4.1.0.tgz#04fd2ec095e4eba121412e287b9c542cd7230a57" + integrity sha512-7QMCwNPAM53PcRG2gHwMHLcTjSwyQPYfTptRS38KuBZ7/Bf7zXVHZrQlvNnpu/m13qCVEMY4Wimnc+qt+rvMZg== + dependencies: + bsert "~0.0.10" + bufio "~1.0.6" + loady "~0.0.1" + nan "^2.13.2" + +bn.js@4.11.8, bn.js@^4.11.8, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== @@ -55,11 +93,21 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +bsert@~0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/bsert/-/bsert-0.0.10.tgz#231ac82873a1418c6ade301ab5cd9ae385895597" + integrity sha512-NHNwlac+WPy4t2LoNh8pXk8uaIGH3NSaIUbTTRXGpE2WEbq0te/tDykYHkFK57YKLPjv/aGHmbqvnGeVWDz57Q== + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +bufio@~1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.0.6.tgz#e0eb6d70b2efcc997b6f8872173540967f90fa4d" + integrity sha512-mjYZFRHmI9bk3Oeexu0rWjHFY+w6hGLabdmwSFzq+EFr4MHHsNOYduDVdYl71NG5pTPL7GGzUCMk9cYuV34/Qw== + camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -233,6 +281,11 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" +loady@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/loady/-/loady-0.0.1.tgz#24a99c14cfed9cd0bffed365b1836035303f7e5d" + integrity sha512-PW5Z13Jd0v6ZcA1P6ZVUc3EV8BJwQuAiwUvvT6VQGHoaZ1d/tu7r1QZctuKfQqwy9SFBWeAGfcIdLxhp7ZW3Rw== + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -266,6 +319,11 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== +nan@^2.13.2: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"