Skip to content

Commit

Permalink
add events for committee.move
Browse files Browse the repository at this point in the history
  • Loading branch information
longbowlu committed Apr 27, 2024
1 parent 6240a8a commit 5db2bb5
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 41 deletions.
3 changes: 2 additions & 1 deletion crates/sui-bridge/src/e2e_tests/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use sui_types::digests::TransactionDigest;
use sui_types::programmable_transaction_builder::ProgrammableTransactionBuilder;
use sui_types::transaction::{ObjectArg, TransactionData};
use sui_types::BRIDGE_PACKAGE_ID;
use sui_types::SUI_BRIDGE_OBJECT_ID;
use tokio::join;
use tokio::task::JoinHandle;

Expand Down Expand Up @@ -309,7 +310,7 @@ impl BridgeTestCluster {
.read_api()
.query_transaction_blocks(
SuiTransactionBlockResponseQuery {
filter: Some(TransactionFilter::InputObject(BRIDGE_PACKAGE_ID)),
filter: Some(TransactionFilter::InputObject(SUI_BRIDGE_OBJECT_ID)),
options: Some(SuiTransactionBlockResponseOptions::full_content()),
},
self.bridge_tx_cursor,
Expand Down
115 changes: 112 additions & 3 deletions crates/sui-bridge/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

#![allow(non_upper_case_globals)]

use std::str::FromStr;

use crate::crypto::BridgeAuthorityPublicKey;
use crate::error::BridgeError;
use crate::error::BridgeResult;
use crate::types::BridgeAction;
Expand All @@ -20,11 +19,15 @@ use fastcrypto::encoding::Hex;
use move_core_types::language_storage::StructTag;
use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use sui_json_rpc_types::SuiEvent;
use sui_types::base_types::SuiAddress;
use sui_types::bridge::BridgeChainId;

use sui_types::bridge::MoveTypeBridgeMessageKey;
use sui_types::bridge::MoveTypeCommitteeMember;
use sui_types::bridge::MoveTypeCommitteeMemberRegistration;
use sui_types::collection_types::VecMap;
use sui_types::crypto::ToFromBytes;
use sui_types::digests::TransactionDigest;
use sui_types::BRIDGE_PACKAGE_ID;

Expand Down Expand Up @@ -64,6 +67,20 @@ pub struct MoveTokenTransferAlreadyClaimed {
pub message_key: MoveTypeBridgeMessageKey,
}

// `CommitteeUpdateEvent` emitted in committee.move
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct MoveCommitteeUpdateEvent {
pub members: VecMap<Vec<u8>, MoveTypeCommitteeMember>,
pub stake_participation_percentage: u64,
}

// `BlocklistValidatorEvent` emitted in committee.move
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct MoveBlocklistValidatorEvent {
pub blocklisted: bool,
pub public_keys: Vec<Vec<u8>>,
}

// Sanitized version of MoveTokenDepositedEvent
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Hash)]
pub struct EmittedSuiToEthTokenBridgeV1 {
Expand Down Expand Up @@ -173,6 +190,53 @@ impl TryFrom<MoveTokenTransferAlreadyClaimed> for TokenTransferAlreadyClaimed {
}
}

// Sanitized version of MoveCommitteeUpdateEvent
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct CommitteeUpdate {
pub members: Vec<MoveTypeCommitteeMember>,
pub stake_participation_percentage: u64,
}

impl TryFrom<MoveCommitteeUpdateEvent> for CommitteeUpdate {
type Error = BridgeError;

fn try_from(event: MoveCommitteeUpdateEvent) -> BridgeResult<Self> {
let members = event
.members
.contents
.into_iter()
.map(|v| v.value)
.collect();
Ok(Self {
members,
stake_participation_percentage: event.stake_participation_percentage,
})
}
}

// Sanitized version of MoveBlocklistValidatorEvent
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct BlocklistValidatorEvent {
pub blocklisted: bool,
pub public_keys: Vec<BridgeAuthorityPublicKey>,
}

impl TryFrom<MoveBlocklistValidatorEvent> for BlocklistValidatorEvent {
type Error = BridgeError;

fn try_from(event: MoveBlocklistValidatorEvent) -> BridgeResult<Self> {
let public_keys = event.public_keys.into_iter().map(|bytes|
BridgeAuthorityPublicKey::from_bytes(&bytes).map_err(|e|
BridgeError::Generic(format!("Failed to convert MoveBlocklistValidatorEvent to BlocklistValidatorEvent. Failed to convert public key to BridgeAuthorityPublicKey: {:?}", e))
)
).collect::<BridgeResult<Vec<_>>>()?;
Ok(Self {
blocklisted: event.blocklisted,
public_keys,
})
}
}

