Computes Ethereum storage roots and state roots from the current EEVM.Database.
The first state root of a database enumerates the backend through
EEVM.Database.accounts/1 and EEVM.Database.storage_slots/2, so the
backend must support them. update/1 keeps the hashed tries in the
database it returns, and every database derived from that one by writes
and EEVM.Database.commit/1 carries them along with the addresses and
slots written since. The next state root rehashes only those paths, so a
block costs Keccak work in proportion to what it wrote, not to the size of
the state (#203). EEVM.Block.execute/4 and EEVM.Block.build/4 use it,
so the databases in their results, committed or not, carry the tries to
the next block.
Summary
Types
Hashed tries for some earlier state, and what changed since: for each
address, the slots written, or :all when its storage was cleared. Kept
in EEVM.Database's :tries field.
Functions
Returns the world-state trie root of db, overlay included.
Returns the storage trie root of address.
Returns the world-state trie root of db, overlay included, and db
with its hashed tries updated, so the next state root of it, or of a
database written or committed from it, rehashes only what changed.
Types
@opaque tries()
Hashed tries for some earlier state, and what changed since: for each
address, the slots written, or :all when its storage was cleared. Kept
in EEVM.Database's :tries field.
Functions
@spec compute_state_root(EEVM.Database.t()) :: binary()
Returns the world-state trie root of db, overlay included.
@spec compute_storage_root(EEVM.Database.t(), non_neg_integer()) :: binary()
Returns the storage trie root of address.
@spec update(EEVM.Database.t()) :: {binary(), EEVM.Database.t()}
Returns the world-state trie root of db, overlay included, and db
with its hashed tries updated, so the next state root of it, or of a
database written or committed from it, rehashes only what changed.
Example
iex> alias EEVM.Database
iex> {_root, db} = EEVM.StateRoot.update(Database.InMemory.new(accounts: %{1 => %{balance: 5}}))
iex> {:ok, db} = db |> Database.set_balance(2, 7) |> Database.commit()
iex> {root, _db} = EEVM.StateRoot.update(db)
iex> fresh = Database.InMemory.new(accounts: %{1 => %{balance: 5}, 2 => %{balance: 7}})
iex> root == EEVM.StateRoot.compute_state_root(fresh)
true