Skip to content

Commit

Permalink
Added proof for Ethereum event and tx receipt
Browse files Browse the repository at this point in the history
  • Loading branch information
k06a committed Apr 13, 2020
1 parent b04d6b1 commit 11c0344
Show file tree
Hide file tree
Showing 16 changed files with 2,375 additions and 92 deletions.
9 changes: 3 additions & 6 deletions ethprover/.gitignore
@@ -1,7 +1,4 @@
target
res/eth_prover.wasm

build/
target/
neardev/

node_modules
package-lock.json
.openzeppelin/
Empty file added ethprover/contracts/.gitkeep
Empty file.
10 changes: 10 additions & 0 deletions ethprover/contracts/Emitter.sol
@@ -0,0 +1,10 @@
pragma solidity ^0.5.0;


contract Emitter {
event Log(uint256 indexed a, uint256 b, uint256 c);

function emitEvent(uint256 a, uint256 b, uint256 c) public {
emit Log(a, b, c);
}
}
40 changes: 40 additions & 0 deletions ethprover/index.js
Expand Up @@ -3,6 +3,10 @@ const nearlib = require('nearlib');
const BN = require('bn.js');
const exec = require('child_process').exec;
const utils = require('ethereumjs-util');
const Tree = require('merkle-patricia-tree');
const { Header, Proof, Receipt, Transaction, Log } = require('eth-object');
const { encode, toBuffer } = require('eth-util-lite');
const { promisfy } = require('promisfy');

