Skip to content

Commit

Permalink
feat(relay): Make relayer work with new version of hashi adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimo99 authored and zah committed Jun 28, 2023
1 parent 36ddbfe commit 85135e0
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ contract BeaconLightClient is LightClientUpdateVerifier, ILightClient {
return executionStateRoots[currentIndex];
}

// TODO: fix
// TODO: fix name to lightClientUpdate
function light_client_update(LightClientUpdate calldata update)
external
payable
Expand Down
85 changes: 85 additions & 0 deletions beacon-light-client/solidity/tasks/hashi_abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@
"name": "InvalidBlockNumberProof",
"type": "error"
},
{
"inputs": [],
"name": "InvalidUpdate",
"type": "error"
},
{
"anonymous": false,
"inputs": [
Expand Down Expand Up @@ -203,5 +208,85 @@
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "_chainId",
"type": "uint32"
},
{
"internalType": "uint64",
"name": "_slot",
"type": "uint64"
},
{
"internalType": "uint256",
"name": "_blockNumber",
"type": "uint256"
},
{
"internalType": "bytes32[]",
"name": "_blockNumberProof",
"type": "bytes32[]"
},
{
"internalType": "bytes32",
"name": "_blockHash",
"type": "bytes32"
},
{
"internalType": "bytes32[]",
"name": "_blockHashProof",
"type": "bytes32[]"
},
{
"components": [
{
"internalType": "bytes32",
"name": "attestedHeaderRoot",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "attestedHeaderSlot",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "finalizedHeaderRoot",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "finalizedExecutionStateRoot",
"type": "bytes32"
},
{
"internalType": "uint256[2]",
"name": "a",
"type": "uint256[2]"
},
{
"internalType": "uint256[2][2]",
"name": "b",
"type": "uint256[2][2]"
},
{
"internalType": "uint256[2]",
"name": "c",
"type": "uint256[2]"
}
],
"internalType": "struct LightClientUpdate",
"name": "update",
"type": "tuple"
}
],
"name": "storeBlockHeader",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
33 changes: 33 additions & 0 deletions relay/implementations/publish_evm_transaction.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BigNumber, Contract } from 'ethers';
import Web3 from 'web3';
import { FeeHistoryResult } from 'web3-eth';
import { groth16 } from 'snarkjs';

type Block = {
number: number | string;
Expand Down Expand Up @@ -104,6 +105,38 @@ export async function publishTransaction(
}
}

export async function getSolidityProof(update: {
a: string[];
b: string[][];
c: string[];
}): Promise<{
a: string[];
b: string[][];
c: string[];
}> {
const calldata = await groth16.exportSolidityCallData(
{
pi_a: update.a,
pi_b: update.b,
pi_c: update.c,
},
[],
);

const argv: string[] = calldata
.replace(/["[\]\s]/g, '')
.split(',')
.map(x => BigInt(x).toString());

const a = [argv[0], argv[1]];
const b = [
[argv[2], argv[3]],
[argv[4], argv[5]],
];
const c = [argv[6], argv[7]];
return { a, b, c };
}

async function getGasPrice(web3: Web3, transactionSpeed: TransactionSpeed) {
const formattedBlocks = formatFeeHistory(
await web3.eth.getFeeHistory(historicalBlocks, 'pending', [1, 50, 99]),
Expand Down
23 changes: 2 additions & 21 deletions relay/implementations/solidity-contract.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Contract } from 'ethers';
import { ISmartContract } from '../abstraction/smart-contract-abstraction';
import { groth16 } from 'snarkjs';
import Web3 from 'web3';
import {
TransactionSpeed,
getSolidityProof,
publishTransaction,
} from './publish_evm_transaction';

Expand Down Expand Up @@ -35,26 +35,7 @@ export class SolidityContract implements ISmartContract {
b: string[][];
c: string[];
}): Promise<any> {
const calldata = await groth16.exportSolidityCallData(
{
pi_a: update.a,
pi_b: update.b,
pi_c: update.c,
},
[],
);

const argv: string[] = calldata
.replace(/["[\]\s]/g, '')
.split(',')
.map(x => BigInt(x).toString());

const a = [argv[0], argv[1]];
const b = [
[argv[2], argv[3]],
[argv[4], argv[5]],
];
const c = [argv[6], argv[7]];
const { a, b, c } = await getSolidityProof(update);

await publishTransaction(
this.lightClientContract,
Expand Down
26 changes: 17 additions & 9 deletions relay/on_chain_publisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ISmartContract } from './abstraction/smart-contract-abstraction';
import { Contract } from 'ethers';
import {
TransactionSpeed,
getSolidityProof,
publishTransaction,
} from './implementations/publish_evm_transaction';
import Web3 from 'web3';
Expand Down Expand Up @@ -141,33 +142,40 @@ export async function postUpdateOnChain(

console.log(update);

await lightClientContract.postUpdateOnChain({
...update,
a: proofResult.proof.pi_a,
b: proofResult.proof.pi_b,
c: proofResult.proof.pi_c,
});

if (hashiAdapterContract) {
const hashiInfo = await beaconApi.getHashiAdapterInfo(
proofResult.proofInput.nextHeaderSlot,
);

const solidityProof = await getSolidityProof({
a: proofResult.proof.pi_a,
b: proofResult.proof.pi_b,
c: proofResult.proof.pi_c,
});

await publishTransaction(
hashiAdapterContract,
'storeBlockHeader',
'storeBlockHeader(uint32,uint64,uint256,bytes32[],bytes32,bytes32[],(bytes32,uint256,bytes32,bytes32,uint256[2],uint256[2][2],uint256[2]))',
[
(await hashiAdapterContract.provider.getNetwork()).chainId,
proofResult.proofInput.nextHeaderSlot,
hashiInfo.blockNumber,
hashiInfo.blockNumberProof.map(x => '0x' + x),
'0x' + hashiInfo.blockHash,
hashiInfo.blockHashProof.map(x => '0x' + x),
{ ...update, ...solidityProof },
],
new Web3(rpcEndpoint),
transactionSpeed,
true,
);
} else {
await lightClientContract.postUpdateOnChain({
...update,
a: proofResult.proof.pi_a,
b: proofResult.proof.pi_b,
c: proofResult.proof.pi_c,
});
}

const transactionSlot = proofResult.proofInput.nextHeaderSlot;
Expand Down Expand Up @@ -203,7 +211,7 @@ async function handleFailure(
isDrainRunning = false;
return [failedNumber, isDrainRunning];
}
log(error, 'ERROR occurred in ${scopeError}', 'will retry');
log(error, `ERROR occurred in ${scopeError}`, 'will retry');
failedNumber++;
await sleep(10000);

Expand Down

0 comments on commit 85135e0

Please sign in to comment.