Skip to content

Commit

Permalink
interop: add interop tests for the consensus roothash state
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrus committed Nov 20, 2023
1 parent d9ca8f4 commit b20a9ad
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 5 deletions.
2 changes: 1 addition & 1 deletion go/consensus/cometbft/apps/beacon/state/interop/interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/oasisprotocol/oasis-core/go/storage/mkvs"
)

// InitializeTestBeaconState must be keet in sync with tests in runtimes/consensus/state/beacon.rs.
// InitializeTestBeaconState must be kept in sync with tests in runtimes/consensus/state/beacon.rs.
func InitializeTestBeaconState(ctx context.Context, mkvs mkvs.Tree) error {
state := beaconState.NewMutableState(mkvs)

Expand Down
73 changes: 73 additions & 0 deletions go/consensus/cometbft/apps/roothash/state/interop/interop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package interop

import (
"context"
"fmt"

"github.com/oasisprotocol/oasis-core/go/common"
"github.com/oasisprotocol/oasis-core/go/common/crypto/hash"
roothashState "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/roothash/state"
registry "github.com/oasisprotocol/oasis-core/go/registry/api"
"github.com/oasisprotocol/oasis-core/go/roothash/api"
"github.com/oasisprotocol/oasis-core/go/roothash/api/block"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs"
)

// InitializeTestBeaconState must be kept in sync with tests in runtimes/consensus/state/roothash.rs.
func InitializeTestRoothashState(ctx context.Context, mkvs mkvs.Tree) error {
var runtimeID common.Namespace
if err := runtimeID.UnmarshalHex("8000000000000000000000000000000000000000000000000000000000000010"); err != nil {
return err
}

state := roothashState.NewMutableState(mkvs)

if err := state.SetConsensusParameters(ctx, &api.ConsensusParameters{
MaxPastRootsStored: 100,
}); err != nil {
return err
}

// Create
// TODO: fill the rest if needed for interop tests in future.
runtimeState := &api.RuntimeState{
Runtime: &registry.Runtime{
ID: runtimeID,
},
Suspended: false,
GenesisBlock: &block.Block{Header: block.Header{
Round: 1,
IORoot: hash.NewFromBytes([]byte("genesis")),
StateRoot: hash.NewFromBytes([]byte("genesis")),
}},
LastBlock: &block.Block{Header: block.Header{
Round: 1,
IORoot: hash.NewFromBytes([]byte("genesis")),
StateRoot: hash.NewFromBytes([]byte("genesis")),
}},
LastBlockHeight: 1,
LastNormalRound: 1,
LastNormalHeight: 1,
}
if err := state.SetRuntimeState(ctx, runtimeState); err != nil {
return err
}

// Save some runtime state rounds, so we fill past roots state.
for i := 0; i < 10; i++ {
runtimeState.LastBlock = &block.Block{Header: block.Header{
Round: uint64(i + 1),
IORoot: hash.NewFromBytes([]byte(fmt.Sprintf("io %d", i+1))),
StateRoot: hash.NewFromBytes([]byte(fmt.Sprintf("state %d", i+1))),
}}
runtimeState.LastNormalRound = uint64(i + 1)
runtimeState.LastBlockHeight = int64(i * 10)
runtimeState.LastNormalHeight = int64(i * 10)

if err := state.SetRuntimeState(ctx, runtimeState); err != nil {
return err
}
}

return nil
}
9 changes: 9 additions & 0 deletions go/storage/mkvs/interop/fixtures/consensus_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package fixtures
import (
"context"
"fmt"
"time"

"github.com/oasisprotocol/oasis-core/go/common"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/api"
beaconInterop "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/beacon/state/interop"
keymanagerInterop "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager/state/interop"
registryInterop "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/registry/state/interop"
roothashInterop "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/roothash/state/interop"
stakingInterop "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/staking/state/interop"
storage "github.com/oasisprotocol/oasis-core/go/storage/api"
"github.com/oasisprotocol/oasis-core/go/storage/mkvs"
Expand All @@ -32,6 +35,9 @@ func (c *consensusMock) Populate(ctx context.Context, ndb db.NodeDB) (*node.Root
Version: 1,
}

// Use a dummy ABCI InitChain context, as SetConsensusParameters methods require a specific ABCI context.
ctx = api.NewContext(ctx, api.ContextInitChain, time.Time{}, nil, nil, nil, 0, nil, 0)

mkvsTree := mkvs.New(nil, ndb, node.RootTypeState, mkvs.WithoutWriteLog())
if err = stakingInterop.InitializeTestStakingState(ctx, mkvsTree); err != nil {
return nil, fmt.Errorf("consensus-mock: failed to initialize staking state: %w", err)
Expand All @@ -45,6 +51,9 @@ func (c *consensusMock) Populate(ctx context.Context, ndb db.NodeDB) (*node.Root
if err = keymanagerInterop.InitializeTestKeyManagerState(ctx, mkvsTree); err != nil {
return nil, fmt.Errorf("consensus-mock: failed to initialize key manager state: %w", err)
}
if err = roothashInterop.InitializeTestRoothashState(ctx, mkvsTree); err != nil {
return nil, fmt.Errorf("consensus-mock: failed to initialize roothash state: %w", err)
}
_, testRoot.Hash, err = mkvsTree.Commit(ctx, common.Namespace{}, 1)
if err != nil {
return nil, fmt.Errorf("consensus-mock: failed to committ tree: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/beacon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("123d46d530ebb004f6de9da7e1f41f7acde10b824e79ca8e718651dab2047c23"),
hash: Hash::from("f637a80b24e3ffaaf3de0da96f1dfd94d0a135348f40006d578d557d70d5fa42"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/keymanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("123d46d530ebb004f6de9da7e1f41f7acde10b824e79ca8e718651dab2047c23"),
hash: Hash::from("f637a80b24e3ffaaf3de0da96f1dfd94d0a135348f40006d578d557d70d5fa42"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("123d46d530ebb004f6de9da7e1f41f7acde10b824e79ca8e718651dab2047c23"),
hash: Hash::from("f637a80b24e3ffaaf3de0da96f1dfd94d0a135348f40006d578d557d70d5fa42"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down
95 changes: 95 additions & 0 deletions runtime/src/consensus/state/roothash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,98 @@ impl<'a, T: ImmutableMKVS> ImmutableState<'a, T> {
Ok(result)
}
}

#[cfg(test)]
mod test {
use crate::{
common::crypto::hash::Hash,
storage::mkvs::{
interop::{Fixture, ProtocolServer},
Root, RootType, Tree,
},
};

use super::*;
#[test]
fn test_roothash_state_interop() {
// Keep in sync with go/consensus/cometbft/apps/roothash/state/interop/interop.go.
// If mock consensus state changes, update the root hash bellow.
// See protocol server stdout for hash.
// To make the hash show up during tests, run "cargo test" as
// "cargo test -- --nocapture".

// Setup protocol server with initialized mock consensus state.
let server = ProtocolServer::new(Fixture::ConsensusMock.into());
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("f637a80b24e3ffaaf3de0da96f1dfd94d0a135348f40006d578d557d70d5fa42"),
..Default::default()
};
let mkvs = Tree::builder()
.with_capacity(100_000, 10_000_000)
.with_root(mock_consensus_root)
.build(server.read_sync());
let state = ImmutableState::new(&mkvs);

let runtime_id =
Namespace::from("8000000000000000000000000000000000000000000000000000000000000010");

// Test fetching past round roots.
let past_round_roots = state
.past_round_roots(runtime_id)
.expect("past round roots query should work");
assert_eq!(
10,
past_round_roots.len(),
"expected number of roots should match"
);
past_round_roots.iter().for_each(|(round, roots)| {
assert_eq!(
RoundRoots {
state_root: Hash::digest_bytes(format!("state {}", round).as_bytes()),
io_root: Hash::digest_bytes(format!("io {}", round).as_bytes())
},
*roots,
"expected roots should match"
);
});

// Test fetching latest round roots.
let round_roots = state
.round_roots(runtime_id, 100)
.expect("round roots query should work");
assert_eq!(None, round_roots, "round root should be missing");

let round_roots = state
.round_roots(runtime_id, 10)
.expect("round roots query should work");
assert_eq!(
Some(RoundRoots {
state_root: Hash::digest_bytes(format!("state {}", 10).as_bytes()),
io_root: Hash::digest_bytes(format!("io {}", 10).as_bytes())
}),
round_roots,
"round root should be missing"
);

// Test non-existing runtime.
let runtime_id =
Namespace::from("8000000000000000000000000000000000000000000000000000000000000000");
let past_round_roots = state
.past_round_roots(runtime_id)
.expect("past round roots query should work");
assert_eq!(
0,
past_round_roots.len(),
"there should be no roots for non-existing runtime"
);
let round_roots = state
.round_roots(runtime_id, 10)
.expect("round roots query should work");
assert_eq!(
None, round_roots,
"round root should be missing for non-existing runtime"
)
}
}
2 changes: 1 addition & 1 deletion runtime/src/consensus/state/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ mod test {
let mock_consensus_root = Root {
version: 1,
root_type: RootType::State,
hash: Hash::from("123d46d530ebb004f6de9da7e1f41f7acde10b824e79ca8e718651dab2047c23"),
hash: Hash::from("f637a80b24e3ffaaf3de0da96f1dfd94d0a135348f40006d578d557d70d5fa42"),
..Default::default()
};
let mkvs = Tree::builder()
Expand Down

0 comments on commit b20a9ad

Please sign in to comment.