impl TryFrom<MoveTokenDepositedEvent> for EmittedSuiToEthTokenBridgeV1 {
type Error = BridgeError;

Expand Down Expand Up @@ -232,6 +296,12 @@ crate::declare_events!(
TokenTransferClaimed(TokenTransferClaimed) => ("bridge::TokenTransferClaimed", MoveTokenTransferClaimed),
TokenTransferAlreadyApproved(TokenTransferAlreadyApproved) => ("bridge::TokenTransferAlreadyApproved", MoveTokenTransferAlreadyApproved),
TokenTransferAlreadyClaimed(TokenTransferAlreadyClaimed) => ("bridge::TokenTransferAlreadyClaimed", MoveTokenTransferAlreadyClaimed),
// No need to define a sanitized event struct for MoveTypeCommitteeMemberRegistration
// because the info provided by validators could be invalid
CommitteeMemberRegistration(MoveTypeCommitteeMemberRegistration) => ("committee::CommitteeMemberRegistration", MoveTypeCommitteeMemberRegistration),
CommitteeUpdateEvent(CommitteeUpdate) => ("committee::CommitteeUpdateEvent", MoveCommitteeUpdateEvent),
BlocklistValidator(BlocklistValidatorEvent) => ("committee::CommitteeUpdateEvent", MoveBlocklistValidatorEvent),

// Add new event types here. Format:
// EnumVariantName(Struct) => ("{module}::{event_struct}", CorrespondingMoveStruct)
);
Expand Down Expand Up @@ -289,13 +359,19 @@ impl SuiBridgeEvent {
SuiBridgeEvent::TokenTransferClaimed(_event) => None,
SuiBridgeEvent::TokenTransferAlreadyApproved(_event) => None,
SuiBridgeEvent::TokenTransferAlreadyClaimed(_event) => None,
SuiBridgeEvent::CommitteeMemberRegistration(_event) => None,
SuiBridgeEvent::CommitteeUpdateEvent(_event) => None,
SuiBridgeEvent::BlocklistValidator(_event) => None,
}
}
}

#[cfg(test)]
pub mod tests {
use std::collections::HashSet;

use super::*;
use crate::e2e_tests::test_utils::BridgeTestClusterBuilder;
use crate::types::BridgeAction;
use crate::types::SuiToEthBridgeAction;
use ethers::types::Address as EthAddress;
Expand Down Expand Up @@ -355,4 +431,37 @@ pub mod tests {
};
(event, bridge_action)
}

#[tokio::test]
async fn test_bridge_events_conversion() {
telemetry_subscribers::init_for_testing();
init_all_struct_tags();
let mut bridge_test_cluster = BridgeTestClusterBuilder::new()
.with_eth_env(true)
.with_bridge_cluster(false)
.build()
.await;

let events = bridge_test_cluster
.new_bridge_events(
HashSet::from_iter([
CommitteeMemberRegistration.get().unwrap().clone(),
CommitteeUpdateEvent.get().unwrap().clone(),
]),
false,
)
.await;
for event in events.iter() {
match SuiBridgeEvent::try_from_sui_event(event).unwrap().unwrap() {
SuiBridgeEvent::CommitteeMemberRegistration(_event) => (),
SuiBridgeEvent::CommitteeUpdateEvent(_event) => (),
_ => panic!(
"Expected CommitteeMemberRegistration or CommitteeUpdateEvent, got {:?}",
event
),
}
}

// TODO: trigger other events and make sure they are converted correctly
}
}
98 changes: 64 additions & 34 deletions crates/sui-bridge/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ use std::{
sync::Arc,
time::Duration,
};
use sui_types::{bridge::BRIDGE_MODULE_NAME, event::EventID, Identifier};
use sui_types::{
bridge::{BRIDGE_COMMITTEE_MODULE_NAME, BRIDGE_MODULE_NAME},
event::EventID,
Identifier,
};
use tokio::task::JoinHandle;
use tracing::info;

