fix: proof building in pos erc20 exit
MODIFY
src/pos/erc20.ts
src/pos/erc20.ts
@@ -109,11 +109,14 @@ export class ERC20 extends POSToken {
* @memberof ERC20
*/
withdrawExit(burnTransactionHash: string, option?: ITransactionOption) {
- return this.exitManager.exit(
+ return this.exitManager.buildPayloadForExit(
burnTransactionHash,
Log_Event_Signature.Erc20Transfer,
- option
+ ).then(payload => {
+ return this.rootChainManager.exit(
+ payload, option
);
+ });
}
/**
@@ -150,9 +153,4 @@ export class ERC20 extends POSToken {
);
}
- isCheckPointed(txHash: string) {
-
- }
-
-
}
\ No newline at end of file

MODIFY
src/pos/exit_manager.ts
src/pos/exit_manager.ts
@@ -7,6 +7,11 @@ import ethUtils from "ethereumjs-util";
import { ITransactionOption, ITransactionReceipt } from "src/interfaces";
import { NetworkService } from "../services";
+interface IChainBlockInfo {
+ lastChildBlock: string;
+ txBlockNumber: number;
+}
+
export class ExitManager {
private maticClient_: BaseWeb3Client;
@@ -14,9 +19,9 @@ export class ExitManager {
requestConcurrency: number;
- constructor(maticClient: BaseWeb3Client, rootChainManager: RootChain, requestConcurrency: number) {
+ constructor(maticClient: BaseWeb3Client, rootChain: RootChain, requestConcurrency: number) {
this.maticClient_ = maticClient;
- this.rootChain = rootChainManager;
+ this.rootChain = rootChain;
this.requestConcurrency = requestConcurrency;
}
@@ -24,7 +29,6 @@ export class ExitManager {
const payload = await this.buildPayloadForExit(
burnTxHash,
logSignature,
- this.requestConcurrency
);
const method = this.rootChain.method("exit", payload);
@@ -153,21 +157,59 @@ export class ExitManager {
return logIndex;
}
- async buildPayloadForExit(burnTxHash: string, logEventSig: string, requestConcurrency?) {
- // check checkpoint
- const [lastChildBlock, burnTx, receipt] = await Promise.all([
+ getChainBlockInfo(burnTxHash: string) {
+ return Promise.all([
this.rootChain.getLastChildBlock(),
this.maticClient_.getTransaction(burnTxHash),
- this.maticClient_.getTransactionReceipt(burnTxHash)
- ]);
+ ]).then(result => {
+ return {
+ lastChildBlock: result[0],
+ txBlockNumber: result[1].blockNumber
+ } as IChainBlockInfo;
+ });
+ }
+
+ private isCheckPointed_(data: IChainBlockInfo) {
+ // lastchild block is greater equal to transacton block number;
+ return new BN(data.lastChildBlock).gte(new BN(data.txBlockNumber));
+ }
+
+ async isCheckPointed(burnTxHash: string) {
+ return this.getChainBlockInfo(
+ burnTxHash
+ ).then(result => {
+ return this.isCheckPointed_(
+ result
+ );
+ });
+ }
- const block = await this.maticClient_.getBlockWithTransaction(burnTx.blockNumber);
+ async buildPayloadForExit(burnTxHash: string, logEventSig: string) {
+
+ const blockInfo = await this.getChainBlockInfo(
+ burnTxHash
+ );
+
+ if (!this.isCheckPointed_(blockInfo)) {
+ throw new Error(
+ 'Burn transaction has not been checkpointed as yet'
+ );
+ }
+
+ const { lastChildBlock, txBlockNumber } = blockInfo;
+
+ // check checkpoint
+ const [receipt, block] = await Promise.all([
+ this.maticClient_.getTransactionReceipt(burnTxHash),
+ this.maticClient_.getBlockWithTransaction(txBlockNumber)
+ ]);
assert.ok(
- new BN(lastChildBlock).gte(new BN(burnTx.blockNumber)),
+ new BN(lastChildBlock).gte(new BN(txBlockNumber)),
'Burn transaction has not been checkpointed as yet'
);
- const rootBlockNumber = await this.rootChain.findRootBlockFromChild(burnTx.blockNumber);
+
+ const rootBlockNumber = await this.rootChain.findRootBlockFromChild(txBlockNumber);
const rootBlockInfo = await this.rootChain.method(
"headerBlocks", formatAmount(rootBlockNumber)
@@ -178,14 +220,14 @@ export class ExitManager {
this.maticClient_,
parseInt(rootBlockInfo.start, 10),
parseInt(rootBlockInfo.end, 10),
- parseInt(burnTx.blockNumber + '', 10)
+ parseInt(txBlockNumber + '', 10)
);
const receiptProof: any = await ProofUtil.getReceiptProof(
receipt,
block,
this.maticClient_,
- requestConcurrency
+ this.requestConcurrency
);
const logIndex = this.getLogIndex_(
@@ -195,7 +237,7 @@ export class ExitManager {
return this._encodePayload(
rootBlockNumber,
blockProof,
- burnTx.blockNumber,
+ txBlockNumber,
block.timestamp,
Buffer.from(block.transactionsRoot.slice(2), 'hex'),
Buffer.from(block.receiptsRoot.slice(2), 'hex'),

MODIFY
src/pos/index.ts
src/pos/index.ts
@@ -57,4 +57,29 @@ export class POSClient {
this.exitManager
);
}
+
+ /**
+ * check whether a txHash is checkPointed
+ *
+ * @param {string} txHash
+ * @returns
+ * @memberof POSClient
+ */
+ isCheckPointed(txHash: string) {
+ return this.exitManager.isCheckPointed(
+ txHash
+ );
+ }
+
+ getBalanceUsingRPC() {
+ return this.client_.child.client.sendRPCRequest({
+ jsonrpc: '2.0',
+ method: 'eth_getBalance',
+ params: [
+ '0x0ef2e86a73c7be7f767d7abe53b1d4cbfbccbf3a',
+ 'latest'
+ ],
+ id: new Date().getTime()
+ });
+ }
}
\ No newline at end of file

MODIFY
src/pos/root_chain_manager.ts
src/pos/root_chain_manager.ts
@@ -30,4 +30,12 @@ export class RootChainManager extends BaseToken {
return this.processWrite(method, option);
}
+ async exit(payload: string, option: ITransactionOption) {
+ const method = this.method("exit", payload);
+ return this.processWrite(
+ method,
+ option
+ );
+ }
+
}
\ No newline at end of file

