Created
July 2, 2019 12:40
-
-
Save s1na/df9682fc4f9a8f4290c7d34be8ffcd2f to your computer and use it in GitHub Desktop.
Relayer for stateless MPT-like token (scout script)
This file contains 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
const assert = require('assert') | |
const { promisify } = require('util') | |
const BN = require('bn.js') | |
const Trie = require('merkle-patricia-tree') | |
const Account = require('ethereumjs-account').default | |
const StateManager = require('ethereumjs-vm/dist/state/stateManager').default | |
const PStateManager = require('ethereumjs-vm/dist/state/promisified').default | |
const { keccak256, ecsign, stripZeros } = require('ethereumjs-util') | |
const { encode } = require('rlp') | |
const prove = promisify(Trie.prove) | |
const verifyProof = promisify(Trie.verifyProof) | |
async function main () { | |
const rawState = new StateManager() | |
const state = new PStateManager(rawState) | |
let root = await state.getStateRoot() | |
console.log('empty trie root: ', root) | |
// Prepare "genesis" state | |
//const fromPubKey = '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' | |
const fromPrivateKey = Buffer.from([234, 84, 189, 197, 45, 22, 63, 136, 201, 58, 176, 97, 87, 130, 207, 113, 138, 46, 251, 158, 81, 167, 152, 154, 171, 27, 8, 6, 126, 156, 28, 95]) | |
const addr0 = Buffer.from('2f015c60e0be116b1f0cd534704db9c92118fb6a', 'hex') | |
const addr1 = Buffer.from('0000000000000000000000000000000000000001', 'hex') | |
const acc0 = new Account() | |
acc0.balance = new BN('ffffff', 16).toBuffer() | |
const acc1 = new Account() | |
await state.putAccount(addr0, acc0) | |
await state.putAccount(addr1, acc1) | |
root = await state.getStateRoot() | |
console.log('genesis state root: ', root.toString('hex')) | |
// Tx data | |
const tx = { | |
from: addr0, | |
to: addr1, | |
value: new BN('00000000000000000000000000000000000000000000000000000000000000ff', 16), | |
nonce: new BN('0000000000000000000000000000000000000000000000000000000000000000', 16), | |
} | |
const txRlp = encode([tx.to, stripZeros(tx.value.toBuffer('be', 32)), stripZeros(tx.nonce.toBuffer('be', 32))]) | |
const txHash = keccak256(txRlp) | |
const txSig = ecsign(txHash, fromPrivateKey) | |
// Compute witnesses for transfer: | |
const fromWitness = await prove(state._wrapped._trie, keccak256(tx.from)) | |
let val = await verifyProof(root, keccak256(tx.from), fromWitness) | |
assert(val.equals(acc0.serialize()), "valid from witness") | |
const toAcc = await state.getAccount(tx.to) | |
const toWitness = await prove(state._wrapped._trie, keccak256(tx.to)) | |
val = await verifyProof(root, keccak256(tx.to), toWitness) | |
assert(val.equals(toAcc.serialize()), "valid to witness") | |
// Serialize witnesses and tx data | |
const blockData = encode( | |
[ | |
[tx.to, stripZeros(tx.value.toBuffer('be', 32)), stripZeros(tx.nonce.toBuffer('be', 32)), [stripZeros(txSig.r), stripZeros(txSig.s), txSig.v]], | |
fromWitness, | |
toWitness | |
] | |
) | |
console.log('block data: ', blockData.toString('hex')) | |
// Simulate transfering funds to compute post state root | |
await transfer(state, tx) | |
root = await state.getStateRoot() | |
console.log('post transfer state root: ', root.toString('hex')) | |
} | |
async function transfer (state, tx) { | |
let { from, to, value, nonce } = tx | |
assert(value.gten(0)) | |
const fromAcc = await state.getAccount(from) | |
const toAcc = await state.getAccount(to) | |
assert(new BN(fromAcc.balance).gte(value)) | |
assert(new BN(fromAcc.nonce).eq(nonce)) | |
const newFromBalance = new BN(fromAcc.balance).sub(value) | |
fromAcc.balance = newFromBalance.toBuffer() | |
fromAcc.nonce = nonce.addn(1).toBuffer() | |
const newToBalance = new BN(toAcc.balance).add(value) | |
toAcc.balance = newToBalance.toBuffer() | |
await state.putAccount(from, fromAcc) | |
await state.putAccount(to, toAcc) | |
} | |
main().then(() => console.log('main done')).catch((e) => console.log(e)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment