Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ jobs:
"until [[ $(docker exec sei-rpc-node build/seid status |jq -M -r .SyncInfo.latest_block_height) -gt 10 ]]; do sleep 10; done",
"echo rpc node started",
"python3 integration_test/scripts/runner.py integration_test/chain_operation/snapshot_operation.yaml",
"python3 integration_test/scripts/runner.py integration_test/chain_operation/statesync_operation.yaml"
"python3 integration_test/scripts/runner.py integration_test/chain_operation/statesync_operation.yaml",
"./integration_test/contracts/verify_statesync_flatkv_digest.sh",
"./integration_test/contracts/verify_cross_validator_flatkv_digest.sh"
]
},
{
Expand Down Expand Up @@ -106,11 +108,49 @@ jobs:
"python3 integration_test/scripts/runner.py integration_test/seidb/state_store_test.yaml",
],
},
{
# Umbrella job for all FlatKV-specific docker-level coverage.
# Future FlatKV scenarios (additional bucket layouts, snapshot
# rotation, etc.) should be appended here rather than added as
# new matrix rows, so the CI surface stays one row per concern.
#
# Step ordering matters:
# 1-2 Deploy EVM fixture and capture baseline RPC reads while
# the cluster is still in memiavl-only mode.
# 3 Run the offline FlatKV import on every validator and
# restart the cluster with flatkv enabled (dual_write,
# lattice-hash off to preserve AppHash trajectory across
# the import boundary).
# 4-5 Re-run the same fixture probe and physical-layout check
# against the post-import cluster; must match step 2.
# 6 SIGKILL one validator, restart, and assert 4-node
# FlatKV digest equality. This exercises WAL recovery on
# the post-import flatkv state, which mirrors the real
# production scenario (chains reach flatkv via migration,
# not via genesis flag).
# 7-9 Destructive disaster-recovery scenarios. They run last
# because they wipe or damage one validator's local state.
name: "FlatKV Integration",
scripts: [
"docker exec sei-node-0 integration_test/contracts/deploy_flatkv_evm_fixture.sh",
"python3 integration_test/scripts/runner.py integration_test/seidb/flatkv_evm_test.yaml",
"./integration_test/contracts/import_flatkv_evm_cluster.sh",
"python3 integration_test/scripts/runner.py integration_test/seidb/flatkv_evm_test.yaml",
"docker exec sei-node-0 integration_test/contracts/verify_flatkv_evm_store.sh",
"./integration_test/contracts/verify_flatkv_crash_recovery.sh",
"./integration_test/contracts/verify_flatkv_statesync_crash_recovery.sh",
"./integration_test/contracts/verify_flatkv_total_loss_recovery.sh",
"./integration_test/contracts/verify_flatkv_partial_loss_fails_loudly.sh",
],
},
{
name: "EVM Module",
env: "GIGA_STORAGE=true",
scripts: [
"./integration_test/evm_module/scripts/evm_tests.sh",
"docker exec sei-node-0 integration_test/contracts/deploy_flatkv_evm_fixture.sh",
"python3 integration_test/scripts/runner.py integration_test/seidb/flatkv_evm_test.yaml",
"docker exec sei-node-0 integration_test/contracts/verify_flatkv_evm_store.sh",
]
},
{
Expand Down
206 changes: 206 additions & 0 deletions integration_test/contracts/deploy_flatkv_evm_fixture.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
#!/bin/bash

set -euo pipefail

export PATH="$PATH:/root/.foundry/bin:/root/go/bin"

RPC_URL=${EVM_RPC_URL:-http://localhost:8545}
FROM=${FLATKV_EVM_FIXTURE_FROM:-admin}
PASSWORD=${FLATKV_EVM_FIXTURE_PASSWORD:-12345678}
CHAIN_ID=${FLATKV_EVM_FIXTURE_CHAIN_ID:-sei}
RECIPIENT_ADDR=${FLATKV_EVM_FIXTURE_RECIPIENT:-0x70997970C51812dc3A010C7d01b50e0d17dc79C8}
MISSING_ADDR=${FLATKV_EVM_FIXTURE_MISSING:-0xc1cadaffffffffffffffffffffffffffffffffff}
TRANSFER_VALUE_WEI=${FLATKV_EVM_FIXTURE_TRANSFER_VALUE_WEI:-1}
KEYRING_ARGS=()
if [ -n "${FLATKV_EVM_FIXTURE_KEYRING_BACKEND:-}" ]; then
KEYRING_ARGS+=(--keyring-backend "$FLATKV_EVM_FIXTURE_KEYRING_BACKEND")
fi

# Constructor:
# sstore(0, 42)
# return runtime bytecode that returns 42 for any call.
STORAGE_CONTRACT_INIT_CODE=0x602a600055600a600f600039600a6000f3602a60005260206000f3
STORAGE_SLOT_ZERO=0x0000000000000000000000000000000000000000000000000000000000000000

seihome=$(git rev-parse --show-toplevel)
out_dir="$seihome/integration_test/contracts"

write_fixture() {
local name=$1
local value=$2
printf "%s\n" "$value" > "$out_dir/$name"
}

run_seid() {
printf "%s\n" "$PASSWORD" | seid "$@"
}

wait_for_evm_rpc() {
local timeout=120
local elapsed=0
until cast block-number --rpc-url "$RPC_URL" >/dev/null 2>&1; do
if [ "$elapsed" -ge "$timeout" ]; then
echo "EVM RPC did not become ready within ${timeout}s" >&2
exit 1
fi
sleep 2
elapsed=$((elapsed + 2))
done
}

block_number() {
cast block-number --rpc-url "$RPC_URL"
}

query_balance() {
cast balance "$1" --block "$2" --rpc-url "$RPC_URL"
}

query_balance_hex() {
cast to-hex "$(query_balance "$1" "$2")"
}

query_storage() {
cast storage "$1" "$2" --block "$3" --rpc-url "$RPC_URL"
}

query_code() {
cast code "$1" --block "$2" --rpc-url "$RPC_URL"
}

extract_tx_hash() {
grep -oE '0x[a-fA-F0-9]{64}' | head -1
}

wait_for_receipt() {
local tx_hash=$1
local timeout=${2:-60}
local elapsed=0
local response

until [ "$elapsed" -ge "$timeout" ]; do
response=$(curl -s -X POST -H "Content-Type: application/json" \
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getTransactionReceipt\",\"params\":[\"$tx_hash\"]}" \
"$RPC_URL" || true)
if printf "%s\n" "$response" | jq -e '.result != null' >/dev/null 2>&1; then
printf "%s\n" "$response"
return 0
fi
sleep 1
elapsed=$((elapsed + 1))
done

echo "Timed out waiting for EVM receipt $tx_hash" >&2
return 1
}

require_success_receipt() {
local name=$1
local receipt=$2
local status
status=$(printf "%s\n" "$receipt" | jq -r '.result.status // empty')
if [ "$status" != "0x1" ] && [ "$status" != "1" ]; then
echo "FlatKV EVM $name failed:" >&2
printf "%s\n" "$receipt" >&2
exit 1
fi
}

echo "Generating FlatKV EVM historical fixture via $RPC_URL..."
wait_for_evm_rpc

initial_height=$(block_number)
write_fixture "flatkv_evm_initial_block_height.txt" "$initial_height"
write_fixture "flatkv_evm_recipient_addr.txt" "$RECIPIENT_ADDR"
write_fixture "flatkv_evm_missing_addr.txt" "$MISSING_ADDR"
write_fixture "flatkv_evm_storage_slot.txt" "$STORAGE_SLOT_ZERO"

run_seid tx evm associate-address \
--from "$FROM" \
"${KEYRING_ARGS[@]}" \
--chain-id "$CHAIN_ID" \
-b block \
-y >/tmp/flatkv_evm_associate.out 2>&1 || true

echo "Sending native EVM transfer to create/update recipient account..."
if ! transfer_out=$(run_seid tx evm send "$RECIPIENT_ADDR" "$TRANSFER_VALUE_WEI" \
--from "$FROM" \
"${KEYRING_ARGS[@]}" \
--chain-id "$CHAIN_ID" \
--evm-rpc "$RPC_URL" \
-b sync \
-y 2>&1); then
echo "FlatKV EVM transfer command failed:" >&2
printf "%s\n" "$transfer_out" >&2
exit 1
fi
printf "%s\n" "$transfer_out" >/tmp/flatkv_evm_transfer.out
transfer_tx=$(printf "%s\n" "$transfer_out" | extract_tx_hash || true)
if [ -z "$transfer_tx" ]; then
echo "Failed to extract FlatKV EVM transfer tx hash:" >&2
printf "%s\n" "$transfer_out" >&2
exit 1
fi
transfer_receipt=$(wait_for_receipt "$transfer_tx")
require_success_receipt "transfer" "$transfer_receipt"
printf "%s\n" "$transfer_receipt" >/tmp/flatkv_evm_transfer_receipt.json

balance_height=$(block_number)
balance_expected=$(query_balance_hex "$RECIPIENT_ADDR" "$balance_height")
write_fixture "flatkv_evm_balance_block_height.txt" "$balance_height"
write_fixture "flatkv_evm_balance_expected.txt" "$balance_expected"

echo "Deploying storage/code fixture contract..."
contract_hex_file=/tmp/flatkv_evm_storage_contract.hex
printf "%s" "${STORAGE_CONTRACT_INIT_CODE#0x}" > "$contract_hex_file"
if ! deploy_out=$(run_seid tx evm deploy "$contract_hex_file" \
--from "$FROM" \
"${KEYRING_ARGS[@]}" \
--chain-id "$CHAIN_ID" \
--evm-rpc "$RPC_URL" \
-b sync \
-y 2>&1); then
echo "FlatKV EVM deploy command failed:" >&2
printf "%s\n" "$deploy_out" >&2
exit 1
fi
deploy_tx=$(printf "%s\n" "$deploy_out" | extract_tx_hash || true)
if [ -z "$deploy_tx" ]; then
echo "Failed to extract FlatKV EVM deploy tx hash:" >&2
printf "%s\n" "$deploy_out" >&2
exit 1
fi
deploy_receipt=$(wait_for_receipt "$deploy_tx")
require_success_receipt "contract deployment" "$deploy_receipt"
printf "%s\n" "$deploy_receipt" > "$out_dir/flatkv_evm_deploy_receipt.json"

contract_addr=$(printf "%s\n" "$deploy_receipt" | jq -r '.result.contractAddress // empty')
if [ -z "$contract_addr" ] || [ "$contract_addr" = "null" ]; then
contract_addr=$(printf "%s\n" "$deploy_out" | sed -n 's/^Deployed to: //p' | tail -1)
fi
if [ -z "$contract_addr" ] || [ "$contract_addr" = "null" ]; then
echo "Failed to extract contract address from deploy receipt:" >&2
printf "%s\n" "$deploy_receipt" >&2
exit 1
fi

contract_height=$(block_number)
storage_expected=$(query_storage "$contract_addr" "$STORAGE_SLOT_ZERO" "$contract_height")
code_expected=$(query_code "$contract_addr" "$contract_height")

write_fixture "flatkv_evm_contract_addr.txt" "$contract_addr"
write_fixture "flatkv_evm_contract_block_height.txt" "$contract_height"
write_fixture "flatkv_evm_storage_expected.txt" "$storage_expected"
write_fixture "flatkv_evm_code_expected.txt" "$code_expected"

missing_balance_expected=$(query_balance_hex "$MISSING_ADDR" "$contract_height")
missing_storage_expected=$(query_storage "$MISSING_ADDR" "$STORAGE_SLOT_ZERO" "$contract_height")
write_fixture "flatkv_evm_missing_balance_expected.txt" "$missing_balance_expected"
write_fixture "flatkv_evm_missing_storage_expected.txt" "$missing_storage_expected"

latest_height=$(block_number)
write_fixture "flatkv_evm_latest_fixture_block_height.txt" "$latest_height"

echo "FlatKV EVM fixture generated:"
echo " recipient=$RECIPIENT_ADDR balance_height=$balance_height balance=$balance_expected"
echo " contract=$contract_addr contract_height=$contract_height storage=$storage_expected"
Loading
Loading