Skip to content

Commit

Permalink
Merge branch 'main' into citation
Browse files Browse the repository at this point in the history
  • Loading branch information
RafaelAPB authored Jun 29, 2023
2 parents 553b8ba + b415ce0 commit d483c06
Show file tree
Hide file tree
Showing 13 changed files with 1,461 additions and 97 deletions.
40 changes: 40 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
USER_PRIVATE_KEY=private_key
ALCHEMY_API_KEY=api_key
REDIS_HOST=localhost
REDIS_PORT=6379
PROVER_SERVER_HOST=http://127.0.0.1
PROVER_SERVER_PORT=5000
INITIAL_SLOT=5860953
SLOTS_JUMP=32
PRATTER=TRUE
MAINNET=FALSE
LC_GOERLI=0xf65B59bc947865490eF92D8461e8B5D0eA87c343
LC_OPTIMISTIC_GOERLI=
LC_BASE_GOERLI=
LC_ARBITRUM_GOERLI=
LC_SEPOLIA=
LC_MUMBAI=
LC_FUJI=
LC_FANTOM=
LC_ALFAJORES=
LC_BSC=
LC_AURORA=
LC_GNOSIS=
LC_CHIADO=
LC_EVMOS=
LC_MALAGA=
GOERLI_HASHI=0x4169ea397fe83F55e732E11390807b3722374f78
OPTIMISTIC_HASHI=''
BASE_HASHI=''
ARBITRUM_HASHI=''
SEPOLIA_HASHI=''
MUMBAI_HASHI=''
FANTOM_HASHI=''
ALFAJORES_HASHI=''
CHIADO_HASHI=''
EVMOS_HASHI=''
MALAGA_HASHI=''
AURORA_HASHI=''
GNOSIS_HASHI=''
FUJI_HASHI=''
BSC_HASHI=''
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ jobs:
- name: Run Verifier in Cosmos - Relayer test
run: nix develop -c yarn test './tests/cosmosLightClient/test-verifier-in-cosmos-relay.ts'

- name: Run Solidity Validators accumulator tests
run: nix develop -c make test-validator-accumulator

# - name: Run Verifier in EOS test
# run: nix develop -c yarn test './tests/eosLightClient/test-verifier-in-EOS.ts'

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.relay
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ COPY ./scripts ./scripts
ENV INFURA_API_KEY=asd ETHERSCAN_API_KEY=asd
RUN cd beacon-light-client/solidity && yarn hardhat compile

VOLUME relayvolume DendrETH/build
VOLUME DendrETH/data

ENTRYPOINT ["./relay/run-relay.sh"]
13 changes: 10 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@ yarn-check:
echo "Please run yarn install"; exit 1; \
}

.PHONY: build-relay-image
build-relay-image:
.PHONY: dendreth-relay-node
dendreth-relay-node:
nix run '.#docker-image-yarn.copyToDockerDaemon'
nix run '.?submodules=1#docker-image-all.copyToDockerDaemon'

docker build -t relayimage -f Dockerfile.relay .
docker build -t metacraft/dendeth-relay-node -f Dockerfile.relay .

publish-dendreth-relay-node: dendreth-relay-node
docker push metacraft/dendeth-relay-node

test-validator-accumulator: yarn-check
cd beacon-light-client/solidity && \
yarn hardhat test test/ValidatorAccumulator.test.ts

