Skip to content

Commit

Permalink
Fix prover promise and header encoding. Fixes #114 . Fixes #140 (#141)
Browse files Browse the repository at this point in the history
* Fix prover promise and header encoding. Fixes #114 . Fixes #140

* Rebuild contract

* Typo
  • Loading branch information
MaksymZavershynskyi committed Jul 6, 2020
1 parent 9ebfc65 commit db81dc3
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 195 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Now start the services that will relay the information between the chains:
```bash
node index.js start eth-relay
node index.js start near-relay --eth-master-sk 0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201
node index.js start near-watchdog --eth-master-sk 0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201
node index.js start near-watchdog --eth-master-sk 0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501202
```

Note, you can observe the logs of the relays by running:
Expand Down
26 changes: 10 additions & 16 deletions environment/commands/clean.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,22 @@ const ProcessManager = require('pm2');

class CleanCommand {
static execute () {
console.log('Stopping all the running processess...');
console.log('Stopping all the running processes...');
ProcessManager.killDaemon((err) => {
if (err) {
console.log(`Error stopping pm2 processes. ${err}`);
process.exit(1);
}
// @ts-ignore
ProcessManager.disconnect((err) => {
if (err) {
process.exit(1);
}
});
try {
execSync('python3 ~/.rainbowup/nearup/main.py stop');
} catch (err) {
console.log(`Error stopping nearup ${err}`);
}
console.log('Cleaning ~/.rainbowup , ~/.nearup , and ~/.near directories...');
execSync('rm -rf ~/.rainbowup && rm -rf ~/.nearup && rm -rf ~/.near');
console.log('Cleaning done...');
process.exit(0)
});
try {
execSync('python3 ~/.rainbowup/nearup/main.py stop');
} catch (err) {
console.log(`Error stopping nearup ${err}`);
}
console.log('Cleaning ~/.rainbowup , ~/.nearup , and ~/.near directories...');
execSync('rm -rf ~/.rainbowup && rm -rf ~/.nearup && rm -rf ~/.near');
console.log('Cleaning done...');
process.exit(0)
}
}

