Skip to content
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

oak-audit: fix issues 2, 12; Updated Grandpa light client with authority set history #382

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from
Draft
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
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions algorithms/grandpa/primitives/src/justification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,33 @@ where
Ok(())
}

/// The function checks if the given chain is canonical:
Copy link
Contributor

Choose a reason for hiding this comment

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

great doc

/// - the chain is not empty
/// - all the header hashes from `base_header` to `header.last()` form a chain
/// - height of the blocks increase sequentially by 1
/// And returns the first and last hashes of the chain
pub fn validate_chain<H: HeaderT>(
mut base_header_hash: H::Hash,
mut base_header_number: H::Number,
headers: &[H],
) -> Result<(&H, &H), anyhow::Error> {
if headers.is_empty() {
return Err(anyhow!("Empty chain"))
}
for header in headers {
if base_header_number + 1u32.into() != *header.number() {
return Err(anyhow!("Invalid block number in the chain"))
}
let current_hash = base_header_hash;
if header.parent_hash() != &current_hash {
return Err(anyhow!("Invalid block hash in the chain"))
}
base_header_hash = header.hash();
base_header_number = *header.number();
}
Ok(headers.first().zip(headers.last()).expect("headers are not empty; qed"))
}

/// Verifies the equivocation proof by making sure that both votes target
/// different blocks and that its signatures are valid.
pub fn check_equivocation_proof<Host, H, N>(
Expand Down
5 changes: 3 additions & 2 deletions algorithms/grandpa/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ pub trait HostFunctions: light_client_common::HostFunctions + 'static {

/// Verify an ed25519 signature
fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pub_key: &ed25519::Public) -> bool;
/// Stores the given list of RelayChain header hashes in the light client's storage.
fn insert_relay_header_hashes(headers: &[<Self::Header as Header>::Hash]);
/// Stores the given list of RelayChain header hashes in the light client's storage with
/// the given timestamp.
fn insert_relay_header_hashes(now_ms: u64, headers: &[<Self::Header as Header>::Hash]);
/// Checks if a RelayChain header hash exists in the light client's storage.
fn contains_relay_header_hash(hash: <Self::Header as Header>::Hash) -> bool;
}
Expand Down
2 changes: 1 addition & 1 deletion algorithms/grandpa/prover/src/host_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl HostFunctions for HostFunctionsProvider {
pubkey.verify(&msg, sig)
}

fn insert_relay_header_hashes(_headers: &[<Self::Header as Header>::Hash]) {
fn insert_relay_header_hashes(_now: u64, _headers: &[<Self::Header as Header>::Hash]) {
unimplemented!()
}

Expand Down
10 changes: 6 additions & 4 deletions algorithms/grandpa/verifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,18 @@ where
proof;

// 1. First validate unknown headers.
let headers = AncestryChain::<H>::new(&finality_proof.unknown_headers);
let headers = AncestryChain::new(&finality_proof.unknown_headers);

let target = finality_proof
.unknown_headers
.iter()
.max_by_key(|h| *h.number())
.ok_or_else(|| anyhow!("Unknown headers can't be empty!"))?;

let target_hash = target.hash();

// this is illegal
if target.hash() != finality_proof.block {
if target_hash != finality_proof.block {
Err(anyhow!("Latest finalized block should be highest block in unknown_headers"))?;
}

Expand All @@ -93,7 +95,7 @@ where
})?;
}