MODIFY
src/utils/merkle_tree.ts
src/utils/merkle_tree.ts
@@ -18,7 +18,14 @@ export class MerkleTree {
throw new Error('Depth must be 20 or less');
}
- this.leaves = leaves.concat(Array.from([Math.pow(2, depth) - leaves.length], () => utils.zeros(32)));
+ this.leaves = leaves.concat(
+ Array.from(
+ // tslint:disable-next-line
+ Array(Math.pow(2, depth) - leaves.length),
+ () => utils.zeros(32)
+ )
+ );
+ console.log("this.leaves", this.leaves, "leaves", leaves);
this.layers = [this.leaves];
this.createHashes(this.leaves);
}
@@ -28,10 +35,14 @@ export class MerkleTree {
return false;
}
+ console.log("nodes", nodes);
+
const treeLevel = [];
for (let i = 0; i < nodes.length; i += 2) {
const left = nodes[i];
const right = nodes[i + 1];
+ console.log("left", left, "right", right);
+
const data = SafeBuffer.concat([left, right]);
treeLevel.push(sha3(data));
}

MODIFY
src/utils/proof_util.ts
src/utils/proof_util.ts
@@ -72,7 +72,7 @@ export class ProofUtil {
// Build a merkle tree of correct size for the subtree using these merkle roots
const leaves = Array.from({ length: 2 ** heightDifference }, () => ethUtils.toBuffer(leafRoots));
leaves[0] = remainingNodesHash;
-
+ console.log("leaves", leaves);
const subTreeMerkleRoot = new MerkleTree(leaves).getRoot();
reversedProof.push(subTreeMerkleRoot);
}
@@ -94,19 +94,23 @@ export class ProofUtil {
);
}
- static async queryRootHash(web3: BaseWeb3Client, startBlock: number, endBlock: number) {
+ static async queryRootHash(client: BaseWeb3Client, startBlock: number, endBlock: number) {
try {
- return ethUtils.toBuffer(`0x${await web3.getRootHash(startBlock, endBlock)}`);
+ console.log("rootHash1");
+ const rootHash = await client.getRootHash(startBlock, endBlock);
+ console.log("rootHash", rootHash);
+ return ethUtils.toBuffer(`0x${rootHash}`);
} catch (err) {
+ console.error("err", err);
return null;
}
}
- static recursiveZeroHash(n: number, web3: BaseWeb3Client) {
+ static recursiveZeroHash(n: number, client: BaseWeb3Client) {
if (n === 0) return '0x0000000000000000000000000000000000000000000000000000000000000000';
- const subHash = this.recursiveZeroHash(n - 1, web3);
+ const subHash = this.recursiveZeroHash(n - 1, client);
return ethUtils.keccak256(
- ethUtils.toBuffer(web3.encodeParameters([subHash, subHash], ['bytes32', 'bytes32'],))
+ ethUtils.toBuffer(client.encodeParameters([subHash, subHash], ['bytes32', 'bytes32'],))
);
}

MODIFY
test/debug.js
test/debug.js
@@ -61,9 +61,11 @@ const execute = async () => {
// console.log('txHash', await approveResult.getTransactionHash());
// console.log('receipt', await approveResult.getReceipt());
- const approveResult = await childErc20.withdrawExit('0xe078925f8bbe43f99bb325cef6e895946f4086fbc05cf4686766b0a172fae396');
- console.log('txHash', await approveResult.getTransactionHash());
- console.log('receipt', await approveResult.getReceipt());
+ // const isCheckPointed = await maticPOS.isCheckPointed('0xbadbf10a33ba5ae48cfa1660e011eb15bf927773610ace9466c71d14749d4132');
+ // return console.log("isCheckPointed", isCheckPointed);
+ const exitResult = await childErc20.withdrawExit('0xe078925f8bbe43f99bb325cef6e895946f4086fbc05cf4686766b0a172fae396');
+ console.log('txHash', await exitResult.getTransactionHash());
+ console.log('receipt', await exitResult.getReceipt());

fix: proof building in pos erc20 exit