Expand Down
4 changes: 2 additions & 2 deletions environment/commands/eth-dump.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class ETHDump {
}
const block = await extractor.extractBlock(receipt.blockNumber);
const tree = await extractor.buildTrie(block);
const proof = await extractor.extractProof(block, tree, receipt.transactionIndex);
const proof = await extractor.extractProof(web3, block, tree, receipt.transactionIndex);
let log_index = -1;
for (const log of receipt.logs) {
log_index++;
Expand All @@ -83,7 +83,7 @@ class ETHDump {

const log_entry_data = logFromWeb3(log).serialize();
const receipt_data = receiptFromWeb3(receipt).serialize();
const header_data = proof.header.serialize();
const header_data = proof.header_rlp;
const _proof = [];
for (const node of proof.receiptProof) {
_proof.push(utils.rlp.encode(node));
Expand Down
9 changes: 5 additions & 4 deletions environment/commands/transfer-eth-erc20-to-near.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class TransferETHERC20ToNear {
const receipt = await extractor.extractReceipt(lockedEvent.transactionHash);
const block = await extractor.extractBlock(receipt.blockNumber);
const tree = await extractor.buildTrie(block);
const proof = await extractor.extractProof(block, tree, receipt.transactionIndex);
const proof = await extractor.extractProof(web3, block, tree, receipt.transactionIndex);

let txLogIndex = -1;
let logFound = false;
Expand All @@ -118,7 +118,7 @@ class TransferETHERC20ToNear {
const log_entry_data = logFromWeb3(log).serialize();
const receipt_index = proof.txIndex;
const receipt_data = receiptFromWeb3(receipt).serialize();
const header_data = proof.header.serialize();
const header_data = proof.header_rlp;
const _proof = [];
for (const node of proof.receiptProof) {
_proof.push(utils.rlp.encode(node));
Expand All @@ -144,9 +144,10 @@ class TransferETHERC20ToNear {
while (true) {
// @ts-ignore
const last_block_number = (await ethClientContract.last_block_number()).toNumber();
if (last_block_number < blockNumber) {
const is_safe = await ethClientContract.block_hash_safe(blockNumber);
if (!is_safe) {
const delay = 10;
console.log(`Eth2NearClient is currently at block ${last_block_number}. Waiting for block ${blockNumber}. Sleeping for ${delay} sec.`);
console.log(`Eth2NearClient is currently at block ${last_block_number}. Waiting for block ${blockNumber} to be confirmed. Sleeping for ${delay} sec.`);
await sleep(delay * 1000);
} else {
break;
Expand Down
54 changes: 24 additions & 30 deletions environment/lib/eth-proof-extractor/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const Web3 = require('web3');
const Tree = require('merkle-patricia-tree');
const utils = require('ethereumjs-util');
const {
Header,
Proof,
Receipt,
Log,
Expand Down Expand Up @@ -57,42 +57,36 @@ class EthProofExtractor {
return tree;
}

async extractProof (block, tree, transactionIndex) {
async extractProof (web3, block, tree, transactionIndex) {
const [, , stack] = await promisfy(tree.findPath, tree)(encode(transactionIndex));

const blockData = await web3.eth.getBlock(block.number);
// Correctly compose and encode the header.
const header = [
blockData.parentHash,
blockData.sha3Uncles,
blockData.miner,
blockData.stateRoot,
blockData.transactionsRoot,
blockData.receiptsRoot,
blockData.logsBloom,
blockData.difficulty == "0" ? "0x": web3.utils.toHex(blockData.difficulty),
web3.utils.toHex(blockData.number),
web3.utils.toHex(blockData.gasLimit),
web3.utils.toHex(blockData.gasUsed),
web3.utils.toHex(blockData.timestamp),
blockData.extraData,
blockData.mixHash,
blockData.nonce,
];

return {
header: Header.fromRpc(block),
header_rlp: utils.rlp.encode(header),
receiptProof: Proof.fromStack(stack),
txIndex: transactionIndex,
};
}

// Print debug information for the given transaction.
async debugPrint (txHash) {
const receipt = await this.extractReceipt(txHash);
console.log('RECEIPT %s', receipt);
const block = await this.extractBlock(receipt.blockNumber);
const tree = await this.buildTrie(block);
const proof = await this.extractProof(block, tree, receipt.transactionIndex);

console.log('let receipt_index = ' + proof.txIndex + ';');
console.log('let header_data = Vec::from_hex("' + proof.header.serialize().toString('hex') + '").unwrap();');
console.log('let receipt_data = Vec::from_hex("' + receiptFromWeb3(receipt).serialize().toString('hex') + '").unwrap();');
let logs = '';
for (const log of receipt.logs) {
logs += 'Vec::from_hex("' + logFromWeb3(log).serialize().toString('hex') + '").unwrap(),';
}
console.log(`let logs = vec![ ${logs} ]`);
console.log('let proof = vec![');
for (const rec of proof.receiptProof) {
console.log(' vec![');
for (const r of rec) {
console.log(' Vec::from_hex("' + r.toString('hex') + '").unwrap(),');
}
console.log(' ],');
}
console.log('];');
}

destroy () {
if (this.web3.currentProvider.connection.close) { // Only WebSocket provider has close, HTTPS don't
this.web3.currentProvider.connection.close();
Expand Down
8 changes: 3 additions & 5 deletions environment/lib/eth2near-relay.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,12 @@ class Eth2NearRelay {
const blockRlp = this.web3.utils.bytesToHex(web3BlockToRlp(await this.web3.eth.getBlock(clientBlockNumber + 1)));
const unparsedBlock = await execute(`./vendor/ethashproof/cmd/relayer/relayer ${blockRlp} | sed -e '1,/Json output/d'`);
const block = JSON.parse(unparsedBlock);
this.submitBlock(block, clientBlockNumber + 1).catch((e) => {
console.error(e);
process.exit(2);
});
await sleep(10000);
await this.submitBlock(block, clientBlockNumber + 1);
} catch (e) {
console.log(`Failed to submit a block ${e}`);
}
} else {
await sleep(10000);
}
}
}
Expand Down
108 changes: 0 additions & 108 deletions environment/lib/near-relay/index.js

This file was deleted.

2 changes: 1 addition & 1 deletion environment/scripts/start_ganache.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ set -euo pipefail

SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
cd $SCRIPTS_DIR/../vendor/ganache
yarn run ganache-cli --port 9545 --blockTime 12 --gasLimit 10000000 --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200,10000000000000000000000000000" --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201,10000000000000000000000000000"
yarn run ganache-cli --port 9545 --blockTime 12 --gasLimit 10000000 --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200,10000000000000000000000000000" --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201,10000000000000000000000000000" --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501202,10000000000000000000000000000"
33 changes: 18 additions & 15 deletions libs-rs/eth-prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,33 +116,36 @@ impl EthProver {
#[serializer(borsh)] header_data: Vec<u8>,
#[serializer(borsh)] proof: Vec<Vec<u8>>,
#[serializer(borsh)] skip_bridge_call: bool,
) -> bool {
) -> PromiseOrValue<bool> {
let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).unwrap();
let receipt: Receipt = rlp::decode(receipt_data.as_slice()).unwrap();
let header: BlockHeader = rlp::decode(header_data.as_slice()).unwrap();

// Verify block header was in the bridge
if !skip_bridge_call {
eth_client::block_hash_safe(header.number, &self.bridge_smart_contract, 0, 10000000000000).then(
remote_self::on_block_hash(
header.hash.unwrap(),
&env::current_account_id(),
0,
env::prepaid_gas()/2,
),
);
}

// Verify log_entry included in receipt
assert_eq!(receipt.logs[log_index as usize], log_entry);

// Verify receipt included into header
Self::verify_trie_proof(
let verification_result = Self::verify_trie_proof(
header.receipts_root,
rlp::encode(&receipt_index),
proof,
receipt_data,
)
);
if verification_result && skip_bridge_call {
return PromiseOrValue::Value(true);
} else if !verification_result {
return PromiseOrValue::Value(false);
}

// Verify block header was in the bridge
eth_client::block_hash_safe(header.number, &self.bridge_smart_contract, 0, 10000000000000).then(
remote_self::on_block_hash(
header.hash.unwrap(),
&env::current_account_id(),
0,
env::prepaid_gas()/2,
),
).into()
}

/// Iterate the proof following the key.
Expand Down

0 comments on commit db81dc3

Please sign in to comment.