let mut finalized = headers.ancestry(from, target.hash()).map_err(|_| {
let mut finalized = headers.ancestry(from, target_hash).map_err(|_| {
anyhow!("[verify_parachain_headers_with_grandpa_finality_proof] Invalid ancestry!")
})?;
finalized.sort();
Expand Down Expand Up @@ -139,7 +141,7 @@ where
}

// 4. set new client state, optionally rotating authorities
client_state.latest_relay_hash = target.hash();
client_state.latest_relay_hash = target_hash;
client_state.latest_relay_height = (*target.number()).into();
if let Some(max_height) = para_heights.into_iter().max() {
if max_height != latest_para_height {
Expand Down
4 changes: 2 additions & 2 deletions config/rococo-local-local.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ para_id = 2000
parachain_rpc_url = "ws://127.0.0.1:9188"
relay_chain_rpc_url = "ws://127.0.0.1:9944"
client_id = "08-wasm-0"
connection_id = "connection-2"
connection_id = "connection-0"
commitment_prefix = "0x6962632f"
private_key = "//Alice"
ss58_version = 49
channel_whitelist = [["channel-2", "transfer"]]
channel_whitelist = [["channel-0", "transfer"]]
finality_protocol = "Grandpa"
key_type = "sr25519"
1 change: 1 addition & 0 deletions contracts/pallet-ibc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ ibc-proto = { path = "../../ibc/proto", default-features = false }
tendermint = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } # cannot be defined as optional in workspace
tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false }
ics23 = { git = "https://github.com/cosmos/ics23", rev = "74ce807b7be39a7e0afb4e2efb8e28a57965f57b", default-features = false }
vec1 = { version = "1.10.1", default-features = false }

grandpa-client-primitives = { package = "grandpa-light-client-primitives", path = "../../algorithms/grandpa/primitives", default-features = false }
beefy-client-primitives = { package = "beefy-light-client-primitives", path = "../../algorithms/beefy/primitives", default-features = false }
Expand Down
11 changes: 8 additions & 3 deletions contracts/pallet-ibc/src/benchmarks/grandpa_benchmark_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ use grandpa_client_primitives::{
use ibc::{timestamp::Timestamp, Height};
use ics10_grandpa::{
client_message::{ClientMessage, Header as GrandpaHeader, RelayChainHeader},
client_state::ClientState,
client_state::{AuthoritiesChange, ClientState},
consensus_state::ConsensusState,
};
use sp_core::H256;
use sp_finality_grandpa::{AuthorityId, AuthoritySignature, KEY_TYPE};
use sp_runtime::{traits::BlakeTwo256, SaturatedConversion};
use sp_std::prelude::*;
use sp_trie::{generate_trie_proof, LayoutV0, MemoryDB, StorageProof, TrieDBMutBuilder, TrieMut};
use vec1::vec1;

pub const GRANDPA_UPDATE_TIMESTAMP: u64 = 1650894363;
/// Builds a grandpa client message that that contains the requested number of precommits
Expand Down Expand Up @@ -156,8 +157,12 @@ pub fn generate_finality_proof(
frozen_height: None,
latest_para_height,
para_id,
current_set_id: set_id,
current_authorities: authorities.into_iter().map(|authority| (authority, 100)).collect(),
authorities_changes: vec1![AuthoritiesChange {
set_id,
authorities: authorities.into_iter().map(|authority| (authority, 100)).collect(),
height: 0,
timestamp: Timestamp::from_nanoseconds(1).unwrap(),
}],
_phantom: Default::default(),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ use ibc_proto::{cosmos::ics23::v1::CommitmentProof, ibc::core::commitment::v1::M
use ics07_tendermint::{
client_state::ClientState as TendermintClientState, consensus_state::ConsensusState,
};
use ics10_grandpa::client_state::AuthoritiesChange;
use ics11_beefy::{
client_state::ClientState as BeefyClientState,
consensus_state::ConsensusState as BeefyConsensusState,
Expand All @@ -68,6 +69,7 @@ use tendermint::{
};
use tendermint_light_client_verifier::types::Validator;
use tendermint_proto::Protobuf;
use vec1::vec1;

pub const TENDERMINT_TIMESTAMP: u64 = 1650894363;

Expand Down Expand Up @@ -317,8 +319,12 @@ pub(crate) fn create_mock_grandpa_client_state() -> (
frozen_height: None,
latest_para_height: 0,
para_id: 2087,
current_set_id: 0,
current_authorities: vec![],
authorities_changes: vec1![AuthoritiesChange {
height: 0,
timestamp: Timestamp::from_nanoseconds(1).unwrap(),
set_id: 0,
authorities: vec![],
}],
_phantom: Default::default(),
};

Expand Down
Loading