evm-simulation: yarn-check
cd beacon-light-client/solidity && \
Expand Down
90 changes: 27 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,53 +119,58 @@ You should see a [Hardhat simulation](https://hardhat.org/hardhat-runner/docs/ge
sequentially processing all available updates. At the time of this writing, each
update costs around 330K in gas.

### Run relayer
### Running the DendrETH relay node

To run the relayer you can execute
The DendrETH relay node efficiently generates proofs and publishes updates for
all blockchains supported by the DendrETH project. To simplify the process of
running a relay, we provide up-to-date Docker images.

```bash
make build-relay-image
```
> You can also build a custom image yourself by executing the
> `make dendreth-relay-node` command within the development environment
> provided by this repository.
Which will build the relayimage for you. To run it
To run the relay node, please follow these steps:

You can also pull the image from docker hub

```
docker pull dimaranti/dendreth
```
1. Ensure that you have Docker installed on your system.
2. Open a terminal or command prompt.
3. Execute the following command:

```bash
docker run -it --env-file .env -v relayvolume:/DendrETH/build relayimage
docker run --env-file .env -v relay-node-data:/DendrETH/data metacraft/dendreth-relay-node
```

Passing the .env file with needed configurations.
This command assumes that you want to store all runtime data in a local directory
called `relay-node-data`. If you prefer to use a different directory, please modify
the command accordingly.

The .env file must contain the following things
The provided `.env` file must supply the following variables:

For accessing the networks and signing transactions:
#### For accessing the networks and signing transactions:

```bash
USER_PRIVATE_KEY=private_key
ALCHEMY_API_KEY=api_key
```

To configure from which slot should the relayer start generating updates. And what step it should use
#### To configure the starting point and frequency of updates:

```bash
INITIAL_SLOT=5355991
SLOTS_JUMP=64
```

To configure relayer what network it should follow. Currently the script only supports following one network. You can mannually run the tasks for publishing and updating on a second network.
#### To configure which networks should be followed:

```bash
PRATTER=TRUE
MAINNET=FALSE
FOLLOW_NETWORK=pratter
```

You can also provide for addresses on different networks if you skip a network transactions won't be broadcasted to it
Currently the scripts within the container support following a single network.
You can manually run the tasks for publishing updates on a second network.

#### To specify the deployed instances of the DendrETH smart contracts:

```bash
LC_GOERLI=0xf65B59bc947865490eF92D8461e8B5D0eA87c343
Expand All @@ -180,52 +185,11 @@ LC_CHIADO=0xAa5eeb05D0B080b366CB6feA00d16216B24FB9bE
LC_EVMOS=0x8E4D36CD13015EA6F384cab3342156b3dC5d0a53
```

And also it needs to contain the hashi adapter addresses

Sample `.env`
If you skip some of these variables, the relay node won't publish updates for
the particular network.

```
USER_PRIVATE_KEY=private_key
ALCHEMY_API_KEY=api_key
REDIS_HOST=localhost
REDIS_PORT=6379
PROVER_SERVER_HOST=http://127.0.0.1
PROVER_SERVER_PORT=5000
INITIAL_SLOT=5860953
SLOTS_JUMP=32
PRATTER=TRUE
MAINNET=FALSE
LC_GOERLI=0xf65B59bc947865490eF92D8461e8B5D0eA87c343
LC_OPTIMISTIC_GOERLI=
LC_BASE_GOERLI=
LC_ARBITRUM_GOERLI=
LC_SEPOLIA=
LC_MUMBAI=
LC_FUJI=
LC_FANTOM=
LC_ALFAJORES=
LC_BSC=
LC_AURORA=
LC_GNOSIS=
LC_CHIADO=
LC_EVMOS=
LC_MALAGA=
GOERLI_HASHI=0x4169ea397fe83F55e732E11390807b3722374f78
OPTIMISTIC_HASHI=''
BASE_HASHI=''
ARBITRUM_HASHI=''
SEPOLIA_HASHI=''
MUMBAI_HASHI=''
FANTOM_HASHI=''
ALFAJORES_HASHI=''
CHIADO_HASHI=''
EVMOS_HASHI=''
MALAGA_HASHI=''
AURORA_HASHI=''
GNOSIS_HASHI=''
FUJI_HASHI=''
BSC_HASHI=''
```
For a full list of supported ENV variables, please see the provided
[example .env file](.env.example).

### How does the relayer work?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ function getValidatorTree(validator, ssz): Tree {
return new Tree(validatorView.node);
}

