Skip to content

Commit

Permalink
feat: hive docker (#764)
Browse files Browse the repository at this point in the history
* feat: first commit to get things started

* feat: start.sh

* update docker

* update dockerfile

* update dockerfile and start

* update hive docker and script

* fix start.sh

* change the way chain id is set at launch

* fix infinite recursion

* update the hive dockerfile

---------

Co-authored-by: Gregory Edison <[email protected]>
  • Loading branch information
Eikix and greged93 committed Feb 22, 2024
1 parent 56379e7 commit 487fbbd
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 6 deletions.
112 changes: 112 additions & 0 deletions docker/hive/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# trunk-ignore-all(terrascan/AC_DOCKER_0047)

# CairoVM Chain
FROM ghcr.io/dojoengine/dojo:v0.5.1 as katana

# Indexer service
### Apibara DNA indexer and indexer
FROM quay.io/apibara/starknet:1.2.0 as apibara
FROM quay.io/apibara/sink-mongo as indexer
FROM debian:bookworm as apibara-build
RUN apt-get update && apt-get install -y patchelf && rm -rf /var/lib/apt/lists/*
# Run `docker image inspect apibara/starknet:1.2.0` to get the exact path
COPY --from=apibara /nix/store/swzxd9vbhhj92qzh16j48vb011q57v59-apibara-starknet-1.2.0/bin/apibara-starknet /usr/local/bin/starknet
COPY --from=indexer /nix/store/3iqnrcirqpg4s7zdy1wdh0dq17jwzmlc-apibara-sink-mongo-0.5.3/bin/apibara-sink-mongo /usr/local/bin/sink-mongo
# Change the interpreter path.
ARG BUILDPLATFORM
RUN case $BUILDPLATFORM in \
"linux/amd64") \
patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 /usr/local/bin/starknet && \
patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 /usr/local/bin/sink-mongo; \
;; \
"linux/arm64") \
patchelf --set-interpreter /lib/ld-linux-aarch64.so.1 /usr/local/bin/starknet && \
patchelf --set-interpreter /lib/ld-linux-aarch64.so.1 /usr/local/bin/sink-mongo; \
;; \
*) \
echo "Unknown BUILDPLATFORM: $BUILDPLATFORM"; \
exit 1; \
;; \
esac

### Indexer transform plugin
#### First, clone the indexer repository
FROM docker.io/alpine/git:latest as indexer-cloner
WORKDIR /code
RUN git clone -v "https://github.com/kkrt-labs/kakarot-indexer.git"

#### MongoDB
FROM mongo:6.0.8 as mongo

# Ethereum RPC Server
FROM ghcr.io/kkrt-labs/kakarot-rpc/node:v0.2.3-2 as rpc

FROM debian:bookworm-slim as base
# Install any necessary dependencies
RUN apt-get update && apt-get install -y tini curl jq && rm -rf /var/lib/apt/lists/*

# Environment
#############
### Indexer environment variables
#### Indexer environment variables
ENV ALLOW_ENV_FROM_ENV=DEBUG,APIBARA_AUTH_TOKEN,STARTING_BLOCK,STREAM_URL,SINK_TYPE,MONGO_CONNECTION_STRING,MONGO_DATABASE_NAME
ENV DEBUG=""
ENV APIBARA_AUTH_TOKEN=""
ENV MONGO_CONNECTION_STRING=mongodb://localhost:27017
ENV MONGO_DATABASE_NAME=kakarot-local
ENV STARTING_BLOCK=0
ENV STREAM_URL=http://localhost:7171
ENV SINK_TYPE=mongo
### Kakarot RPC environment variables
### Port 8545: https://github.com/ethereum/hive/blob/master/simulators/ethereum/rpc/helper.go#L50
ENV KATANA_ACCOUNT_ADDRESS=0x01b44e32c8edbcada35fa7ae6f1f44bbc16657f442b7b19286812e1976c34d83
ENV KATANA_PRIVATE_KEY=0x05b8e27acc53020ed612507af8245cbffafd8aa588b79decaee1acf99a1c5cc2
ENV KAKAROT_RPC_URL=0.0.0.0:8545
ENV STARKNET_NETWORK=http://localhost:5050
ENV RUST_LOG=kakarot_rpc=info

HEALTHCHECK --interval=10s --timeout=10s --start-period=15s --retries=5 \
CMD response=$(curl --silent --request POST \
--header "Content-Type: application/json" \
--data '{"jsonrpc": "2.0", "method": "eth_getBlockByNumber", "params": ["latest", true], "id": 1}' \
http://${KAKAROT_RPC_URL} | jq -e '.result != null') && echo $response && [ "$response" = "true" ] || exit 1


# Ports
#######
# 8545 Ethereum RPC
# 27017 MongoDB
EXPOSE 8545 27017

# Copy binaries and dependencies
################################
### CairoVM chain service
COPY --from=katana /usr/local/bin/katana /usr/local/bin

### Indexer service
#### We need the DNA indexer binary
COPY --from=apibara-build /usr/local/bin/starknet /usr/local/bin/starknet

#### We need the indexer typescript code and the binary that knows how to run it
COPY --from=indexer-cloner /code /usr/src/app/code
COPY --from=apibara-build /usr/local/bin/sink-mongo /usr/local/bin/sink-mongo

#### We need the mongo binary
COPY --from=mongo /bin/mongod /usr/local/bin
RUN mkdir -p /data/db


# Generate the genesis
COPY --from=rpc /usr/local/bin/kakarot-rpc-hive /usr/local/bin/kakarot-rpc
COPY --from=rpc /usr/local/bin/hive_genesis /usr/local/bin
RUN mkdir -p /genesis/contracts
COPY ./lib/kakarot/build /genesis/contracts
COPY ./docker/hive/genesis.json /genesis/hive-genesis.json

# Copy start script
COPY docker/hive/start.sh /start.sh
RUN chmod +x /start.sh

ENTRYPOINT ["/usr/bin/tini", "--", "/start.sh"]

CMD []
Binary file added docker/hive/docs/hive_strategy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions docker/hive/genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"config": {
"chainId": 7,
"homesteadBlock": 0,
"eip150Block": 0,
"eip150Hash": "0x5de1ee4135274003348e80b788e5afa4b18b18d320a5622218d5c493fedf5689",
"eip155Block": 0,
"eip158Block": 0
},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x2fefd8",
"nonce": "0x0000000000000000",
"timestamp": "0x1234",
"alloc": {
"cf49fda3be353c69b41ed96333cd24302da4556f": {
"balance": "0x123450000000000000000"
},
"0161e041aad467a890839d5b08b138c1e6373072": {
"balance": "0x123450000000000000000"
},
"87da6a8c6e9eff15d703fc2773e32f6af8dbe301": {
"balance": "0x123450000000000000000"
},
"b97de4b8c857e4f6bc354f226dc3249aaee49209": {
"balance": "0x123450000000000000000"
},
"c5065c9eeebe6df2c2284d046bfc906501846c51": {
"balance": "0x123450000000000000000"
},
"0000000000000000000000000000000000000314": {
"balance": "0x0",
"code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x1234",
"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x01"
}
},
"0000000000000000000000000000000000000315": {
"balance": "0x9999999999999999999999999999999",
"code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029"
}
}
}
51 changes: 51 additions & 0 deletions docker/hive/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# 1. Create the genesis file
echo "Creating the genesis file..."
KAKAROT_CONTRACTS_PATH="genesis/contracts" \
HIVE_GENESIS_PATH="genesis/hive-genesis.json" \
GENESIS_OUTPUT="genesis.json" \
MANIFEST_OUTPUT="manifest.json" \
hive_genesis
mv /genesis/hive-genesis.json /hive-genesis.json && rm -fr /genesis

# 2. Start Katana
echo "Launching Katana..."
RUST_LOG=warn katana --block-time 2000 --disable-fee --chain-id=0x$(jq -r '.config.chainId' hive-genesis.json) --genesis genesis.json &
###### 2.5. Await Katana to be healthy
# Loop until the curl command succeeds
until
curl --silent --request POST \
--header "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "starknet_blockNumber",
"params": [],
"id": 1
}' \
"${STARKNET_NETWORK}" # Use the provided network address
do
echo "Waiting for Katana to start..."
sleep 1
done

# 3. Start the Indexer service: DNA Indexer, Indexer transformer, and MongoDB
## MongoDB
echo "Launching mongo..."
mongod --bind_ip 0.0.0.0 --noauth &
## DNA
echo "Launching DNA..."
starknet start --rpc=http://localhost:5050 --wait-for-rpc --head-refresh-interval-ms=500 --data=/data &
# ## Indexer
echo "Launching indexer..."
sink-mongo run /usr/src/app/code/kakarot-indexer/src/main.ts &

### 3.5. Await the Indexer to be healthy
echo "Waiting for the indexer to start..."
sleep 3

# 4. Start the Kakarot RPC service
echo "Launching Kakarot RPC..."
export PROXY_ACCOUNT_CLASS_HASH=$(jq -r '.declarations.proxy' manifest.json)
export CONTRACT_ACCOUNT_CLASS_HASH=$(jq -r '.declarations.contract_account' manifest.json)
export EXTERNALLY_OWNED_ACCOUNT_CLASS_HASH=$(jq -r '.declarations.externally_owned_account' manifest.json)
export KAKAROT_ADDRESS=$(jq -r '.deployments.kakarot_address' manifest.json)
kakarot-rpc
2 changes: 1 addition & 1 deletion src/eth_provider/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ lazy_static! {
)),
FieldElement::from_str(&var("KATANA_ACCOUNT_ADDRESS").expect("Missing deployer address"))
.expect("Failed to parse deployer address"),
*CHAIN_ID.get().expect("Missing chain ID"),
*CHAIN_ID.get().expect("Failed to get chain id"),
ExecutionEncoding::New
);
pub static ref DEPLOY_WALLET_NONCE: Arc<Mutex<FieldElement>> = Arc::new(Mutex::new(FieldElement::ZERO));
Expand Down
4 changes: 1 addition & 3 deletions src/eth_provider/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ where
// If the contract is not found, we need to deploy it.
#[cfg(feature = "hive")]
{
use crate::eth_provider::constant::{CHAIN_ID, DEPLOY_WALLET, DEPLOY_WALLET_NONCE};
use crate::eth_provider::constant::{DEPLOY_WALLET, DEPLOY_WALLET_NONCE};
use starknet::accounts::Call;
use starknet::accounts::Execution;
use starknet::core::types::BlockTag;
Expand All @@ -467,8 +467,6 @@ where
proxy.get_implementation().block_id(StarknetBlockId::Tag(BlockTag::Latest)).call().await;

if contract_not_found(&maybe_class_hash) {
let chain_id = self.starknet_provider.chain_id().await?;
let _ = CHAIN_ID.set(chain_id);
let execution = Execution::new(
vec![Call {
to: *KAKAROT_ADDRESS,
Expand Down
2 changes: 1 addition & 1 deletion src/eth_rpc/servers/eth_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ where

#[tracing::instrument(skip_all, ret, err)]
async fn syncing(&self) -> Result<SyncStatus> {
Ok(self.syncing().await?)
Ok(self.eth_provider.syncing().await?)
}

async fn coinbase(&self) -> Result<Address> {
Expand Down
10 changes: 9 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,16 @@ async fn main() -> Result<()> {
// Get the deployer nonce and set the value in the DEPLOY_WALLET_NONCE
#[cfg(feature = "hive")]
{
use kakarot_rpc::eth_provider::constant::{DEPLOY_WALLET, DEPLOY_WALLET_NONCE};
use kakarot_rpc::eth_provider::constant::{CHAIN_ID, DEPLOY_WALLET, DEPLOY_WALLET_NONCE};
use starknet::accounts::ConnectedAccount;
use starknet::providers::Provider;
let provider = JsonRpcClient::new(HttpTransport::new(
starknet_config.network.provider_url().expect("Incorrect provider URL"),
));

let chain_id = provider.chain_id().await?;
CHAIN_ID.set(chain_id).expect("Failed to set chain id");

let deployer_nonce = DEPLOY_WALLET.get_nonce().await?;
let mut nonce = DEPLOY_WALLET_NONCE.lock().await;
*nonce = deployer_nonce;
Expand Down
3 changes: 3 additions & 0 deletions tests/eth_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ async fn test_fee_history(#[future] katana: Katana, _setup: ()) {
#[cfg(feature = "hive")]
async fn test_predeploy_eoa(#[future] katana: Katana, _setup: ()) {
use futures::future::join_all;
use kakarot_rpc::eth_provider::constant::CHAIN_ID;
use kakarot_rpc::test_utils::eoa::KakarotEOA;
use reth_primitives::B256;
use starknet::providers::Provider;
Expand All @@ -275,6 +276,8 @@ async fn test_predeploy_eoa(#[future] katana: Katana, _setup: ()) {
let starknet_provider = eth_provider.starknet_provider();
let other_eoa_1 = KakarotEOA::new(B256::from_str(&format!("0x{:0>64}", "0abde1")).unwrap(), eth_provider.clone());
let other_eoa_2 = KakarotEOA::new(B256::from_str(&format!("0x{:0>64}", "0abde2")).unwrap(), eth_provider.clone());
let chain_id = starknet_provider.chain_id().await.unwrap();
CHAIN_ID.set(chain_id).expect("Failed to set chain id");

let evm_address = eoa.evm_address().unwrap();
let balance_before = eth_provider.balance(eoa.evm_address().unwrap(), None).await.unwrap();
Expand Down

0 comments on commit 487fbbd

Please sign in to comment.