8000 fix(node): fix startup machine hash validation by GCdePaula · Pull Request #179 · cartesi/dave · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix(node): fix startup machine hash validation #179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 4, 2025
Merged
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
5 changes: 4 additions & 1 deletion cartesi-rollups/node/cartesi-rollups-prt-node/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,10 @@ impl PRTConfig {
)
.expect("could not create `state_manager`");

let mut machine = state_manager.latest_snapshot().unwrap();
let mut machine = state_manager
.snapshot(0)
.unwrap()
.expect("epoch zero should always exist");
Comment on lines +169 to +172
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the relevant fix.

assert_eq!(
machine.state_hash().unwrap(),
address_book.initial_hash,
Expand Down
6 changes: 3 additions & 3 deletions prt/client-lua/player/reader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ function Reader:new(endpoint)
return reader
end

function Reader._get_block_number(block)
local cmd = string.format("cast block " .. block .. " 2>&1")
function Reader:_get_block_number(block)
local cmd = string.format("cast block %s --rpc-url %s 2>&1", block, self.endpoint)

local handle = io.popen(cmd)
assert(handle)
Expand Down Expand Up @@ -302,7 +302,7 @@ function Reader:read_commitment(tournament_address, commitment_hash)
assert(allowance)
assert(last_resume)

local block_number = Reader._get_block_number("latest")
local block_number = self:_get_block_number("latest")

local commitment = {
clock = CommitmentClock:new(allowance, last_resume, block_number),
Expand Down
10 changes: 7 additions & 3 deletions prt/tests/common/runners/sybil_runner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,24 @@ local function sybil_player(root_tournament, strategy, blockchain_endpoint)
end)
end

local function sybil_runner(commitment_builder, machine_path, root_tournament, inputs, player_id)
local function sybil_runner(commitment_builder, machine_path, root_tournament, inputs, player_id, config)
config = config or {}
player_id = player_id or 1
local pk = config.pk or blockchain_consts.pks[player_id]
local endpoint = config.endpoint or blockchain_consts.endpoint

local strategy = HonestStrategy:new(
commitment_builder,
inputs,
machine_path,
Sender:new(blockchain_consts.pks[player_id], player_id, blockchain_consts.endpoint)
Sender:new(pk, player_id, endpoint)
)
strategy:disable_gc()

local react = sybil_player(
root_tournament,
strategy,
blockchain_consts.endpoint
endpoint
)

return react
Expand Down
92 changes: 75 additions & 17 deletions prt/tests/rollups/dave/reader.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
local eth_abi = require "utils.eth_abi"
local blockchain_constants = require "blockchain.constants"
local InnerReader = require "player.reader"
local uint256 = require "utils.bint" (256)
local time = require "utils.time"

local function parse_topics(json)
local _, _, topics = json:find(
Expand Down Expand Up @@ -62,13 +64,15 @@ end
local Reader = {}
Reader.__index = Reader

function Reader:new(input_box_address, consensus_address, endpoint)
function Reader:new(input_box_address, consensus_address, endpoint, genesis)
genesis = genesis or 0
endpoint = endpoint or blockchain_constants.endpoint
local reader = {
input_box_address = input_box_address,
consensus_address = consensus_address,
endpoint = assert(endpoint),
inner_reader = InnerReader:new(endpoint)
inner_reader = InnerReader:new(endpoint),
genesis = genesis,
}

setmetatable(reader, self)
Expand All @@ -77,7 +81,7 @@ end

local cast_logs_template = [==[
cast rpc -r "%s" eth_getLogs \
'[{"fromBlock": "earliest", "toBlock": "latest", "address": "%s", "topics": [%s]}]' -w 2>&1
'[{"fromBlock":"0x%x", "toBlock":"0x%x", "address": "%s", "topics": [%s]}]' -w 2>&1
]==]

function Reader:_read_logs(contract_address, sig, topics, data_sig)
Expand All @@ -98,23 +102,61 @@ function Reader:_read_logs(contract_address, sig, topics, data_sig)
end
local topic_str = table.concat(topics_strs, ", ")

local cmd = string.format(
cast_logs_template,
self.endpoint,
contract_address,
topic_str
)
local latest
do
local cmd = string.format("cast block-number --rpc-url %s", self.endpoint)
local handle = io.popen(cmd)
assert(handle)
latest = handle:read()
local tail = handle:read "*a"
if latest:find "Error" or tail:find "error" then
handle:close()
error(string.format("Call `%s` failed:\n%s%s", cmd, latest, tail))
end
handle:close()
latest = tonumber(latest)
end

local handle = io.popen(cmd)
assert(handle)
local logs = handle:read "*a"
handle:close()
local function call(from, to)
local cmd = string.format(
cast_logs_template,
self.endpoint,
from,
to,
contract_address,
topic_str
)

local handle = io.popen(cmd)
assert(handle)
local logs = handle:read "*a"
handle:close()

if logs:find "Error" then
error(string.format("Read logs `%s` failed:\n%s", sig, logs))
end

if logs:find "Error" then
error(string.format("Read logs `%s` failed:\n%s", sig, logs))
local ret = parse_logs(logs, data_sig)
return ret
end

local ret = {}
local from = self.genesis
while true do
local to = math.min(from + 1000, latest)
local r = call(from, to)
for _, value in ipairs(r) do
table.insert(ret, value)
end

if to == latest then
break
end

from = to + 1
time.sleep_ms(500)
end

local ret = parse_logs(logs, data_sig)
return ret
end

Expand Down Expand Up @@ -206,7 +248,7 @@ function Reader:root_tournament_winner(address)
end

function Reader:commitment_exists(tournament, commitment)
local commitments = self.inner_reader:read_commitment_joined(tournament)
local commitments = self.inner_reader:read_commitment_joined(tournament)

for _, log in ipairs(commitments) do
if log.root == commitment then
Expand All @@ -217,4 +259,20 @@ function Reader:commitment_exists(tournament, commitment)
return false
end

function Reader:balance(address)
local cmd = string.format("cast balance %s --rpc-url %s", address, self.endpoint)
local handle = io.popen(cmd)
assert(handle)

local balance = handle:read()
local tail = handle:read "*a"
if balance:find "Error" or tail:find "error" then
handle:close()
error(string.format("Call `%s` failed:\n%s%s", cmd, balance, tail))
end
handle:close()

return uint256.new(balance)
end

return Reader
5 changes: 3 additions & 2 deletions prt/tests/rollups/dave/sender.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ function Sender:_send_tx(contract_address, sig, args)
if ret:find "Error" then
handle:close()
error(string.format("Send transaction `%s` reverted:\n%s", cmd, ret))
else
print("Transaction sent:")
print(ret)
end

self.tx_count = self.tx_count + 1
Expand All @@ -95,9 +98,7 @@ end

function Sender:tx_add_inputs(inputs)
for _,payload in ipairs(inputs) do
self:advance_blocks(1)
self:tx_add_input(payload)
self:advance_blocks(1)
end
end

Expand Down
12 changes: 12 additions & 0 deletions prt/tests/rollups/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,15 @@ test-honeypot-case CASE:
# read logs from PRT Rollups node, run in separate terminal after `test-echo`
read-node-logs:
cat dave.log; tail -f dave.log

# sepolia-honeypot
download-sepolia-honeypot: clean-sepolia-honeypot-snapshot
mkdir -p sepolia/machine-image
curl -L \
https://github.com/cartesi/honeypot/releases/download/v2.0.0-rc-3/honeypot-snapshot-sepolia.tar.gz | \
tar -xz -C sepolia/machine-image
clean-sepolia-honeypot-snapshot:
rm -rf sepolia/machine-image

run-sepolia SCRIPT:
( set -a; source sepolia/.env; exec lua sepolia/{{SCRIPT}}.lua)
2 changes: 2 additions & 0 deletions prt/tests/rollups/sepolia/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
machine-image
.env
10 changes: 10 additions & 0 deletions prt/tests/rollups/sepolia/add_input.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require "setup_path"

local env = require "sepolia.setup_env"
local conversion = require "utils.conversion"

local big_input = conversion.bin_from_hex_n("0x6228290203658fd4987e40cbb257cabf258f9c288cdee767eaba6b234a73a2f9")
:rep((1 << 11) - 10)
assert(big_input:len() == (1 << 16) - 320)

env.sender:tx_add_inputs { conversion.hex_from_bin_n(big_input) }
74 changes: 74 additions & 0 deletions prt/tests/rollups/sepolia/dispute.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require "setup_path"

local PatchedCommitmentBuilder = require "runners.helpers.patched_commitment"
local CommitmentBuilder = require "computation.commitment"
local Hash = require "cryptography.hash"
local Machine = require "computation.machine"
local start_sybil = require "runners.sybil_runner"
local time = require "utils.time"

local env = require "sepolia.setup_env"

local sealed_epochs = env.reader:read_epochs_sealed()
local sealed_epoch = sealed_epochs[#sealed_epochs]

-- get all inputs
local all_inputs = env.reader:read_inputs_added(sealed_epoch.epoch_number)

-- slice inputs into `sealed_epoch` inputs
local inputs = {}
for i = sealed_epoch.input_lower_bound + 1, sealed_epoch.input_upper_bound do
table.insert(inputs, all_inputs[i].data)
end

-- Get `sealed_epoch` machine path.

-- Compute honest commitment
-- 44 is the initial log2_stride currently configured in the smart contracts.
local initial_state, commitment = Machine.root_rollup_commitment(env.template_machine, 44, inputs)
assert(sealed_epoch.initial_machine_state_hash, initial_state)

local patches = {
-- add input 2 + ustep
{ hash = Hash.zero, meta_cycle = (1 << 44) },
{ hash = Hash.zero, meta_cycle = (1 << 27) },
{ hash = Hash.zero, meta_cycle = (1) },
}

local honest_commitment_builder = CommitmentBuilder:new(env.template_machine, inputs, commitment)
local patched_commitment_builder = PatchedCommitmentBuilder:new(patches, honest_commitment_builder)
local player = start_sybil(patched_commitment_builder, env.template_machine, sealed_epoch.tournament, inputs, 1, {pk = env.pk, endpoint = env.gateway})

local function player_react(player_coroutine)
local success, log = coroutine.resume(player_coroutine)
assert(success, string.format("player fail to resume with error: %s", log))
return coroutine.status(player_coroutine), log
end

local function drive_player_until(player_coroutine, condition_f)
local ret
while true do
ret = { condition_f(player_react(player_coroutine)) }

if ret[1] then
return table.unpack(ret)
end

time.sleep(15)
end
end

local function drive_player(player_coroutine)
return drive_player_until(player_coroutine, function(status, log)
if log.has_lost then
return "lost"
elseif status == "dead" then
return "dead"
end
end)
end

-- Run player till completion
print("Run Sybil")
assert(drive_player(player) == "lost")
print "Sybil has lost"
36 changes: 36 additions & 0 deletions prt/tests/rollups/sepolia/setup_env.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
local Reader = require "dave.reader"
local Sender = require "dave.sender"

-- addresses
local APP_ADDRESS = assert(os.getenv("APP_ADDRESS"))
local CONSENSUS_ADDRESS = assert(os.getenv("CONSENSUS_ADDRESS"))
local INPUT_BOX_ADDRESS = assert(os.getenv("INPUT_BOX_ADDRESS"))
local PK_ADDRESS = assert(os.getenv("PK_ADDRESS"))

print(string.format([[
APP_ADDRESS = %s
CONSENSUS_ADDRESS = %s
INPUT_BOX_ADDRESS = %s
PK_ADDRESS = %s
]], APP_ADDRESS, CONSENSUS_ADDRESS, INPUT_BOX_ADDRESS, PK_ADDRESS))

local GATEWAY = assert(os.getenv("GATEWAY"))
local PK = assert(os.getenv("PK"))

local reader = Reader:new(INPUT_BOX_ADDRESS, CONSENSUS_ADDRESS, GATEWAY, 8467207)
local sender = Sender:new(INPUT_BOX_ADDRESS, APP_ADDRESS, PK, GATEWAY)

print(string.format("BALANCE = %s", reader:balance(PK_ADDRESS)))

return {
app_address = APP_ADDRESS,
consensus_address = CONSENSUS_ADDRESS,
input_box_address = INPUT_BOX_ADDRESS,
signer_address = PK_ADDRESS,
gateway = GATEWAY,
pk = PK,
template_machine = "sepolia/machine-image",

reader = reader,
sender = sender,
}
Loading
0