diff --git a/explorer/src/api/graphql/mod.rs b/explorer/src/api/graphql/mod.rs index c93de68f2f..afbd16aa73 100644 --- a/explorer/src/api/graphql/mod.rs +++ b/explorer/src/api/graphql/mod.rs @@ -855,6 +855,18 @@ impl Transaction { Ok(blocks.iter().map(|b| Block::from(Arc::clone(b))).collect()) } + /// Initial bootstrap config params (initial fragments), only present in Block0 + pub async fn initial_configuration_params( + &self, + context: &Context<'_>, + ) -> FieldResult> { + let transaction = self.get_contents(context).await?; + match transaction.config_params { + Some(params) => Ok(Some(config_param::ConfigParams::from(¶ms))), + None => Ok(None), + } + } + pub async fn inputs(&self, context: &Context<'_>) -> FieldResult> { let transaction = self.get_contents(context).await?; Ok(transaction diff --git a/explorer/src/db/indexing.rs b/explorer/src/db/indexing.rs index f14373c980..4f4fc911f9 100644 --- a/explorer/src/db/indexing.rs +++ b/explorer/src/db/indexing.rs @@ -8,7 +8,7 @@ use chain_impl_mockchain::{ certificate::{ Certificate, ExternalProposalId, PoolId, PoolRegistration, PoolRetirement, VotePlanId, }, - fragment::{Fragment, FragmentId}, + fragment::{ConfigParams, Fragment, FragmentId}, header::{BlockDate, ChainLength, Epoch, HeaderId as HeaderHash}, key::BftLeaderId, transaction::{InputEnum, TransactionSlice, Witness}, @@ -70,6 +70,7 @@ pub struct ExplorerTransaction { pub outputs: Vec, pub certificate: Option, pub offset_in_block: u32, + pub config_params: Option, } /// Unified Input representation for utxo and account inputs as used in the graphql API @@ -161,6 +162,14 @@ impl ExplorerBlock { let fragment_id = fragment.id(); let offset: u32 = offset.try_into().unwrap(); let metx = match fragment { + Fragment::Initial(config) => Some(ExplorerTransaction { + id: fragment_id, + inputs: vec![], + outputs: vec![], + certificate: None, + offset_in_block: offset, + config_params: Some(config.clone()), + }), Fragment::Transaction(tx) => { let tx = tx.as_slice(); Some(ExplorerTransaction::from( @@ -277,6 +286,7 @@ impl ExplorerBlock { outputs, certificate: None, offset_in_block: offset, + config_params: None, }) } _ => None, @@ -429,6 +439,7 @@ impl ExplorerTransaction { outputs: new_outputs, certificate, offset_in_block, + config_params: None, } } diff --git a/explorer/src/settings.rs b/explorer/src/settings.rs index 3c946b42b5..f9e187b580 100644 --- a/explorer/src/settings.rs +++ b/explorer/src/settings.rs @@ -18,7 +18,7 @@ const DEFAULT_LOG_SETTINGS_ENTRY: LogSettingsEntry = LogSettingsEntry { }; const DEFAULT_QUERY_DEPTH_LIMIT: usize = 15; -const DEFAULT_QUERY_COMPLEXITY_LIMIT: usize = 40; +const DEFAULT_QUERY_COMPLEXITY_LIMIT: usize = 100; lazy_static! { pub static ref LOG_FILTER_LEVEL_POSSIBLE_VALUES: Vec<&'static str> = { diff --git a/explorer/src/tests.rs b/explorer/src/tests.rs index 868e950df5..9ab4b2ef32 100644 --- a/explorer/src/tests.rs +++ b/explorer/src/tests.rs @@ -67,6 +67,23 @@ pub fn get_valid_block(explorer: &Explorer, genesis_block: Hash) { assert_eq!(block_id, genesis_block.to_string()); } +pub fn verify_config_params_present(explorer: &Explorer, jormungandr: JormungandrProcess) { + let binding = jormungandr.block0_configuration().to_block(); + + // first fragment txs should contain config params + let block0fragment = binding.fragments().next().unwrap(); + + let params = explorer + .transaction(Hash::from_str(&block0fragment.hash().to_string()).unwrap()) + .unwrap() + .data + .unwrap() + .transaction + .initial_configuration_params; + + assert!(params.is_some()); +} + #[test] pub fn explorer_tests() { let config = ExplorerTestConfig::default(); @@ -75,4 +92,5 @@ pub fn explorer_tests() { get_invalid_block(explorer.client()); get_valid_block(explorer.client(), jormungandr.genesis_block_hash()); + verify_config_params_present(explorer.client(), jormungandr); } diff --git a/testing/jormungandr-automation/resources/explorer/graphql/schema.graphql b/testing/jormungandr-automation/resources/explorer/graphql/schema.graphql index d4aa2b888f..7c85a51680 100644 --- a/testing/jormungandr-automation/resources/explorer/graphql/schema.graphql +++ b/testing/jormungandr-automation/resources/explorer/graphql/schema.graphql @@ -44,7 +44,10 @@ type BlockConnection { pageInfo: PageInfo! """A list of edges.""" - edges: [BlockEdge] + edges: [BlockEdge!]! + + """A list of nodes.""" + nodes: [Block!]! totalCount: Int! } @@ -60,11 +63,11 @@ type BlockDate { """An edge in a connection.""" type BlockEdge { - """The item at the end of the edge""" - node: Block! - """A cursor for use in pagination""" cursor: String! + + """The item at the end of the edge""" + node: Block! } type Branch { @@ -222,17 +225,20 @@ type PoolConnection { pageInfo: PageInfo! """A list of edges.""" - edges: [PoolEdge] + edges: [PoolEdge!]! + + """A list of nodes.""" + nodes: [Pool!]! totalCount: Int! } """An edge in a connection.""" type PoolEdge { - """The item at the end of the edge""" - node: Pool! - """A cursor for use in pagination""" cursor: String! + + """The item at the end of the edge""" + node: Pool! } scalar PoolId @@ -283,7 +289,6 @@ type Proposal { """ get the vote options range - this is the available range of choices to make for the given proposal. all casted votes for this proposals ought to be in within the given range @@ -409,6 +414,11 @@ type Transaction { """All the blocks this transaction is included in""" blocks: [Block!]! + + """ + Initial bootstrap config params (initial fragments), only present in Block0 + """ + initialConfigurationParams: ConfigParams inputs: [TransactionInput!]! outputs: [TransactionOutput!]! certificate: Certificate @@ -419,17 +429,20 @@ type TransactionConnection { pageInfo: PageInfo! """A list of edges.""" - edges: [TransactionEdge] + edges: [TransactionEdge!]! + + """A list of nodes.""" + nodes: [Transaction!]! totalCount: Int! } """An edge in a connection.""" type TransactionEdge { - """The item at the end of the edge""" - node: Transaction! - """A cursor for use in pagination""" cursor: String! + + """The item at the end of the edge""" + node: Transaction! } type TransactionInput { @@ -534,17 +547,20 @@ type VotePlanStatusConnection { pageInfo: PageInfo! """A list of edges.""" - edges: [VotePlanStatusEdge] + edges: [VotePlanStatusEdge!]! + + """A list of nodes.""" + nodes: [VotePlanStatus!]! totalCount: Int! } """An edge in a connection.""" type VotePlanStatusEdge { - """The item at the end of the edge""" - node: VotePlanStatus! - """A cursor for use in pagination""" cursor: String! + + """The item at the end of the edge""" + node: VotePlanStatus! } type VoteProposalStatus { @@ -564,17 +580,20 @@ type VoteStatusConnection { pageInfo: PageInfo! """A list of edges.""" - edges: [VoteStatusEdge] + edges: [VoteStatusEdge!]! + + """A list of nodes.""" + nodes: [VoteStatus!]! totalCount: Int! } """An edge in a connection.""" type VoteStatusEdge { - """The item at the end of the edge""" - node: VoteStatus! - """A cursor for use in pagination""" cursor: String! + + """The item at the end of the edge""" + node: VoteStatus! } type VoteTally { diff --git a/testing/jormungandr-automation/resources/explorer/graphql/transaction_by_id.graphql b/testing/jormungandr-automation/resources/explorer/graphql/transaction_by_id.graphql index 15e4ab3ec7..35595c7007 100644 --- a/testing/jormungandr-automation/resources/explorer/graphql/transaction_by_id.graphql +++ b/testing/jormungandr-automation/resources/explorer/graphql/transaction_by_id.graphql @@ -1,6 +1,8 @@ query TransactionById($id: String!){ transaction(id: $id) { id + __typename + initialConfigurationParams { configParams {...configParam}} blocks{id date{...blockDate}} inputs{amount address{id}} outputs{amount address{id}}}} @@ -9,3 +11,83 @@ fragment blockDate on BlockDate{ epoch{id} slot } + +fragment configParam on ConfigParam +{ + __typename + ... on Block0Date { block0Date } + ... on Discrimination { discrimination } + ... on ConsensusType { consensusType } + ... on SlotsPerEpoch { slotsPerEpoch } + ... on SlotDuration { slotDuration} + ... on EpochStabilityDepth { epochStabilityDepth } + ... on Milli { milli} + ... on BlockContentMaxSize { blockContentMaxSize} + ... on AddBftLeader { addBftLeader{ id }} + ... on RemoveBftLeader { removeBftLeader { id }} + ... on LinearFee { + constant + coefficient + certificate + perCertificateFees { + certificatePoolRegistration + certificateStakeDelegation + certificateOwnerStakeDelegation + } + perVoteCertificateFees { + certificateVotePlan + certificateVoteCast + }} + ... on ProposalExpiration{ proposalExpiration } + ... on KesUpdateSpeed { kesUpdateSpeed} + ... on TreasuryAdd { treasuryAdd } + ... on TreasuryParams { treasuryParams { + fixed + ratio { + numerator + denominator + } + maxLimit + }} + ... on RewardPot { rewardPot } + ... on RewardParams { rewardParams { + __typename + ... on LinearRewardParams{ + constant + ratio { + numerator + denominator + } + epochStart + epochRate + } + ... on HalvingRewardParams { + constant + ratio { + numerator + denominator + } + epochStart + epochRate + } + }} + ... on PerCertificateFee{ + certificatePoolRegistration + certificateStakeDelegation + certificateOwnerStakeDelegation + } + ... on FeesInTreasury { feesInTreasury} + ... on RewardLimitNone { rewardLimitNone } + ... on RewardLimitByAbsoluteStake { rewardLimitByAbsoluteStake { + numerator + denominator + }} + ... on PoolRewardParticipationCapping { min max } + ... on AddCommitteeId { addCommitteeId} + ... on RemoveCommitteeId { removeCommitteeId } + ... on PerVoteCertificateFee { + certificateVotePlan + certificateVoteCast + } + ... on TransactionMaxExpiryEpochs { transactionMaxExpiryEpochs } +} diff --git a/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/block_by_id_verifier.rs b/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/block_by_id_verifier.rs index 69c8c75db0..9757928c87 100644 --- a/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/block_by_id_verifier.rs +++ b/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/block_by_id_verifier.rs @@ -109,8 +109,8 @@ impl ExplorerVerifier { if !block.contents().is_empty() { for fragment in block.fragments() { - for edge in explorer_block.transactions.edges.as_ref().unwrap() { - let explorer_transaction = &edge.as_ref().unwrap().node; + for edge in &explorer_block.transactions.edges { + let explorer_transaction = &edge.node; if fragment.hash().to_string() == explorer_transaction.id { matching_fragments_count += 1; match &explorer_transaction.certificate { diff --git a/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/mod.rs b/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/mod.rs index 55844c5f7b..b58ead9f6c 100644 --- a/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/mod.rs +++ b/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/mod.rs @@ -105,15 +105,10 @@ impl ExplorerVerifier { ); }; - assert!(explorer_transactions.edges.is_some()); + assert_eq!(fragment_statuses.len(), explorer_transactions.edges.len()); - assert_eq!( - fragment_statuses.len(), - explorer_transactions.edges.as_ref().unwrap().len() - ); - - for edges in explorer_transactions.edges.unwrap().iter() { - let node = &edges.as_ref().unwrap().node; + for edges in explorer_transactions.edges.iter() { + let node = &edges.node; assert!(fragment_statuses.get(&node.id.to_string()).is_some()); let fragment_status = fragment_statuses.get(&node.id.to_string()).unwrap().1; assert!( diff --git a/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/vote_plan_verifier.rs b/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/vote_plan_verifier.rs index b661d71947..abd4701426 100644 --- a/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/vote_plan_verifier.rs +++ b/testing/jormungandr-automation/src/jormungandr/explorer/verifiers/vote_plan_verifier.rs @@ -134,19 +134,17 @@ impl ExplorerVerifier { explorer_proposal.votes.total_count as usize ); if vote_proposal_status.votes_cast == 0 { - assert!(explorer_proposal.votes.edges.unwrap().is_empty()); + assert!(explorer_proposal.votes.edges.is_empty()); } else { - let explorer_votes = explorer_proposal.votes.edges.unwrap(); + let explorer_votes = explorer_proposal.votes.edges; assert_eq!(explorer_votes.len(), vote_proposal_status.votes_cast); let votes = proposal_votes .get(&vote_proposal_status.proposal_id.to_string()) .unwrap(); for vote in votes { for explorer_vote in &explorer_votes { - if vote.0.public_key().to_string() - == explorer_vote.as_ref().unwrap().node.address.id - { - match &explorer_vote.as_ref().unwrap().node.payload { + if vote.0.public_key().to_string() == explorer_vote.node.address.id { + match &explorer_vote.node.payload { VotePayloadPublicStatus(choice) => { assert_eq!(choice.choice as u8, vote.1.as_byte()) } diff --git a/testing/jormungandr-integration-tests/src/jormungandr/explorer/explorer_sanity.rs b/testing/jormungandr-integration-tests/src/jormungandr/explorer/explorer_sanity.rs index f52520a095..deba6ea384 100644 --- a/testing/jormungandr-integration-tests/src/jormungandr/explorer/explorer_sanity.rs +++ b/testing/jormungandr-integration-tests/src/jormungandr/explorer/explorer_sanity.rs @@ -54,7 +54,7 @@ pub fn explorer_sanity_test() { let jcli: JCli = Default::default(); let faucet = thor::Wallet::default(); let receiver = thor::Wallet::default(); - let query_complexity_limit = 70; + let query_complexity_limit = 100; let attempts_number = 20; let mut config = ConfigurationBuilder::new(); @@ -112,10 +112,9 @@ fn blocks(explorer: &Explorer, blocks_from_logs: Vec) { .tip .blocks .edges - .unwrap() .iter() .skip(1) - .map(|x| Hash::from_str(&x.as_ref().unwrap().node.id).unwrap()) + .map(|x| Hash::from_str(&x.node.id).unwrap()) .collect::>(); let mut common_blocks = blocks_from_logs.clone(); @@ -133,7 +132,7 @@ fn blocks(explorer: &Explorer, blocks_from_logs: Vec) { fn stake_pools(explorer: &Explorer, initial_stake_pools: &[StakePool]) { let stake_pools = explorer.stake_pools(1000).unwrap(); - let explorer_stake_pools = stake_pools.data.unwrap().tip.all_stake_pools.edges.unwrap(); + let explorer_stake_pools = stake_pools.data.unwrap().tip.all_stake_pools.edges; // we are skipping first block because log doesn't contains genesis block assert_eq!( initial_stake_pools @@ -142,7 +141,7 @@ fn stake_pools(explorer: &Explorer, initial_stake_pools: &[StakePool]) { .collect::>(), explorer_stake_pools .iter() - .map(|x| x.as_ref().unwrap().node.id.clone()) + .map(|x| x.node.id.clone()) .collect::>(), "blocks are empty" ); diff --git a/testing/jormungandr-integration-tests/src/jormungandr/explorer/vote_plan.rs b/testing/jormungandr-integration-tests/src/jormungandr/explorer/vote_plan.rs index c7c4ec5dbf..d50f7c0c3d 100644 --- a/testing/jormungandr-integration-tests/src/jormungandr/explorer/vote_plan.rs +++ b/testing/jormungandr-integration-tests/src/jormungandr/explorer/vote_plan.rs @@ -31,7 +31,7 @@ const REWARD_INCREASE: u64 = 10; const SLOTS_PER_EPOCH: u32 = 20; const SLOT_DURATION: u8 = 4; -const VOTE_PLAN_QUERY_COMPLEXITY_LIMIT: u64 = 50; +const VOTE_PLAN_QUERY_COMPLEXITY_LIMIT: u64 = 100; const VOTE_PLAN_QUERY_DEPTH_LIMIT: u64 = 30; const VOTE_FOR_MARIO: u8 = 0; const VOTE_FOR_LUIGI: u8 = 1; diff --git a/testing/mjolnir/src/mjolnir_lib/generators/explorer.rs b/testing/mjolnir/src/mjolnir_lib/generators/explorer.rs index 16e82cd0c7..0371a207d7 100644 --- a/testing/mjolnir/src/mjolnir_lib/generators/explorer.rs +++ b/testing/mjolnir/src/mjolnir_lib/generators/explorer.rs @@ -29,10 +29,10 @@ impl ExplorerRequestGen { pub fn do_setup(&mut self, addresses: Vec) -> Result<(), ExplorerError> { self.addresses = addresses; let stake_pools = self.explorer.stake_pools(1000)?; - let explorer_stake_pools = stake_pools.data.unwrap().tip.all_stake_pools.edges.unwrap(); + let explorer_stake_pools = stake_pools.data.unwrap().tip.all_stake_pools.edges; self.stake_pools = explorer_stake_pools .iter() - .map(|edge| edge.as_ref().unwrap().node.id.clone()) + .map(|edge| edge.node.id.clone()) .collect::>(); Ok(()) }