From 1b5875732f2bdf2829a3bf5f2db44fb87645e39f Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 09:26:35 +1300 Subject: [PATCH 01/14] feat: Add `StartBlock` to registry types --- registry/types/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/registry/types/src/lib.rs b/registry/types/src/lib.rs index ddbd16bd8..d57a3c0a6 100644 --- a/registry/types/src/lib.rs +++ b/registry/types/src/lib.rs @@ -60,10 +60,21 @@ pub struct IndexerRule { pub name: Option, } +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +pub enum StartBlock { + /// Specific block height to start indexing from + Height(u64), + /// Real-time indexing, always taking the latest finalized block to stream + Latest, + /// Starts indexing from the block the Indexer was interrupted last time + Interruption, +} + #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct IndexerConfig { pub code: String, pub start_block_height: Option, + pub start_block: StartBlock, pub schema: Option, pub filter: IndexerRule, pub updated_at_block_height: Option, From 52bd32d2a5f51303c602461bc1da795f8e97429e Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 09:26:50 +1300 Subject: [PATCH 02/14] feat: Add support for `Startblock` in registry contract --- registry/contract/src/lib.rs | 45 +++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/registry/contract/src/lib.rs b/registry/contract/src/lib.rs index c9b000bff..b0a04180e 100644 --- a/registry/contract/src/lib.rs +++ b/registry/contract/src/lib.rs @@ -5,7 +5,8 @@ use near_sdk::store::UnorderedMap; use near_sdk::{env, log, near_bindgen, serde_json, AccountId, BorshStorageKey, CryptoHash}; use registry_types::{ - AccountOrAllIndexers, IndexerConfig, IndexerRule, IndexerRuleKind, MatchingRule, Status, + AccountOrAllIndexers, IndexerConfig, IndexerRule, IndexerRuleKind, MatchingRule, StartBlock, + Status, }; type FunctionName = String; @@ -131,6 +132,7 @@ impl Contract { updated_at_block_height: None, created_at_block_height: env::block_height(), schema: indexer_config.schema.clone(), + start_block: StartBlock::Latest, code: indexer_config.code.clone(), start_block_height: indexer_config.start_block_height, filter: indexer_config.filter.clone(), @@ -288,6 +290,8 @@ impl Contract { schema: Option, account_id: Option, filter_json: Option, + // TODO if this isn't optional then it's a breaking change - + start_block: Option, ) { let account_id = match account_id { Some(account_id) => { @@ -321,6 +325,8 @@ impl Contract { &account_id ); + let start_block = start_block.unwrap_or(StartBlock::Latest); + let account_indexers = self.registry .entry(account_id.clone()) @@ -336,6 +342,7 @@ impl Contract { start_block_height, schema, filter, + start_block, updated_at_block_height: Some(env::block_height()), created_at_block_height: indexer.created_at_block_height, }); @@ -346,6 +353,7 @@ impl Contract { start_block_height, schema, filter, + start_block, updated_at_block_height: None, created_at_block_height: env::block_height(), }); @@ -502,6 +510,7 @@ mod tests { code: "return block;".to_string(), start_block_height: None, schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: env::block_height(), @@ -518,6 +527,7 @@ mod tests { code: "return block2;".to_string(), start_block_height: None, schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: env::block_height(), @@ -751,6 +761,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -763,6 +774,7 @@ mod tests { config.schema.clone(), None, None, + None, ); assert_eq!( @@ -784,6 +796,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -795,6 +808,7 @@ mod tests { config.schema.clone(), None, None, + None, ); assert_eq!( contract.read_indexer_function("test".to_string(), None), @@ -817,6 +831,7 @@ mod tests { None, None, None, + None, ); } @@ -835,6 +850,7 @@ mod tests { None, Some("alice.near".to_string()), None, + None, ); } @@ -856,6 +872,7 @@ mod tests { None, Some("alice.near".to_string()), None, + None, ); } @@ -876,6 +893,7 @@ mod tests { None, Some("alice.near".to_string()), None, + None, ); assert!(contract @@ -899,6 +917,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: None, schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -911,6 +930,7 @@ mod tests { config.schema.clone(), None, None, + None, ); assert_eq!( @@ -941,6 +961,7 @@ mod tests { Some("".to_string()), None, None, + None, ); let indexer_config = contract @@ -967,6 +988,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: None, schema: None, + start_block: StartBlock::Latest, filter: IndexerRule { indexer_rule_kind: IndexerRuleKind::Action, matching_rule: MatchingRule::ActionFunctionCall { @@ -988,6 +1010,7 @@ mod tests { config.schema.clone(), None, Some(r#"{"indexer_rule_kind":"Action","matching_rule":{"rule":"ACTION_FUNCTION_CALL","affected_account_id":"test","function":"test","status":"FAIL"}}"#.to_string()), + None ); assert_eq!( @@ -1014,6 +1037,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: None, schema: None, + start_block: StartBlock::Latest, filter: IndexerRule { indexer_rule_kind: IndexerRuleKind::Action, matching_rule: MatchingRule::ActionAny { @@ -1034,6 +1058,7 @@ mod tests { config.schema.clone(), None, Some(r#"{"indexer_rule_kind":"Action","matching_rule":{"rule":"ACTION_ANY","affected_account_id":"test","status":"SUCCESS"}}"#.to_string()), + None, ); assert_eq!( @@ -1067,6 +1092,7 @@ mod tests { None, None, Some(filter_json_missing_rule_type.to_string()), + None, ); } @@ -1083,6 +1109,7 @@ mod tests { start_block_height: Some(43434343), schema: None, filter: Contract::near_social_indexer_rule(), + start_block: StartBlock::Latest, updated_at_block_height: None, created_at_block_height: 100, }, @@ -1104,6 +1131,7 @@ mod tests { Some("".to_string()), None, None, + None, ); let indexer_config = contract @@ -1132,6 +1160,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1152,6 +1181,7 @@ mod tests { schema: None, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, + start_block: StartBlock::Latest, created_at_block_height: 0, }; @@ -1162,6 +1192,7 @@ mod tests { config.schema, None, None, + None, ); assert_eq!( @@ -1186,6 +1217,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1221,6 +1253,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1257,6 +1290,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1287,6 +1321,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1323,6 +1358,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1350,6 +1386,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1362,6 +1399,7 @@ mod tests { start_block_height: Some(43434343), schema: None, filter: Contract::near_social_indexer_rule(), + start_block: StartBlock::Latest, updated_at_block_height: None, created_at_block_height: 0, }, @@ -1412,6 +1450,7 @@ mod tests { start_block_height: None, schema: None, filter: Contract::near_social_indexer_rule(), + start_block: StartBlock::Latest, updated_at_block_height: None, created_at_block_height: 0, }; @@ -1439,6 +1478,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: None, schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1476,6 +1516,7 @@ mod tests { start_block_height: Some(43434343), schema: None, filter: Contract::near_social_indexer_rule(), + start_block: StartBlock::Latest, updated_at_block_height: None, created_at_block_height: 0, }; @@ -1506,6 +1547,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1545,6 +1587,7 @@ mod tests { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, + start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, From c4188b69dc51ce93e1db1dfc6048b9d6d6ae5c5b Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 14:47:07 +1300 Subject: [PATCH 03/14] refactor: Remove unnused fields from registry types --- registry/types/src/lib.rs | 58 ++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/registry/types/src/lib.rs b/registry/types/src/lib.rs index d57a3c0a6..fca5d7dee 100644 --- a/registry/types/src/lib.rs +++ b/registry/types/src/lib.rs @@ -16,14 +16,6 @@ use serde::{Deserialize, Serialize}; type FunctionName = String; -#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] -pub enum Status { - Any, - Success, - Fail, -} - #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] #[serde(tag = "rule", rename_all = "SCREAMING_SNAKE_CASE")] pub enum MatchingRule { @@ -45,6 +37,7 @@ pub enum MatchingRule { } #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +#[serde(tag = "kind", rename_all = "SCREAMING_SNAKE_CASE")] pub enum IndexerRuleKind { Action, Event, @@ -53,14 +46,54 @@ pub enum IndexerRuleKind { } #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -pub struct IndexerRule { +pub struct OldIndexerRule { pub indexer_rule_kind: IndexerRuleKind, pub matching_rule: MatchingRule, + // These are not set, and not used anywhere pub id: Option, pub name: Option, } #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +pub struct OldIndexerConfig { + pub code: String, + pub start_block_height: Option, + pub schema: Option, + pub filter: OldIndexerRule, + pub updated_at_block_height: Option, + pub created_at_block_height: u64, +} + +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum Status { + Any, + Success, + Fail, +} + +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +#[serde(tag = "kind", rename_all = "SCREAMING_SNAKE_CASE")] +pub enum IndexerRule { + ActionAny { + affected_account_id: String, + status: Status, + }, + ActionFunctionCall { + affected_account_id: String, + status: Status, + function: String, + }, + Event { + contract_account_id: String, + standard: String, + version: String, + event: String, + }, +} + +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum StartBlock { /// Specific block height to start indexing from Height(u64), @@ -73,9 +106,8 @@ pub enum StartBlock { #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct IndexerConfig { pub code: String, - pub start_block_height: Option, pub start_block: StartBlock, - pub schema: Option, + pub schema: String, pub filter: IndexerRule, pub updated_at_block_height: Option, pub created_at_block_height: u64, @@ -83,6 +115,6 @@ pub struct IndexerConfig { #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum AccountOrAllIndexers { - All(HashMap>), - Account(HashMap), + All(HashMap>), + Account(HashMap), } From 47af7246a9470ebea156576fa877a0a61dbc09cb Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 16:33:09 +1300 Subject: [PATCH 04/14] fix: Remove breaking serde change to existing registry types --- registry/types/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/registry/types/src/lib.rs b/registry/types/src/lib.rs index fca5d7dee..3a38f490f 100644 --- a/registry/types/src/lib.rs +++ b/registry/types/src/lib.rs @@ -37,7 +37,6 @@ pub enum MatchingRule { } #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -#[serde(tag = "kind", rename_all = "SCREAMING_SNAKE_CASE")] pub enum IndexerRuleKind { Action, Event, From 047a4a5b78f1cd6144093a526bb5aa67e29bc3ce Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 16:33:42 +1300 Subject: [PATCH 05/14] refactor: Rename `IndexerRule` -> `Rule` --- registry/types/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/types/src/lib.rs b/registry/types/src/lib.rs index 3a38f490f..33fd378ae 100644 --- a/registry/types/src/lib.rs +++ b/registry/types/src/lib.rs @@ -73,7 +73,7 @@ pub enum Status { #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] #[serde(tag = "kind", rename_all = "SCREAMING_SNAKE_CASE")] -pub enum IndexerRule { +pub enum Rule { ActionAny { affected_account_id: String, status: Status, @@ -107,7 +107,7 @@ pub struct IndexerConfig { pub code: String, pub start_block: StartBlock, pub schema: String, - pub filter: IndexerRule, + pub rule: Rule, pub updated_at_block_height: Option, pub created_at_block_height: u64, } From 7841c0c6df40667b8538bc43adffa02010e42d6a Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 16:33:58 +1300 Subject: [PATCH 06/14] feat: Add `From` conversions between new/old types --- registry/types/src/lib.rs | 114 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/registry/types/src/lib.rs b/registry/types/src/lib.rs index 33fd378ae..473ec073e 100644 --- a/registry/types/src/lib.rs +++ b/registry/types/src/lib.rs @@ -36,6 +36,40 @@ pub enum MatchingRule { }, } +impl From for MatchingRule { + fn from(value: Rule) -> Self { + match value { + Rule::ActionAny { + affected_account_id, + status, + } => MatchingRule::ActionAny { + affected_account_id, + status, + }, + Rule::Event { + contract_account_id, + standard, + version, + event, + } => MatchingRule::Event { + contract_account_id, + standard, + version, + event, + }, + Rule::ActionFunctionCall { + affected_account_id, + status, + function, + } => MatchingRule::ActionFunctionCall { + affected_account_id, + status, + function, + }, + } + } +} + #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] pub enum IndexerRuleKind { Action, @@ -63,6 +97,36 @@ pub struct OldIndexerConfig { pub created_at_block_height: u64, } +impl From for OldIndexerConfig { + fn from(config: IndexerConfig) -> Self { + let start_block_height = match config.start_block { + StartBlock::Latest => None, + StartBlock::Interruption => None, + StartBlock::Height(height) => Some(height), + }; + + let schema = if config.schema.is_empty() { + None + } else { + Some(config.schema) + }; + + OldIndexerConfig { + start_block_height, + schema, + code: config.code, + filter: OldIndexerRule { + indexer_rule_kind: IndexerRuleKind::Action, + matching_rule: config.rule.into(), + id: None, + name: None, + }, + created_at_block_height: config.created_at_block_height, + updated_at_block_height: config.updated_at_block_height, + } + } +} + #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum Status { @@ -91,6 +155,40 @@ pub enum Rule { }, } +impl From for Rule { + fn from(value: MatchingRule) -> Self { + match value { + MatchingRule::ActionAny { + affected_account_id, + status, + } => Rule::ActionAny { + affected_account_id, + status, + }, + MatchingRule::Event { + contract_account_id, + standard, + version, + event, + } => Rule::Event { + contract_account_id, + standard, + version, + event, + }, + MatchingRule::ActionFunctionCall { + affected_account_id, + status, + function, + } => Rule::ActionFunctionCall { + affected_account_id, + status, + function, + }, + } + } +} + #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum StartBlock { @@ -112,6 +210,22 @@ pub struct IndexerConfig { pub created_at_block_height: u64, } +impl From for IndexerConfig { + fn from(config: OldIndexerConfig) -> Self { + Self { + start_block: match config.start_block_height { + Some(height) => StartBlock::Height(height), + None => StartBlock::Latest, + }, + schema: config.schema.unwrap_or(String::new()), + code: config.code, + rule: config.filter.matching_rule.into(), + created_at_block_height: config.created_at_block_height, + updated_at_block_height: config.updated_at_block_height, + } + } +} + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum AccountOrAllIndexers { All(HashMap>), From 3b4a539da25018f875ad5a4b5f19ab828a6e031c Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 16:34:18 +1300 Subject: [PATCH 07/14] refactor: Implement new types while maintaining current API --- registry/contract/src/lib.rs | 571 +++++++++++++++++------------------ 1 file changed, 284 insertions(+), 287 deletions(-) diff --git a/registry/contract/src/lib.rs b/registry/contract/src/lib.rs index b0a04180e..b62c7cf1e 100644 --- a/registry/contract/src/lib.rs +++ b/registry/contract/src/lib.rs @@ -5,51 +5,44 @@ use near_sdk::store::UnorderedMap; use near_sdk::{env, log, near_bindgen, serde_json, AccountId, BorshStorageKey, CryptoHash}; use registry_types::{ - AccountOrAllIndexers, IndexerConfig, IndexerRule, IndexerRuleKind, MatchingRule, StartBlock, - Status, + AccountOrAllIndexers, IndexerConfig, IndexerRuleKind, MatchingRule, OldIndexerConfig, + OldIndexerRule, Rule, StartBlock, Status, }; type FunctionName = String; -// Define the contract structure -#[near_bindgen] -#[derive(BorshDeserialize, BorshSerialize, Debug)] -pub struct Contract { - registry: IndexersByAccount, + +pub struct OldContract { + registry: OldIndexersByAccount, account_roles: Vec, } -pub type IndexersByAccount = UnorderedMap; +pub type OldIndexersByAccount = UnorderedMap; -pub type IndexerConfigByFunctionName = UnorderedMap; +pub type OldIndexerConfigByFunctionName = UnorderedMap; +// Define the contract structure +#[near_bindgen] #[derive(BorshDeserialize, BorshSerialize, Debug)] -pub struct OldState { - registry: OldIndexersByAccount, +pub struct Contract { + registry: IndexersByAccount, account_roles: Vec, } -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] -#[serde(crate = "near_sdk::serde")] -pub struct OldIndexerConfig { - pub code: String, - pub start_block_height: Option, - pub schema: Option, - pub filter: IndexerRule, -} +type IndexersByAccount = UnorderedMap; -pub type OldIndexersByAccount = UnorderedMap; - -pub type OldIndexerConfigByFunctionName = UnorderedMap; +type IndexerConfigByFunctionName = UnorderedMap; // Migration types #[derive(BorshStorageKey, BorshSerialize)] -pub enum StorageKeys { +enum StorageKeys { Registry, // can be removed after migration Account(CryptoHash), // can be removed after migration RegistryV1, AccountV1(CryptoHash), RegistryV2, AccountV2(CryptoHash), + RegistryV3, + AccountV3(CryptoHash), } /// These roles are used to control access across the various contract methods. @@ -75,7 +68,6 @@ pub struct AccountRole { role: Role, } -// Define the default, which automatically initializes the contract impl Default for Contract { fn default() -> Self { Self { @@ -113,54 +105,54 @@ impl Default for Contract { // Implement the contract structure #[near_bindgen] impl Contract { - #[private] - #[init(ignore_state)] - pub fn migrate() -> Self { - let state: OldState = env::state_read().expect("failed to parse existing state"); - - let mut registry = IndexersByAccount::new(StorageKeys::RegistryV2); - - for (account_id, indexers) in state.registry.iter() { - let mut new_indexers: IndexerConfigByFunctionName = IndexerConfigByFunctionName::new( - StorageKeys::AccountV2(env::sha256_array(account_id.as_bytes())), - ); - - for (function_name, indexer_config) in indexers.iter() { - new_indexers.insert( - function_name.to_string(), - IndexerConfig { - updated_at_block_height: None, - created_at_block_height: env::block_height(), - schema: indexer_config.schema.clone(), - start_block: StartBlock::Latest, - code: indexer_config.code.clone(), - start_block_height: indexer_config.start_block_height, - filter: indexer_config.filter.clone(), - }, - ); - } - - registry.insert(account_id.clone(), new_indexers); - } - - let account_roles: Vec<_> = Contract::default() - .account_roles - .into_iter() - .chain( - state - .account_roles - .into_iter() - .filter(|account_role| account_role.role == Role::User), - ) - .collect(); - - Self { - registry, - account_roles, - } - } - - pub fn near_social_indexer_rule() -> IndexerRule { + // #[private] + // #[init(ignore_state)] + // pub fn migrate() -> Self { + // let state: OldState = env::state_read().expect("failed to parse existing state"); + // + // let mut registry = IndexersByAccount::new(StorageKeys::RegistryV2); + // + // for (account_id, indexers) in state.registry.iter() { + // let mut new_indexers: IndexerConfigByFunctionName = IndexerConfigByFunctionName::new( + // StorageKeys::AccountV2(env::sha256_array(account_id.as_bytes())), + // ); + // + // for (function_name, indexer_config) in indexers.iter() { + // new_indexers.insert( + // function_name.to_string(), + // OldIndexerConfig { + // updated_at_block_height: None, + // created_at_block_height: env::block_height(), + // schema: indexer_config.schema.clone(), + // start_block: StartBlock::Latest, + // code: indexer_config.code.clone(), + // start_block_height: indexer_config.start_block_height, + // filter: indexer_config.filter.clone(), + // }, + // ); + // } + // + // registry.insert(account_id.clone(), new_indexers); + // } + // + // let account_roles: Vec<_> = Contract::default() + // .account_roles + // .into_iter() + // .chain( + // state + // .account_roles + // .into_iter() + // .filter(|account_role| account_role.role == Role::User), + // ) + // .collect(); + // + // Self { + // registry, + // account_roles, + // } + // } + + pub fn near_social_indexer_rule() -> OldIndexerRule { let contract = "social.near"; let method = "set"; let matching_rule = MatchingRule::ActionFunctionCall { @@ -168,7 +160,7 @@ impl Contract { function: method.to_string(), status: Status::Any, }; - IndexerRule { + OldIndexerRule { indexer_rule_kind: IndexerRuleKind::Action, matching_rule, id: None, @@ -181,7 +173,7 @@ impl Contract { &self, function_name: String, account_id: Option, - ) -> IndexerConfig { + ) -> OldIndexerConfig { let account_id = match account_id { Some(account_id) => account_id.parse::().unwrap_or_else(|_| { env::panic_str(&format!("Account ID {} is invalid", account_id)); @@ -193,7 +185,7 @@ impl Contract { env::panic_str(format!("Account {} has no registered functions", account_id).as_str()) }); - let indexer_config = account_indexers.get(&function_name).unwrap_or_else(|| { + let config = account_indexers.get(&function_name).unwrap_or_else(|| { env::panic_str( format!( "Function {} is not registered under account {}", @@ -203,7 +195,7 @@ impl Contract { ) }); - indexer_config.clone() + config.clone().into() } pub fn assert_roles(&self, permitted_roles: Vec) { @@ -290,8 +282,6 @@ impl Contract { schema: Option, account_id: Option, filter_json: Option, - // TODO if this isn't optional then it's a breaking change - - start_block: Option, ) { let account_id = match account_id { Some(account_id) => { @@ -307,11 +297,11 @@ impl Contract { } }; - let filter: IndexerRule = match filter_json { + let filter: OldIndexerRule = match filter_json { Some(filter_json) => { - let filter_rule: IndexerRule = - serde_json::from_str(&filter_json).unwrap_or_else(|_| { - env::panic_str(&format!("Invalid filter JSON {}", filter_json)); + let filter_rule: OldIndexerRule = serde_json::from_str(&filter_json) + .unwrap_or_else(|e| { + env::panic_str(&format!("Invalid filter JSON {}", e)); }); filter_rule @@ -325,8 +315,6 @@ impl Contract { &account_id ); - let start_block = start_block.unwrap_or(StartBlock::Latest); - let account_indexers = self.registry .entry(account_id.clone()) @@ -334,15 +322,19 @@ impl Contract { env::sha256_array(account_id.as_bytes()), ))); + let start_block = match start_block_height { + Some(height) => StartBlock::Height(height), + None => StartBlock::Latest, + }; + match account_indexers.entry(function_name) { near_sdk::store::unordered_map::Entry::Occupied(mut entry) => { let indexer = entry.get(); entry.insert(IndexerConfig { code, - start_block_height, - schema, - filter, start_block, + schema: schema.unwrap_or(String::new()), + rule: filter.matching_rule.into(), updated_at_block_height: Some(env::block_height()), created_at_block_height: indexer.created_at_block_height, }); @@ -350,10 +342,9 @@ impl Contract { near_sdk::store::unordered_map::Entry::Vacant(entry) => { entry.insert(IndexerConfig { code, - start_block_height, - schema, - filter, start_block, + schema: schema.unwrap_or(String::new()), + rule: filter.matching_rule.into(), updated_at_block_height: None, created_at_block_height: env::block_height(), }); @@ -417,7 +408,9 @@ impl Contract { AccountOrAllIndexers::Account( account_indexers .iter() - .map(|(function_name, config)| (function_name.clone(), config.clone())) + .map(|(function_name, config)| { + (function_name.clone(), config.clone().into()) + }) .collect(), ) } @@ -430,7 +423,7 @@ impl Contract { account_indexers .iter() .map(|(function_name, config)| { - (function_name.clone(), config.clone()) + (function_name.clone(), config.clone().into()) }) .collect(), ) @@ -451,100 +444,100 @@ mod tests { use std::collections::HashMap; - #[test] - fn migrate() { - let mut registry = OldIndexersByAccount::new(StorageKeys::RegistryV1); - let account_id = "morgs.near".parse::().unwrap(); - let mut functions = OldIndexerConfigByFunctionName::new(StorageKeys::AccountV1( - env::sha256_array(account_id.as_bytes()), - )); - - functions.insert( - "test".to_string(), - OldIndexerConfig { - code: "return block;".to_string(), - start_block_height: None, - schema: None, - filter: Contract::near_social_indexer_rule(), - }, - ); - functions.insert( - "test2".to_string(), - OldIndexerConfig { - code: "return block2;".to_string(), - start_block_height: None, - schema: None, - filter: Contract::near_social_indexer_rule(), - }, - ); - registry.insert(account_id.clone(), functions); - - env::state_write(&OldState { - registry, - account_roles: vec![ - AccountRole { - account_id: account_id.clone(), - role: Role::Owner, - }, - AccountRole { - account_id: "should-be-removed.near".parse().unwrap(), - role: Role::Owner, - }, - AccountRole { - account_id: "bob.near".parse().unwrap(), - role: Role::User, - }, - ], - }); - - let contract = Contract::migrate(); - - assert_eq!( - contract - .registry - .get(&account_id) - .unwrap() - .get("test") - .unwrap(), - &IndexerConfig { - code: "return block;".to_string(), - start_block_height: None, - schema: None, - start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), - updated_at_block_height: None, - created_at_block_height: env::block_height(), - } - ); - assert_eq!( - contract - .registry - .get(&account_id) - .unwrap() - .get("test2") - .unwrap(), - &IndexerConfig { - code: "return block2;".to_string(), - start_block_height: None, - schema: None, - start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), - updated_at_block_height: None, - created_at_block_height: env::block_height(), - } - ); - assert_eq!( - contract.account_roles, - Contract::default() - .account_roles - .into_iter() - .chain(std::iter::once(AccountRole { - account_id: "bob.near".parse().unwrap(), - role: Role::User, - })) - .collect::>() - ); - } + // #[test] + // fn migrate() { + // let mut registry = IndexersByAccount::new(StorageKeys::RegistryV1); + // let account_id = "morgs.near".parse::().unwrap(); + // let mut functions = IndexerConfigByFunctionName::new(StorageKeys::AccountV1( + // env::sha256_array(account_id.as_bytes()), + // )); + // + // functions.insert( + // "test".to_string(), + // IndexerConfig { + // code: "return block;".to_string(), + // start_block_height: None, + // schema: None, + // filter: Contract::near_social_indexer_rule(), + // }, + // ); + // functions.insert( + // "test2".to_string(), + // IndexerConfig { + // code: "return block2;".to_string(), + // start_block_height: None, + // schema: None, + // filter: Contract::near_social_indexer_rule(), + // }, + // ); + // registry.insert(account_id.clone(), functions); + // + // env::state_write(&OldState { + // registry, + // account_roles: vec![ + // AccountRole { + // account_id: account_id.clone(), + // role: Role::Owner, + // }, + // AccountRole { + // account_id: "should-be-removed.near".parse().unwrap(), + // role: Role::Owner, + // }, + // AccountRole { + // account_id: "bob.near".parse().unwrap(), + // role: Role::User, + // }, + // ], + // }); + // + // let contract = Contract::migrate(); + // + // assert_eq!( + // contract + // .registry + // .get(&account_id) + // .unwrap() + // .get("test") + // .unwrap(), + // &IndexerConfig { + // code: "return block;".to_string(), + // start_block_height: None, + // schema: None, + // start_block: StartBlock::Latest, + // filter: Contract::near_social_indexer_rule(), + // updated_at_block_height: None, + // created_at_block_height: env::block_height(), + // } + // ); + // assert_eq!( + // contract + // .registry + // .get(&account_id) + // .unwrap() + // .get("test2") + // .unwrap(), + // &IndexerConfig { + // code: "return block2;".to_string(), + // start_block_height: None, + // schema: None, + // start_block: StartBlock::Latest, + // filter: Contract::near_social_indexer_rule(), + // updated_at_block_height: None, + // created_at_block_height: env::block_height(), + // } + // ); + // assert_eq!( + // contract.account_roles, + // Contract::default() + // .account_roles + // .into_iter() + // .chain(std::iter::once(AccountRole { + // account_id: "bob.near".parse().unwrap(), + // role: Role::User, + // })) + // .collect::>() + // ); + // } #[test] fn list_account_roles() { @@ -607,7 +600,7 @@ mod tests { assert!(contract .account_roles .iter() - .any(|account| account.account_id.to_string() == "alice.near")) + .any(|account| account.account_id == "alice.near")) } #[test] @@ -699,7 +692,7 @@ mod tests { assert!(!contract .account_roles .iter() - .any(|account| account.account_id.to_string() == "alice.near")) + .any(|account| account.account_id == "alice.near")) } #[test] @@ -757,11 +750,10 @@ mod tests { role: Role::User, }], }; - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, - start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -774,7 +766,6 @@ mod tests { config.schema.clone(), None, None, - None, ); assert_eq!( @@ -792,11 +783,10 @@ mod tests { role: Role::Owner, }], }; - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, - start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -808,7 +798,6 @@ mod tests { config.schema.clone(), None, None, - None, ); assert_eq!( contract.read_indexer_function("test".to_string(), None), @@ -831,7 +820,6 @@ mod tests { None, None, None, - None, ); } @@ -850,7 +838,6 @@ mod tests { None, Some("alice.near".to_string()), None, - None, ); } @@ -872,7 +859,6 @@ mod tests { None, Some("alice.near".to_string()), None, - None, ); } @@ -893,7 +879,6 @@ mod tests { None, Some("alice.near".to_string()), None, - None, ); assert!(contract @@ -913,11 +898,10 @@ mod tests { role: Role::User, }], }; - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: None, schema: None, - start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -930,17 +914,19 @@ mod tests { config.schema.clone(), None, None, - None, ); assert_eq!( - contract - .registry - .get(&"bob.near".parse::().unwrap()) - .unwrap() - .get("test") - .unwrap(), - &config + OldIndexerConfig::from( + contract + .registry + .get(&"bob.near".parse::().unwrap()) + .unwrap() + .get("test") + .unwrap() + .clone() + ), + config ); } @@ -961,7 +947,6 @@ mod tests { Some("".to_string()), None, None, - None, ); let indexer_config = contract @@ -984,12 +969,11 @@ mod tests { role: Role::User, }], }; - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: None, schema: None, - start_block: StartBlock::Latest, - filter: IndexerRule { + filter: OldIndexerRule { indexer_rule_kind: IndexerRuleKind::Action, matching_rule: MatchingRule::ActionFunctionCall { affected_account_id: "test".to_string(), @@ -1010,17 +994,19 @@ mod tests { config.schema.clone(), None, Some(r#"{"indexer_rule_kind":"Action","matching_rule":{"rule":"ACTION_FUNCTION_CALL","affected_account_id":"test","function":"test","status":"FAIL"}}"#.to_string()), - None ); assert_eq!( - contract - .registry - .get(&"bob.near".parse::().unwrap()) - .unwrap() - .get("test") - .unwrap(), - &config + OldIndexerConfig::from( + contract + .registry + .get(&"bob.near".parse::().unwrap()) + .unwrap() + .get("test") + .unwrap() + .clone() + ), + config ); } @@ -1033,12 +1019,11 @@ mod tests { role: Role::User, }], }; - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: None, schema: None, - start_block: StartBlock::Latest, - filter: IndexerRule { + filter: OldIndexerRule { indexer_rule_kind: IndexerRuleKind::Action, matching_rule: MatchingRule::ActionAny { affected_account_id: "test".to_string(), @@ -1058,17 +1043,19 @@ mod tests { config.schema.clone(), None, Some(r#"{"indexer_rule_kind":"Action","matching_rule":{"rule":"ACTION_ANY","affected_account_id":"test","status":"SUCCESS"}}"#.to_string()), - None, ); assert_eq!( - contract - .registry - .get(&"bob.near".parse::().unwrap()) - .unwrap() - .get("test") - .unwrap(), - &config + OldIndexerConfig::from( + contract + .registry + .get(&"bob.near".parse::().unwrap()) + .unwrap() + .get("test") + .unwrap() + .clone() + ), + config ); } @@ -1092,7 +1079,6 @@ mod tests { None, None, Some(filter_json_missing_rule_type.to_string()), - None, ); } @@ -1106,10 +1092,12 @@ mod tests { "test".to_string(), IndexerConfig { code: "var x= 1;".to_string(), - start_block_height: Some(43434343), - schema: None, - filter: Contract::near_social_indexer_rule(), start_block: StartBlock::Latest, + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, created_at_block_height: 100, }, @@ -1131,7 +1119,6 @@ mod tests { Some("".to_string()), None, None, - None, ); let indexer_config = contract @@ -1158,12 +1145,14 @@ mod tests { "test".to_string(), IndexerConfig { code: "var x= 1;".to_string(), - start_block_height: Some(43434343), - schema: None, start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, - created_at_block_height: 0, + created_at_block_height: 100, }, ); let mut registry = IndexersByAccount::new(StorageKeys::Registry); @@ -1175,13 +1164,12 @@ mod tests { role: Role::User, }], }; - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: None, schema: None, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, - start_block: StartBlock::Latest, created_at_block_height: 0, }; @@ -1192,7 +1180,6 @@ mod tests { config.schema, None, None, - None, ); assert_eq!( @@ -1215,12 +1202,14 @@ mod tests { "test".to_string(), IndexerConfig { code: "var x= 1;".to_string(), - start_block_height: Some(43434343), - schema: None, start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, - created_at_block_height: 0, + created_at_block_height: 100, }, ); let mut registry = IndexersByAccount::new(StorageKeys::Registry); @@ -1251,12 +1240,14 @@ mod tests { "test".to_string(), IndexerConfig { code: "var x= 1;".to_string(), - start_block_height: Some(43434343), - schema: None, start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, - created_at_block_height: 0, + created_at_block_height: 100, }, ); let mut registry = IndexersByAccount::new(StorageKeys::Registry); @@ -1288,12 +1279,14 @@ mod tests { "test".to_string(), IndexerConfig { code: "var x= 1;".to_string(), - start_block_height: Some(43434343), - schema: None, start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, - created_at_block_height: 0, + created_at_block_height: 100, }, ); let mut registry = IndexersByAccount::new(StorageKeys::Registry); @@ -1319,12 +1312,14 @@ mod tests { "test".to_string(), IndexerConfig { code: "var x= 1;".to_string(), - start_block_height: Some(43434343), - schema: None, start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, - created_at_block_height: 0, + created_at_block_height: 100, }, ); let mut registry = IndexersByAccount::new(StorageKeys::Registry); @@ -1356,12 +1351,14 @@ mod tests { "test".to_string(), IndexerConfig { code: "var x= 1;".to_string(), - start_block_height: Some(43434343), - schema: None, start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, - created_at_block_height: 0, + created_at_block_height: 100, }, ); let mut registry = IndexersByAccount::new(StorageKeys::Registry); @@ -1384,24 +1381,28 @@ mod tests { "test".to_string(), IndexerConfig { code: "var x= 1;".to_string(), - start_block_height: Some(43434343), - schema: None, start_block: StartBlock::Latest, - filter: Contract::near_social_indexer_rule(), + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, - created_at_block_height: 0, + created_at_block_height: 100, }, ); account_indexers.insert( "test2".to_string(), IndexerConfig { - code: "var x= 2;".to_string(), - start_block_height: Some(43434343), - schema: None, - filter: Contract::near_social_indexer_rule(), + code: "var x= 1;".to_string(), start_block: StartBlock::Latest, + schema: String::new(), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, updated_at_block_height: None, - created_at_block_height: 0, + created_at_block_height: 100, }, ); let mut registry = IndexersByAccount::new(StorageKeys::Registry); @@ -1445,20 +1446,20 @@ mod tests { #[test] fn read_indexer_function() { - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: None, schema: None, filter: Contract::near_social_indexer_rule(), - start_block: StartBlock::Latest, updated_at_block_height: None, created_at_block_height: 0, }; + let account_id = "bob.near".parse::().unwrap(); let mut account_indexers = IndexerConfigByFunctionName::new(StorageKeys::Account( env::sha256_array(account_id.as_bytes()), )); - account_indexers.insert("test".to_string(), config.clone()); + account_indexers.insert("test".to_string(), config.clone().into()); let mut registry = IndexersByAccount::new(StorageKeys::Registry); registry.insert(account_id, account_indexers); let contract = Contract { @@ -1474,11 +1475,10 @@ mod tests { #[test] fn read_indexer_function_from_other_account() { - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: None, schema: None, - start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1487,7 +1487,7 @@ mod tests { let mut account_indexers = IndexerConfigByFunctionName::new(StorageKeys::Account( env::sha256_array(account_id.as_bytes()), )); - account_indexers.insert("test".to_string(), config.clone()); + account_indexers.insert("test".to_string(), config.clone().into()); let mut registry = IndexersByAccount::new(StorageKeys::Registry); registry.insert(account_id, account_indexers); let contract = Contract { @@ -1511,12 +1511,11 @@ mod tests { #[test] fn list_indexer_functions() { - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, filter: Contract::near_social_indexer_rule(), - start_block: StartBlock::Latest, updated_at_block_height: None, created_at_block_height: 0, }; @@ -1524,7 +1523,7 @@ mod tests { let mut account_indexers = IndexerConfigByFunctionName::new(StorageKeys::Account( env::sha256_array(account_id.as_bytes()), )); - account_indexers.insert("test".to_string(), config.clone()); + account_indexers.insert("test".to_string(), config.clone().into()); let mut registry = IndexersByAccount::new(StorageKeys::Registry); registry.insert(account_id, account_indexers); let contract = Contract { @@ -1543,11 +1542,10 @@ mod tests { #[test] fn list_account_indexer_functions() { - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, - start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1556,7 +1554,7 @@ mod tests { let mut account_indexers = IndexerConfigByFunctionName::new(StorageKeys::Account( env::sha256_array(account_id.as_bytes()), )); - account_indexers.insert("test".to_string(), config.clone()); + account_indexers.insert("test".to_string(), config.clone().into()); let mut registry = IndexersByAccount::new(StorageKeys::Registry); registry.insert(account_id, account_indexers); let contract = Contract { @@ -1583,11 +1581,10 @@ mod tests { #[test] fn list_other_account_indexer_functions() { - let config = IndexerConfig { + let config = OldIndexerConfig { code: "var x= 1;".to_string(), start_block_height: Some(43434343), schema: None, - start_block: StartBlock::Latest, filter: Contract::near_social_indexer_rule(), updated_at_block_height: None, created_at_block_height: 0, @@ -1596,7 +1593,7 @@ mod tests { let mut account_indexers = IndexerConfigByFunctionName::new(StorageKeys::Account( env::sha256_array(account_id.as_bytes()), )); - account_indexers.insert("test".to_string(), config.clone()); + account_indexers.insert("test".to_string(), config.clone().into()); let mut registry = IndexersByAccount::new(StorageKeys::Registry); registry.insert(account_id, account_indexers); let contract = Contract { From 9417874e308d15cff341a775941bdf3f2c290d4d Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 16:54:51 +1300 Subject: [PATCH 08/14] feat: Migrate contract types --- registry/contract/src/lib.rs | 253 ++++++++++++++++------------------- 1 file changed, 113 insertions(+), 140 deletions(-) diff --git a/registry/contract/src/lib.rs b/registry/contract/src/lib.rs index b62c7cf1e..53cd29277 100644 --- a/registry/contract/src/lib.rs +++ b/registry/contract/src/lib.rs @@ -11,6 +11,7 @@ use registry_types::{ type FunctionName = String; +#[derive(BorshDeserialize, BorshSerialize, Debug)] pub struct OldContract { registry: OldIndexersByAccount, account_roles: Vec, @@ -105,52 +106,30 @@ impl Default for Contract { // Implement the contract structure #[near_bindgen] impl Contract { - // #[private] - // #[init(ignore_state)] - // pub fn migrate() -> Self { - // let state: OldState = env::state_read().expect("failed to parse existing state"); - // - // let mut registry = IndexersByAccount::new(StorageKeys::RegistryV2); - // - // for (account_id, indexers) in state.registry.iter() { - // let mut new_indexers: IndexerConfigByFunctionName = IndexerConfigByFunctionName::new( - // StorageKeys::AccountV2(env::sha256_array(account_id.as_bytes())), - // ); - // - // for (function_name, indexer_config) in indexers.iter() { - // new_indexers.insert( - // function_name.to_string(), - // OldIndexerConfig { - // updated_at_block_height: None, - // created_at_block_height: env::block_height(), - // schema: indexer_config.schema.clone(), - // start_block: StartBlock::Latest, - // code: indexer_config.code.clone(), - // start_block_height: indexer_config.start_block_height, - // filter: indexer_config.filter.clone(), - // }, - // ); - // } - // - // registry.insert(account_id.clone(), new_indexers); - // } - // - // let account_roles: Vec<_> = Contract::default() - // .account_roles - // .into_iter() - // .chain( - // state - // .account_roles - // .into_iter() - // .filter(|account_role| account_role.role == Role::User), - // ) - // .collect(); - // - // Self { - // registry, - // account_roles, - // } - // } + #[private] + #[init(ignore_state)] + pub fn migrate() -> Self { + let state: OldContract = env::state_read().expect("failed to parse existing state"); + + let mut registry = IndexersByAccount::new(StorageKeys::RegistryV3); + + for (account_id, indexers) in state.registry.iter() { + let mut new_indexers: IndexerConfigByFunctionName = IndexerConfigByFunctionName::new( + StorageKeys::AccountV3(env::sha256_array(account_id.as_bytes())), + ); + + for (function_name, indexer_config) in indexers.iter() { + new_indexers.insert(function_name.to_string(), indexer_config.clone().into()); + } + + registry.insert(account_id.clone(), new_indexers); + } + + Self { + registry, + account_roles: state.account_roles, + } + } pub fn near_social_indexer_rule() -> OldIndexerRule { let contract = "social.near"; @@ -444,100 +423,94 @@ mod tests { use std::collections::HashMap; - // #[test] - // fn migrate() { - // let mut registry = IndexersByAccount::new(StorageKeys::RegistryV1); - // let account_id = "morgs.near".parse::().unwrap(); - // let mut functions = IndexerConfigByFunctionName::new(StorageKeys::AccountV1( - // env::sha256_array(account_id.as_bytes()), - // )); - // - // functions.insert( - // "test".to_string(), - // IndexerConfig { - // code: "return block;".to_string(), - // start_block_height: None, - // schema: None, - // filter: Contract::near_social_indexer_rule(), - // }, - // ); - // functions.insert( - // "test2".to_string(), - // IndexerConfig { - // code: "return block2;".to_string(), - // start_block_height: None, - // schema: None, - // filter: Contract::near_social_indexer_rule(), - // }, - // ); - // registry.insert(account_id.clone(), functions); - // - // env::state_write(&OldState { - // registry, - // account_roles: vec![ - // AccountRole { - // account_id: account_id.clone(), - // role: Role::Owner, - // }, - // AccountRole { - // account_id: "should-be-removed.near".parse().unwrap(), - // role: Role::Owner, - // }, - // AccountRole { - // account_id: "bob.near".parse().unwrap(), - // role: Role::User, - // }, - // ], - // }); - // - // let contract = Contract::migrate(); - // - // assert_eq!( - // contract - // .registry - // .get(&account_id) - // .unwrap() - // .get("test") - // .unwrap(), - // &IndexerConfig { - // code: "return block;".to_string(), - // start_block_height: None, - // schema: None, - // start_block: StartBlock::Latest, - // filter: Contract::near_social_indexer_rule(), - // updated_at_block_height: None, - // created_at_block_height: env::block_height(), - // } - // ); - // assert_eq!( - // contract - // .registry - // .get(&account_id) - // .unwrap() - // .get("test2") - // .unwrap(), - // &IndexerConfig { - // code: "return block2;".to_string(), - // start_block_height: None, - // schema: None, - // start_block: StartBlock::Latest, - // filter: Contract::near_social_indexer_rule(), - // updated_at_block_height: None, - // created_at_block_height: env::block_height(), - // } - // ); - // assert_eq!( - // contract.account_roles, - // Contract::default() - // .account_roles - // .into_iter() - // .chain(std::iter::once(AccountRole { - // account_id: "bob.near".parse().unwrap(), - // role: Role::User, - // })) - // .collect::>() - // ); - // } + #[test] + fn migrate() { + let mut registry = OldIndexersByAccount::new(StorageKeys::RegistryV2); + let account_id = "morgs.near".parse::().unwrap(); + let mut functions = OldIndexerConfigByFunctionName::new(StorageKeys::AccountV2( + env::sha256_array(account_id.as_bytes()), + )); + + functions.insert( + "test".to_string(), + OldIndexerConfig { + code: "return block;".to_string(), + start_block_height: None, + schema: None, + filter: Contract::near_social_indexer_rule(), + created_at_block_height: 10, + updated_at_block_height: None, + }, + ); + functions.insert( + "test2".to_string(), + OldIndexerConfig { + code: "return block2;".to_string(), + start_block_height: Some(100), + schema: Some(String::from("create table blah")), + filter: OldIndexerRule { + id: None, + name: None, + indexer_rule_kind: IndexerRuleKind::Action, + matching_rule: MatchingRule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success, + }, + }, + created_at_block_height: 10, + updated_at_block_height: Some(20), + }, + ); + registry.insert(account_id.clone(), functions); + + env::state_write(&OldContract { + registry, + account_roles: Contract::default().account_roles, + }); + + let contract = Contract::migrate(); + + assert_eq!( + contract + .registry + .get(&account_id) + .unwrap() + .get("test") + .unwrap(), + &IndexerConfig { + code: "return block;".to_string(), + start_block: StartBlock::Latest, + schema: String::new(), + rule: Rule::ActionFunctionCall { + affected_account_id: String::from("social.near"), + status: Status::Any, + function: String::from("set") + }, + updated_at_block_height: None, + created_at_block_height: 10, + } + ); + assert_eq!( + contract + .registry + .get(&account_id) + .unwrap() + .get("test2") + .unwrap(), + &IndexerConfig { + code: "return block2;".to_string(), + schema: String::from("create table blah"), + start_block: StartBlock::Height(100), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Success + }, + updated_at_block_height: Some(20), + created_at_block_height: 10, + } + ); + assert_eq!(contract.account_roles, Contract::default().account_roles); + } #[test] fn list_account_roles() { From e99a590937a1d61b69c56e3ea50bacedd95685d1 Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 16:57:45 +1300 Subject: [PATCH 09/14] fix: Use latest storage keys --- registry/contract/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/contract/src/lib.rs b/registry/contract/src/lib.rs index 53cd29277..29b938ee6 100644 --- a/registry/contract/src/lib.rs +++ b/registry/contract/src/lib.rs @@ -72,7 +72,7 @@ pub struct AccountRole { impl Default for Contract { fn default() -> Self { Self { - registry: IndexersByAccount::new(StorageKeys::Registry), + registry: IndexersByAccount::new(StorageKeys::RegistryV3), account_roles: vec![ AccountRole { account_id: "morgs.near".parse().unwrap(), @@ -297,7 +297,7 @@ impl Contract { let account_indexers = self.registry .entry(account_id.clone()) - .or_insert(IndexerConfigByFunctionName::new(StorageKeys::Account( + .or_insert(IndexerConfigByFunctionName::new(StorageKeys::AccountV3( env::sha256_array(account_id.as_bytes()), ))); From 1b1a92e6d3a76148b8968f86aa43d3a1c7036200 Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 20:47:19 +1300 Subject: [PATCH 10/14] feat: Add new methods for new types --- registry/contract/src/lib.rs | 186 ++++++++++++++++++++++++++++++++--- registry/types/src/lib.rs | 14 ++- 2 files changed, 183 insertions(+), 17 deletions(-) diff --git a/registry/contract/src/lib.rs b/registry/contract/src/lib.rs index 29b938ee6..38a9909eb 100644 --- a/registry/contract/src/lib.rs +++ b/registry/contract/src/lib.rs @@ -5,8 +5,8 @@ use near_sdk::store::UnorderedMap; use near_sdk::{env, log, near_bindgen, serde_json, AccountId, BorshStorageKey, CryptoHash}; use registry_types::{ - AccountOrAllIndexers, IndexerConfig, IndexerRuleKind, MatchingRule, OldIndexerConfig, - OldIndexerRule, Rule, StartBlock, Status, + AccountIndexers, AllIndexers, IndexerConfig, IndexerRuleKind, MatchingRule, + OldAccountOrAllIndexers, OldIndexerConfig, OldIndexerRule, Rule, StartBlock, Status, }; type FunctionName = String; @@ -252,6 +252,54 @@ impl Contract { }) } + pub fn register( + &mut self, + function_name: String, + code: String, + schema: String, + rule: Rule, + start_block: StartBlock, + ) { + let account_id = env::signer_account_id(); + + log!( + "Registering function {} for account {}", + &function_name, + &account_id + ); + + let account_indexers = + self.registry + .entry(account_id.clone()) + .or_insert(IndexerConfigByFunctionName::new(StorageKeys::AccountV3( + env::sha256_array(account_id.as_bytes()), + ))); + + match account_indexers.entry(function_name) { + near_sdk::store::unordered_map::Entry::Occupied(mut entry) => { + let indexer = entry.get(); + entry.insert(IndexerConfig { + code, + schema, + rule, + start_block, + updated_at_block_height: Some(env::block_height()), + created_at_block_height: indexer.created_at_block_height, + }); + } + near_sdk::store::unordered_map::Entry::Vacant(entry) => { + entry.insert(IndexerConfig { + code, + schema, + rule, + start_block, + updated_at_block_height: None, + created_at_block_height: env::block_height(), + }); + } + } + } + // Public method - registers indexer code under then function_name pub fn register_indexer_function( &mut self, @@ -371,7 +419,7 @@ impl Contract { } } - pub fn list_indexer_functions(&self, account_id: Option) -> AccountOrAllIndexers { + pub fn list_indexer_functions(&self, account_id: Option) -> OldAccountOrAllIndexers { match account_id { Some(account_id) => { let account_id = account_id.parse::().unwrap_or_else(|_| { @@ -384,7 +432,7 @@ impl Contract { ) }); - AccountOrAllIndexers::Account( + OldAccountOrAllIndexers::Account( account_indexers .iter() .map(|(function_name, config)| { @@ -393,7 +441,7 @@ impl Contract { .collect(), ) } - None => AccountOrAllIndexers::All( + None => OldAccountOrAllIndexers::All( self.registry .iter() .map(|(account_id, account_indexers)| { @@ -411,12 +459,34 @@ impl Contract { ), } } + + pub fn list_by_account(&self, account_id: AccountId) -> AccountIndexers { + self.registry + .get(&account_id) + .unwrap_or(&IndexerConfigByFunctionName::new(StorageKeys::AccountV3( + env::sha256_array(account_id.as_bytes()), + ))) + .iter() + .map(|(function_name, config)| (function_name.clone(), config.clone())) + .collect() + } + + pub fn list_all(&self) -> AllIndexers { + self.registry + .iter() + .map(|(account_id, account_indexers)| { + ( + account_id.clone(), + account_indexers + .iter() + .map(|(function_name, config)| (function_name.clone(), config.clone())) + .collect(), + ) + }) + .collect() + } } -/* - * The rest of this file holds the inline tests for the code above - * Learn more about Rust tests: https://doc.rust-lang.org/book/ch11-01-writing-tests.html - */ #[cfg(test)] mod tests { use super::*; @@ -1506,7 +1576,7 @@ mod tests { assert_eq!( contract.list_indexer_functions(None), - AccountOrAllIndexers::All(HashMap::from([( + OldAccountOrAllIndexers::All(HashMap::from([( "bob.near".parse().unwrap(), HashMap::from([("test".to_string(), config)]) )])) @@ -1537,7 +1607,7 @@ mod tests { assert_eq!( contract.list_indexer_functions(Some("bob.near".to_string())), - AccountOrAllIndexers::Account(HashMap::from([("test".to_string(), config)])) + OldAccountOrAllIndexers::Account(HashMap::from([("test".to_string(), config)])) ); } @@ -1576,7 +1646,99 @@ mod tests { assert_eq!( contract.list_indexer_functions(Some("alice.near".to_string())), - AccountOrAllIndexers::Account(HashMap::from([("test".to_string(), config)])) + OldAccountOrAllIndexers::Account(HashMap::from([("test".to_string(), config)])) + ); + } + + #[test] + fn list_all_indexers() { + let mut contract = Contract::default(); + + contract.register( + String::from("test"), + String::from("code"), + String::from("schema"), + Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Any, + }, + StartBlock::Latest, + ); + + assert_eq!( + contract.list_all(), + HashMap::from([( + "bob.near".parse::().unwrap(), + HashMap::from([( + String::from("test"), + IndexerConfig { + code: String::from("code"), + schema: String::from("schema"), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Any, + }, + start_block: StartBlock::Latest, + updated_at_block_height: None, + created_at_block_height: env::block_height(), + } + )]) + )]) + ); + } + + #[test] + fn list_empty_account_indexers() { + let mut contract = Contract::default(); + + contract.register( + String::from("test"), + String::from("code"), + String::from("schema"), + Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Any, + }, + StartBlock::Latest, + ); + + assert_eq!( + contract.list_by_account("morgs.near".parse().unwrap()), + HashMap::new() + ); + } + + #[test] + fn list_account_indexers() { + let mut contract = Contract::default(); + + contract.register( + String::from("test"), + String::from("code"), + String::from("schema"), + Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Any, + }, + StartBlock::Latest, + ); + + assert_eq!( + contract.list_by_account(env::signer_account_id()), + HashMap::from([( + String::from("test"), + IndexerConfig { + code: String::from("code"), + schema: String::from("schema"), + rule: Rule::ActionAny { + affected_account_id: String::from("social.near"), + status: Status::Any, + }, + start_block: StartBlock::Latest, + updated_at_block_height: None, + created_at_block_height: env::block_height(), + } + )]) ); } } diff --git a/registry/types/src/lib.rs b/registry/types/src/lib.rs index 473ec073e..e166769a9 100644 --- a/registry/types/src/lib.rs +++ b/registry/types/src/lib.rs @@ -127,6 +127,12 @@ impl From for OldIndexerConfig { } } +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] +pub enum OldAccountOrAllIndexers { + All(HashMap>), + Account(HashMap), +} + #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum Status { @@ -226,8 +232,6 @@ impl From for IndexerConfig { } } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] -pub enum AccountOrAllIndexers { - All(HashMap>), - Account(HashMap), -} +pub type AccountIndexers = HashMap; + +pub type AllIndexers = HashMap; From 09dbaf43d32fa2efadd32b457aec465358ebb553 Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Mon, 5 Feb 2024 21:17:26 +1300 Subject: [PATCH 11/14] feat: Use old types in block-streamer/coordinator --- block-streamer/src/block_stream.rs | 2 +- block-streamer/src/indexer_config.rs | 2 +- block-streamer/src/rules/mod.rs | 2 +- block-streamer/src/rules/outcomes_reducer.rs | 2 +- block-streamer/src/server/block_streamer_service.rs | 2 +- coordinator/src/main.rs | 2 +- coordinator/src/registry.rs | 6 ++++-- 7 files changed, 10 insertions(+), 8 deletions(-) diff --git a/block-streamer/src/block_stream.rs b/block-streamer/src/block_stream.rs index fd98e03cd..a605f30c4 100644 --- a/block-streamer/src/block_stream.rs +++ b/block-streamer/src/block_stream.rs @@ -294,7 +294,7 @@ mod tests { ) .unwrap(), function_name: "test".to_string(), - indexer_rule: registry_types::IndexerRule { + indexer_rule: registry_types::OldIndexerRule { indexer_rule_kind: registry_types::IndexerRuleKind::Action, matching_rule: registry_types::MatchingRule::ActionAny { affected_account_id: "queryapi.dataplatform.near".to_string(), diff --git a/block-streamer/src/indexer_config.rs b/block-streamer/src/indexer_config.rs index aebd7bb2c..435c4aa3b 100644 --- a/block-streamer/src/indexer_config.rs +++ b/block-streamer/src/indexer_config.rs @@ -2,7 +2,7 @@ use near_lake_framework::near_indexer_primitives::types::AccountId; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; -use registry_types::IndexerRule; +use registry_types::OldIndexerRule as IndexerRule; #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] pub struct IndexerConfig { diff --git a/block-streamer/src/rules/mod.rs b/block-streamer/src/rules/mod.rs index 5c5058514..f87b906fd 100644 --- a/block-streamer/src/rules/mod.rs +++ b/block-streamer/src/rules/mod.rs @@ -3,7 +3,7 @@ pub mod outcomes_reducer; pub mod types; use near_lake_framework::near_indexer_primitives::StreamerMessage; -use registry_types::{IndexerRule, MatchingRule}; +use registry_types::{MatchingRule, OldIndexerRule as IndexerRule}; use types::{ChainId, IndexerRuleMatch}; diff --git a/block-streamer/src/rules/outcomes_reducer.rs b/block-streamer/src/rules/outcomes_reducer.rs index 934eda37c..e66fab593 100644 --- a/block-streamer/src/rules/outcomes_reducer.rs +++ b/block-streamer/src/rules/outcomes_reducer.rs @@ -115,7 +115,7 @@ fn build_indexer_rule_match_payload( #[cfg(test)] mod tests { - use registry_types::{IndexerRule, IndexerRuleKind, MatchingRule, Status}; + use registry_types::{IndexerRuleKind, MatchingRule, OldIndexerRule as IndexerRule, Status}; use crate::rules::outcomes_reducer::reduce_indexer_rule_matches_from_outcomes; use crate::rules::types::{ChainId, IndexerRuleMatch}; diff --git a/block-streamer/src/server/block_streamer_service.rs b/block-streamer/src/server/block_streamer_service.rs index 829ec4876..2fbb6aee5 100644 --- a/block-streamer/src/server/block_streamer_service.rs +++ b/block-streamer/src/server/block_streamer_service.rs @@ -6,7 +6,7 @@ use tonic::{Request, Response, Status}; use crate::indexer_config::IndexerConfig; use crate::rules::types::ChainId; -use registry_types::{IndexerRule, IndexerRuleKind, MatchingRule}; +use registry_types::{IndexerRuleKind, MatchingRule, OldIndexerRule as IndexerRule}; use crate::block_stream; use crate::server::blockstreamer; diff --git a/coordinator/src/main.rs b/coordinator/src/main.rs index e308f1613..66322065b 100644 --- a/coordinator/src/main.rs +++ b/coordinator/src/main.rs @@ -255,7 +255,7 @@ mod tests { use mockall::predicate; use std::collections::HashMap; - use registry_types::{IndexerRule, IndexerRuleKind, MatchingRule, Status}; + use registry_types::{IndexerRuleKind, MatchingRule, OldIndexerRule as IndexerRule, Status}; use crate::registry::IndexerConfig; diff --git a/coordinator/src/registry.rs b/coordinator/src/registry.rs index db13c77af..b3ed7776e 100644 --- a/coordinator/src/registry.rs +++ b/coordinator/src/registry.rs @@ -8,7 +8,9 @@ use near_jsonrpc_client::JsonRpcClient; use near_jsonrpc_primitives::types::query::QueryResponseKind; use near_primitives::types::{AccountId, BlockReference, Finality, FunctionArgs}; use near_primitives::views::QueryRequest; -use registry_types::{AccountOrAllIndexers, IndexerRule}; +use registry_types::{ + OldAccountOrAllIndexers as AccountOrAllIndexers, OldIndexerRule as IndexerRule, +}; use crate::utils::exponential_retry; @@ -69,7 +71,7 @@ impl RegistryImpl { fn enrich_indexer_registry( &self, - registry: HashMap>, + registry: HashMap>, ) -> IndexerRegistry { registry .into_iter() From f202d897bb26288504043fcf13b40b94653fa642 Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Wed, 7 Feb 2024 14:31:07 +1300 Subject: [PATCH 12/14] refactor: Rename `Interruption` -> `Continue` --- registry/types/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/registry/types/src/lib.rs b/registry/types/src/lib.rs index e166769a9..ee9d1deaa 100644 --- a/registry/types/src/lib.rs +++ b/registry/types/src/lib.rs @@ -101,7 +101,7 @@ impl From for OldIndexerConfig { fn from(config: IndexerConfig) -> Self { let start_block_height = match config.start_block { StartBlock::Latest => None, - StartBlock::Interruption => None, + StartBlock::Continue => None, StartBlock::Height(height) => Some(height), }; @@ -198,12 +198,13 @@ impl From for Rule { #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum StartBlock { - /// Specific block height to start indexing from + /// Specifies the particular block height from which to start indexing from. Height(u64), - /// Real-time indexing, always taking the latest finalized block to stream + /// Starts indexing from the most recently finalized block. Latest, - /// Starts indexing from the block the Indexer was interrupted last time - Interruption, + /// Resumes indexing from the block immediately following the last one successfully indexed + /// prior to update. + Continue, } #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] From 27fe54b8fffb4938aa3ddbf4b35199199664bacf Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Wed, 7 Feb 2024 15:08:42 +1300 Subject: [PATCH 13/14] feat: Prevent non-owners from using '*' --- registry/contract/src/lib.rs | 71 ++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/registry/contract/src/lib.rs b/registry/contract/src/lib.rs index 38a9909eb..f33835461 100644 --- a/registry/contract/src/lib.rs +++ b/registry/contract/src/lib.rs @@ -268,6 +268,22 @@ impl Contract { &account_id ); + match &rule { + Rule::ActionAny { + affected_account_id, + .. + } + | Rule::ActionFunctionCall { + affected_account_id, + .. + } => { + if affected_account_id == "*" { + self.assert_roles(vec![Role::Owner]); + } + } + _ => {} + } + let account_indexers = self.registry .entry(account_id.clone()) @@ -331,6 +347,22 @@ impl Contract { env::panic_str(&format!("Invalid filter JSON {}", e)); }); + match &filter_rule.matching_rule { + MatchingRule::ActionAny { + affected_account_id, + .. + } + | MatchingRule::ActionFunctionCall { + affected_account_id, + .. + } => { + if affected_account_id == "*" { + self.assert_roles(vec![Role::Owner]); + } + } + _ => {} + } + filter_rule } None => Contract::near_social_indexer_rule(), @@ -1235,6 +1267,45 @@ mod tests { ); } + #[test] + #[should_panic(expected = "Account bob.near does not have one of required roles [Owner]")] + fn prevents_non_owners_from_using_wildcard() { + let mut contract = Contract::default(); + contract.account_roles.push(AccountRole { + account_id: "bob.near".parse().unwrap(), + role: Role::User, + }); + + contract.register_indexer_function( + String::from("name"), + String::from("code"), + Some(0), + Some(String::from("schema")), + None, + Some(r#"{"indexer_rule_kind":"Action","matching_rule":{"rule":"ACTION_ANY","affected_account_id":"*","status":"SUCCESS"}}"#.to_string()), + ); + } + + #[test] + fn allows_owners_to_use_wildcard() { + let mut contract = Contract::default(); + contract.account_roles.push(AccountRole { + account_id: "bob.near".parse().unwrap(), + role: Role::Owner, + }); + + contract.register_indexer_function( + String::from("name"), + String::from("code"), + Some(0), + Some(String::from("schema")), + None, + Some(r#"{"indexer_rule_kind":"Action","matching_rule":{"rule":"ACTION_ANY","affected_account_id":"*","status":"SUCCESS"}}"#.to_string()), + ); + + assert_eq!(contract.registry.len(), 1); + } + #[test] fn users_can_remove_their_own_functions() { let account_id = "bob.near".parse::().unwrap(); From cc7ad3eb18ad38b7c8bf4cdff7067eb4fa7fbc35 Mon Sep 17 00:00:00 2001 From: Morgan Mccauley Date: Wed, 7 Feb 2024 15:14:35 +1300 Subject: [PATCH 14/14] fix: Update old type usage after rebase --- coordinator/src/migration.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coordinator/src/migration.rs b/coordinator/src/migration.rs index 38575b23b..514fbb596 100644 --- a/coordinator/src/migration.rs +++ b/coordinator/src/migration.rs @@ -281,7 +281,7 @@ mod tests { use std::collections::HashMap; use mockall::predicate; - use registry_types::{IndexerRule, IndexerRuleKind, MatchingRule, Status}; + use registry_types::{IndexerRuleKind, MatchingRule, OldIndexerRule, Status}; use crate::registry::IndexerConfig; @@ -296,7 +296,7 @@ mod tests { function_name: "test".to_string(), code: String::new(), schema: Some(String::new()), - filter: IndexerRule { + filter: OldIndexerRule { id: None, name: None, indexer_rule_kind: IndexerRuleKind::Action, @@ -369,7 +369,7 @@ mod tests { function_name: "test".to_string(), code: String::new(), schema: Some(String::new()), - filter: IndexerRule { + filter: OldIndexerRule { id: None, name: None, indexer_rule_kind: IndexerRuleKind::Action,