function calculateValidatorsAccumulator(
// TODO: fix so it matches the test in beacon-light-client/solidity
export function calculateValidatorsAccumulator(
validatorsPubkeys: Uint8Array[],
eth1DepositIndexes: BigInt[],
) {
Expand All @@ -41,7 +42,7 @@ function calculateValidatorsAccumulator(
);
}

const validatorsAccumulator = hexToBytes(hashTreeRoot(leaves));
const validatorsAccumulator = hexToBytes(hashTreeRoot(leaves, leaves.length));

return bytesToBinaryArray(validatorsAccumulator);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
`validatorsAccumulator` is a Merkle tree accumulator that contains the public keys of validators and their corresponding Eth1 deposit indexes.
The purpose of storing the Eth1 deposit index is to ascertain whether a particular validator is already a participant in the beacon chain.

A Merkle tree accumulator is a binary tree of hashes, which is used for efficiently proving membership of an element in a set. In this context, the set comprises of validators.

This is a sample solidity implementation of the `validatorsAccumulator`

```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
// This interface is designed to be compatible with the Vyper version.
/// @notice This is the Ethereum 2.0 deposit contract interface.
/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs
interface IDepositContract {
/// @notice A processed deposit event.
event DepositEvent(
bytes pubkey,
bytes withdrawal_credentials,
bytes amount,
bytes signature,
bytes index
);
/// @notice Submit a Phase 0 DepositData object.
/// @param pubkey A BLS12-381 public key.
/// @param withdrawal_credentials Commitment to a public key for withdrawals.
/// @param signature A BLS12-381 signature.
/// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object.
/// Used as a protection against malformed input.
function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) external payable;
/// @notice Query the current deposit root hash.
/// @return The deposit root hash.
function get_deposit_root() external view returns (bytes32);
/// @notice Query the current deposit count.
/// @return The deposit count encoded as a little endian 64-bit number.
function get_deposit_count() external view returns (bytes memory);
}
contract ValidatorsAccumulator {
address depositAddress;
// The depth of the validator accumulator tree
uint constant VALIDATOR_ACCUMULATOR_TREE_DEPTH = 32;
// An array to hold the branch hashes for the Merkle tree
bytes32[VALIDATOR_ACCUMULATOR_TREE_DEPTH] branch;
bytes32[VALIDATOR_ACCUMULATOR_TREE_DEPTH] zero_hashes;
// A counter for the total number of validators
uint validators_count;
constructor(address _depositAddress) {
depositAddress = _depositAddress;
// Compute hashes in empty Merkle tree
for (
uint height = 0;
height < VALIDATOR_ACCUMULATOR_TREE_DEPTH - 1;
height++
)
zero_hashes[height + 1] = sha256(
abi.encodePacked(zero_hashes[height], zero_hashes[height])
);
}
// Function to calculate and return the Merkle accumulator root of the validators
function get_validators_accumulator() external view returns (bytes32) {
bytes32 node;
uint size = validators_count;
// Calculate the Merkle accumulator root
for (uint height = 0; height < VALIDATOR_ACCUMULATOR_TREE_DEPTH; height++) {
// This if-else structure supports tree balancing
// If size is odd, the new node will be hashed with the previous node on this level
// If size is even, the new node will be hashed with a predefined zero hash
if ((size & 1) == 1)
node = sha256(abi.encodePacked(branch[height], node));
else node = sha256(abi.encodePacked(node, zero_hashes[height]));
size /= 2;
}
return node;
}
// Function to handle deposits from validators
function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) public payable {
// Perform the deposit using the DepositContract
IDepositContract(depositAddress).deposit{value: msg.value}(
pubkey,
withdrawal_credentials,
signature,
deposit_data_root
);
// Get the deposit count and increase the validator count
bytes memory deposit_index = IDepositContract(depositAddress)
.get_deposit_count();
validators_count += 1;
// Create a node for the validator
bytes32 node = sha256(abi.encodePacked(pubkey, deposit_index));
// Insert the node into the Merkle accumulator tree
uint size = validators_count;
for (uint height = 0; height < VALIDATOR_ACCUMULATOR_TREE_DEPTH; height++) {
if ((size & 1) == 1) {
branch[height] = node;
return;
}
node = sha256(abi.encodePacked(branch[height], node));
size /= 2;
}
}
}
```

In the deposit function, each validator's public key and their Eth1 deposit index are packed together and hashed to form a node. This node represents the validator in the Merkle tree.

The node is then inserted into the Merkle tree at the appropriate level, based on the current number of validators. The path to insert the node is determined using the binary representation of the total validator count. The leftmost branch is taken for every 0, and the rightmost branch for every 1.

The get_validators_accumulator function calculates and returns the Merkle root of the validatorsAccumulator. This root is a single hash that effectively represents all the validators in the accumulator.
Loading

0 comments on commit d483c06

Please sign in to comment.