function execute(command, callback){
return new Promise(resolve => exec(command, (error, stdout, stderr) => {
Expand Down Expand Up @@ -306,7 +310,43 @@ class EthProverContract extends Contract {
}
}

function receiptFromWeb3(result) {
return new Receipt([
toBuffer((result.status ? 0x1 : 0x0) || result.root),
toBuffer(result.cumulativeGasUsed),
toBuffer(result.logsBloom),
result.logs.map(Log.fromRpc)
]);
}

(async function () {
const web3 = new Web3(process.env.ETH_NODE_URL);
const emitter = new web3.eth.Contract(require('./build/contracts/Emitter.json').abi, process.env.ETH_CONTRACT_ADDRESS);
const events = await emitter.getPastEvents('allEvents');

// Get proof
// https://github.com/zmitton/eth-proof/blob/master/getProof.js#L39
const event = events[0];
const targetReceipt = await web3.eth.getTransactionReceipt(event.transactionHash);
const block = await web3.eth.getBlock(event.blockHash);
const blockReceipts = await Promise.all(block.transactions.map(web3.eth.getTransactionReceipt));
const tree = new Tree();

await Promise.all(blockReceipts.map((receipt, index) => {
const path = encode(index);
const serializedReceipt = receiptFromWeb3(receipt).serialize();
return promisfy(tree.put, tree)(path, serializedReceipt);
}));

const [_, __, stack] = await promisfy(tree.findPath, tree)(encode(targetReceipt.transactionIndex))

const proof = {
header: Header.fromRpc(block),
receiptProof: Proof.fromStack(stack),
txIndex: targetReceipt.transactionIndex,
};

console.log('proof:', proof);

const near = await nearlib.connect({
nodeUrl: process.env.NEAR_NODE_URL, // 'https://rpc.nearprotocol.com',
Expand Down
12 changes: 12 additions & 0 deletions ethprover/networks.js
@@ -0,0 +1,12 @@
module.exports = {
networks: {
development: {
protocol: 'http',
host: 'localhost',
port: 9545,
gas: 5000000,
gasPrice: 5e9,
networkId: '*',
},
},
};
12 changes: 9 additions & 3 deletions ethprover/package.json
@@ -1,6 +1,6 @@
{
"name": "ethprover",
"version": "0.0.0",
"version": "0.0.1",
"description": "EthProver test",
"main": "index.js",
"author": "",
Expand All @@ -9,10 +9,16 @@
"test": "scripts/run_localnet.sh"
},
"dependencies": {
"nearlib": "^0.22.0",
"near-shell": "^0.20.1",
"@openzeppelin/cli": "^2.8.1",
"eth-object": "^1.0.3",
"eth-util-lite": "^1.0.1",
"ethereumjs-block": "^2.2.2",
"ethereumjs-util": "^6.2.0",
"ganache-cli": "^6.9.1",
"merkle-patricia-tree": "^3.0.0",
"near-shell": "^0.20.1",
"nearlib": "^0.22.0",
"promisfy": "^1.2.0",
"web3": "^1.2.6"
}
}
Binary file added ethprover/res/eth_prover.wasm
Binary file not shown.
81 changes: 32 additions & 49 deletions ethprover/scripts/run_localnet.sh
@@ -1,45 +1,27 @@
#!/usr/bin/env bash

# Exit script as soon as a command fails.
set -o errexit

# Executes cleanup function at script exit.
trap cleanup EXIT
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

cleanup() {
# Kill the nearnode instance that we started (if we started one and if it's still running).
if [ -n "$node_started" ]; then
docker kill nearcore watchtower > /dev/null &
fi
}
source $DIR/../../scripts/start_ganache.sh
source $DIR/../../scripts/start_nearcore.sh

./build.sh
# Exit script as soon as a command fails.
set -o errexit

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
NODE_URL="http://localhost:3030"
nearnode_port=24567
start_ganache_if_needed
start_nearcore_if_needed

waitport() {
while ! nc -z localhost $1 ; do sleep 1 ; done
}
oz compile
ETH_CONTRACT_ADDRESS=$(oz deploy Emitter --kind regular --network development --silent --no-interactive)
EXH_TX=$(oz send-tx --to $ETH_CONTRACT_ADDRESS --method "emitEvent(uint256,uint256,uint256)" --args 1,2,3 --network development)

nearnode_running() {
nc -z localhost "$nearnode_port"
}
echo "xxx: $EXH_TX"

start_nearnode() {
echo "ethrelay" | "$DIR/start_localnet.py" --home "$DIR/.near" --image "nearprotocol/nearcore:ethdenver"
waitport $nearnode_port
}
$DIR/../build.sh

if nearnode_running; then
echo "Using existing nearnode instance"
else
echo "Starting our own nearnode instance"
rm -rf "$DIR/.near"
start_nearnode
node_started=1
fi
ETH_NODE_URL="http://localhost:9545"
NODE_URL="http://localhost:3030"
NODE_ROOT="$DIR/../../scripts/.near"

# The master account ID to create accounts
NEAR_MASTER_ACCOUNT_ID="ethrelay"
Expand All @@ -51,16 +33,15 @@ NEAR_ETHPROVER_ACCOUNT_ID="ethprover"
NEAR_ETHBRIDGE_ACCOUNT_ID="ethbridge"

echo "Creating account to call prover:"
NODE_ENV=local yarn run near --nodeUrl=$NODE_URL --homeDir "$DIR/.near" --keyPath "$DIR/.near/validator_key.json" create_account $NEAR_CALLER_ACCOUNT_ID --masterAccount=$NEAR_MASTER_ACCOUNT_ID --initialBalance 100000000 || echo "Skip creating caller accout"
NODE_ENV=local yarn run near --nodeUrl=$NODE_URL --homeDir $NODE_ROOT --keyPath "$NODE_ROOT/validator_key.json" create_account $NEAR_CALLER_ACCOUNT_ID --masterAccount=$NEAR_MASTER_ACCOUNT_ID --initialBalance 100000000 || echo "Skip creating caller accout"
echo "Creating account for smart contract:"
NODE_ENV=local yarn run near --nodeUrl=$NODE_URL --homeDir "$DIR/.near" --keyPath "$DIR/.near/validator_key.json" create_account $NEAR_ETHPROVER_ACCOUNT_ID --masterAccount=$NEAR_MASTER_ACCOUNT_ID --initialBalance 100000000 || echo "Skip creating ethprover accout"
NODE_ENV=local yarn run near --nodeUrl=$NODE_URL --homeDir $NODE_ROOT --keyPath "$NODE_ROOT/validator_key.json" create_account $NEAR_ETHPROVER_ACCOUNT_ID --masterAccount=$NEAR_MASTER_ACCOUNT_ID --initialBalance 100000000 || echo "Skip creating ethprover accout"
echo "Deploying smart contract:"
NODE_ENV=local yarn run near --nodeUrl=$NODE_URL --homeDir "$DIR/.near" --keyPath "$DIR/.near/validator_key.json" deploy --contractName $NEAR_ETHPROVER_ACCOUNT_ID --wasmFile "$DIR/../res/eth_prover.wasm" || echo "Skip deploying ethprover smart contract"
NODE_ENV=local yarn run near --nodeUrl=$NODE_URL --homeDir $NODE_ROOT --keyPath "$NODE_ROOT/validator_key.json" deploy --contractName $NEAR_ETHPROVER_ACCOUNT_ID --wasmFile "$DIR/../res/eth_prover.wasm" || echo "Skip deploying ethprover smart contract"

NEAR_BLOCK_NUMBER=9591235
NEAR_EXPECTED_BLOCK_HASH="0x4825597982da98143abc4720083439ebd2e698637a2edd7565a2e198b18f17cd"

echo "Good block"
# Launch EthProver call
NEAR_NODE_URL=$NODE_URL \
NEAR_BLOCK_NUMBER=$NEAR_BLOCK_NUMBER \
Expand All @@ -69,18 +50,20 @@ NEAR_NODE_URL=$NODE_URL \
NEAR_CALLER_ACCOUNT_ID=$NEAR_CALLER_ACCOUNT_ID \
NEAR_ETHPROVER_ACCOUNT_ID=$NEAR_ETHPROVER_ACCOUNT_ID \
NEAR_ETHBRIDGE_ACCOUNT_ID=$NEAR_ETHBRIDGE_ACCOUNT_ID \
ETH_NODE_URL=$ETH_NODE_URL \
ETH_CONTRACT_ADDRESS=$ETH_CONTRACT_ADDRESS \
node "$DIR/../index.js"

NEAR_BLOCK_NUMBER=9591234
NEAR_EXPECTED_BLOCK_HASH="0x4825597982da98143abc4720083439ebd2e698637a2edd7565a2e198b18f17cd"
# NEAR_BLOCK_NUMBER=9591234
# NEAR_EXPECTED_BLOCK_HASH="0x4825597982da98143abc4720083439ebd2e698637a2edd7565a2e198b18f17cd"

echo "Bad block"
# Launch EthProver call
NEAR_NODE_URL=$NODE_URL \
NEAR_BLOCK_NUMBER=$NEAR_BLOCK_NUMBER \
NEAR_EXPECTED_BLOCK_HASH=$NEAR_EXPECTED_BLOCK_HASH \
NEAR_NODE_NETWORK_ID=default \
NEAR_CALLER_ACCOUNT_ID=$NEAR_CALLER_ACCOUNT_ID \
NEAR_ETHPROVER_ACCOUNT_ID=$NEAR_ETHPROVER_ACCOUNT_ID \
NEAR_ETHBRIDGE_ACCOUNT_ID=$NEAR_ETHBRIDGE_ACCOUNT_ID \
node "$DIR/index.js"
# echo "Bad block"
# # Launch EthProver call
# NEAR_NODE_URL=$NODE_URL \
# NEAR_BLOCK_NUMBER=$NEAR_BLOCK_NUMBER \
# NEAR_EXPECTED_BLOCK_HASH=$NEAR_EXPECTED_BLOCK_HASH \
# NEAR_NODE_NETWORK_ID=default \
# NEAR_CALLER_ACCOUNT_ID=$NEAR_CALLER_ACCOUNT_ID \
# NEAR_ETHPROVER_ACCOUNT_ID=$NEAR_ETHPROVER_ACCOUNT_ID \
# NEAR_ETHBRIDGE_ACCOUNT_ID=$NEAR_ETHBRIDGE_ACCOUNT_ID \
# node "$DIR/index.js"
2 changes: 0 additions & 2 deletions ethprover/src/lib.rs
Expand Up @@ -104,7 +104,6 @@ impl EthProver {
).into()
}

/*
pub fn verify_log_entry(
&self,
log_index: usize,
Expand Down Expand Up @@ -254,5 +253,4 @@ impl EthProver {

expected_value.len() == 0
}
*/
}

0 comments on commit 11c0344

Please sign in to comment.