Expand Down Expand Up @@ -113,30 +117,35 @@ fn get_sui_modules_to_watch(
store: &std::sync::Arc<BridgeOrchestratorTables>,
sui_bridge_module_last_processed_event_id_override: Option<EventID>,
) -> HashMap<Identifier, Option<EventID>> {
let module_identifier = BRIDGE_MODULE_NAME.to_owned();
let sui_bridge_modules = vec![module_identifier.clone()];
let sui_bridge_modules = vec![
BRIDGE_MODULE_NAME.to_owned(),
BRIDGE_COMMITTEE_MODULE_NAME.to_owned(),
];
if let Some(cursor) = sui_bridge_module_last_processed_event_id_override {
info!("Overriding cursor for sui bridge modules to {:?}", cursor);
return HashMap::from_iter(
sui_bridge_modules
.iter()
.map(|module| (module.clone(), Some(cursor))),
);
}

let sui_bridge_module_stored_cursor = store
.get_sui_event_cursors(&sui_bridge_modules)
.expect("Failed to get eth sui event cursors from storage")[0];
.expect("Failed to get eth sui event cursors from storage");
let mut sui_modules_to_watch = HashMap::new();
match sui_bridge_module_last_processed_event_id_override {
Some(cursor) => {
for (module_identifier, cursor) in sui_bridge_modules
.iter()
.zip(sui_bridge_module_stored_cursor)
{
if cursor.is_none() {
info!(
"Overriding cursor for sui bridge module {} to {:?}. Stored cursor: {:?}",
module_identifier, cursor, sui_bridge_module_stored_cursor,
"No cursor found for sui bridge module {} in storage or config override, query start from the beginning.",
module_identifier
);
sui_modules_to_watch.insert(module_identifier, Some(cursor));
}
None => {
if sui_bridge_module_stored_cursor.is_none() {
info!(
"No cursor found for sui bridge module {} in storage or config override",
module_identifier
);
}
sui_modules_to_watch.insert(module_identifier, sui_bridge_module_stored_cursor);
}
};
sui_modules_to_watch.insert(module_identifier.clone(), cursor);
}
sui_modules_to_watch
}

Expand Down Expand Up @@ -257,14 +266,18 @@ mod tests {
let temp_dir = tempfile::tempdir().unwrap();

let store = BridgeOrchestratorTables::new(temp_dir.path());
let module = BRIDGE_MODULE_NAME.to_owned();
let bridge_module = BRIDGE_MODULE_NAME.to_owned();
let committee_module = BRIDGE_COMMITTEE_MODULE_NAME.to_owned();
// No override, no stored watermark, use None
let sui_modules_to_watch = get_sui_modules_to_watch(&store, None);
assert_eq!(
sui_modules_to_watch,
vec![(module.clone(), None)]
.into_iter()
.collect::<HashMap<_, _>>()
vec![
(bridge_module.clone(), None),
(committee_module.clone(), None)
]
.into_iter()
.collect::<HashMap<_, _>>()
);

// no stored watermark, use override
Expand All @@ -275,34 +288,51 @@ mod tests {
let sui_modules_to_watch = get_sui_modules_to_watch(&store, Some(override_cursor));
assert_eq!(
sui_modules_to_watch,
vec![(module.clone(), Some(override_cursor))]
.into_iter()
.collect::<HashMap<_, _>>()
vec![
(bridge_module.clone(), Some(override_cursor)),
(committee_module.clone(), Some(override_cursor))
]
.into_iter()
.collect::<HashMap<_, _>>()
);

// No override, found stored watermark, use stored watermark
// No override, found stored watermark for `bridge` module, use stored watermark for `bridge`
// and None for `committee`
let stored_cursor = EventID {
tx_digest: TransactionDigest::random(),
event_seq: 100,
};
store
.update_sui_event_cursor(module.clone(), stored_cursor)
.update_sui_event_cursor(bridge_module.clone(), stored_cursor)
.unwrap();
let sui_modules_to_watch = get_sui_modules_to_watch(&store, None);
assert_eq!(
sui_modules_to_watch,
vec![(module.clone(), Some(stored_cursor))]
.into_iter()
.collect::<HashMap<_, _>>()
vec![
(bridge_module.clone(), Some(stored_cursor)),
(committee_module.clone(), None)
]
.into_iter()
.collect::<HashMap<_, _>>()
);

// found stored watermark, use override
let stored_cursor = EventID {
tx_digest: TransactionDigest::random(),
event_seq: 100,
};
store
.update_sui_event_cursor(committee_module.clone(), stored_cursor)
.unwrap();
let sui_modules_to_watch = get_sui_modules_to_watch(&store, Some(override_cursor));
assert_eq!(
sui_modules_to_watch,
vec![(module.clone(), Some(override_cursor))]
.into_iter()
.collect::<HashMap<_, _>>()
vec![
(bridge_module.clone(), Some(override_cursor)),
(committee_module.clone(), Some(override_cursor))
]
.into_iter()
.collect::<HashMap<_, _>>()
);
}

Expand Down
1 change: 0 additions & 1 deletion crates/sui-bridge/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ impl BridgeAuthority {
}
}

// A static Bridge committee implementation
#[derive(Debug, Clone)]
pub struct BridgeCommittee {
members: BTreeMap<BridgeAuthorityPublicKeyBytes, BridgeAuthority>,
Expand Down
5 changes: 3 additions & 2 deletions crates/sui-types/src/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub type BridgeRecordDyanmicField = Field<
>;

pub const BRIDGE_MODULE_NAME: &IdentStr = ident_str!("bridge");
pub const BRIDGE_COMMITTEE_MODULE_NAME: &IdentStr = ident_str!("committee");
pub const BRIDGE_MESSAGE_MODULE_NAME: &IdentStr = ident_str!("message");
pub const BRIDGE_CREATE_FUNCTION_NAME: &IdentStr = ident_str!("create");
pub const BRIDGE_INIT_COMMITTEE_FUNCTION_NAME: &IdentStr = ident_str!("init_bridge_committee");
Expand Down Expand Up @@ -373,7 +374,7 @@ pub struct MoveTypeBridgeCommittee {

/// Rust version of the Move committee::CommitteeMemberRegistration type.
#[serde_as]
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema, Default, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct MoveTypeCommitteeMemberRegistration {
pub sui_address: SuiAddress,
Expand Down Expand Up @@ -408,7 +409,7 @@ pub struct BridgeTreasurySummary {

/// Rust version of the Move committee::CommitteeMember type.
#[serde_as]
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema, Default, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct MoveTypeCommitteeMember {
pub sui_address: SuiAddress,
Expand Down

0 comments on commit 5db2bb5

Please sign in to comment.