Skip to main content

hotshot_query_service/testing/
mocks.rs

1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the HotShot Query Service library.
3//
4// This program is free software: you can redistribute it and/or modify it under the terms of the GNU
5// General Public License as published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
8// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9// General Public License for more details.
10// You should have received a copy of the GNU General Public License along with this program. If not,
11// see <https://www.gnu.org/licenses/>.
12
13use hotshot::traits::{NodeImplementation, implementations::MemoryNetwork};
14use hotshot_example_types::{
15    block_types::{TestBlockHeader, TestBlockPayload, TestMetadata, TestTransaction},
16    membership::{static_committee::StaticStakeTable, strict_membership::StrictMembership},
17    state_types::{TestInstanceState, TestValidatedState},
18    storage_types::TestStorage,
19};
20use hotshot_types::{
21    data::{QuorumProposal, VidCommitment, VidCommon},
22    signature_key::{BLSPubKey, SchnorrPubKey},
23    traits::node_implementation::NodeType,
24};
25use jf_merkle_tree_compat::{
26    ForgetableMerkleTreeScheme, ForgetableUniversalMerkleTreeScheme,
27    prelude::{MerkleProof, Sha3Digest, Sha3Node},
28    universal_merkle_tree::UniversalMerkleTree,
29};
30use serde::{Deserialize, Serialize};
31use vbs::version::StaticVersion;
32use versions::{Upgrade, version};
33
34use crate::{
35    availability::{
36        QueryableHeader, QueryablePayload, TransactionIndex, VerifiableInclusion,
37        VidCommonQueryData,
38    },
39    explorer::traits::{ExplorerHeader, ExplorerTransaction},
40    merklized_state::MerklizedState,
41};
42
43pub type MockHeader = TestBlockHeader;
44pub type MockPayload = TestBlockPayload;
45pub type MockTransaction = TestTransaction;
46
47pub fn mock_transaction(payload: Vec<u8>) -> MockTransaction {
48    TestTransaction::new(payload)
49}
50
51impl QueryableHeader<MockTypes> for MockHeader {
52    type NamespaceId = i64;
53    type NamespaceIndex = i64;
54
55    fn namespace_id(&self, i: &i64) -> Option<i64> {
56        // Test types only support a single namespace.
57        if *i == 0 { Some(0) } else { None }
58    }
59
60    fn namespace_size(&self, i: &i64, payload_size: usize) -> u64 {
61        // Test types only support a single namespace.
62        if *i == 0 { payload_size as u64 } else { 0 }
63    }
64
65    fn ns_table(&self) -> String {
66        self.metadata.to_string()
67    }
68}
69
70impl ExplorerHeader<MockTypes> for MockHeader {
71    type BalanceAmount = i128;
72    type WalletAddress = [u8; 32];
73    type ProposerId = [u8; 32];
74
75    fn proposer_id(&self) -> Self::ProposerId {
76        [0; 32]
77    }
78
79    fn fee_info_account(&self) -> Self::WalletAddress {
80        [0; 32]
81    }
82
83    fn fee_info_balance(&self) -> Self::BalanceAmount {
84        0
85    }
86
87    fn reward_balance(&self) -> Self::BalanceAmount {
88        0
89    }
90
91    fn namespace_ids(&self) -> Vec<i64> {
92        vec![0]
93    }
94}
95
96impl ExplorerTransaction<MockTypes> for MockTransaction {
97    fn namespace_id(&self) -> i64 {
98        0
99    }
100
101    fn payload_size(&self) -> u64 {
102        self.bytes().len() as u64
103    }
104}
105
106/// A naive inclusion proof for `MockPayload` and `MockTransaction`.
107#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
108pub struct MockInclusionProof(MockPayload);
109
110impl VerifiableInclusion<MockTypes> for MockInclusionProof {
111    fn verify(
112        &self,
113        _metadata: &TestMetadata,
114        tx: &MockTransaction,
115        _payload_commitment: &VidCommitment,
116        _common: &VidCommon,
117    ) -> bool {
118        self.0.transactions.contains(tx)
119    }
120}
121
122impl QueryablePayload<MockTypes> for MockPayload {
123    type Iter<'a> = <Vec<TransactionIndex<MockTypes>> as IntoIterator>::IntoIter;
124    type InclusionProof = MockInclusionProof;
125
126    fn len(&self, _meta: &Self::Metadata) -> usize {
127        self.transactions.len()
128    }
129
130    fn iter(&self, meta: &Self::Metadata) -> Self::Iter<'_> {
131        (0..<TestBlockPayload as QueryablePayload<MockTypes>>::len(self, meta))
132            .map(|i| TransactionIndex {
133                ns_index: 0,
134                position: i as u32,
135            })
136            .collect::<Vec<_>>()
137            .into_iter()
138    }
139
140    fn transaction(
141        &self,
142        _meta: &Self::Metadata,
143        index: &TransactionIndex<MockTypes>,
144    ) -> Option<Self::Transaction> {
145        self.transactions.get(index.position as usize).cloned()
146    }
147
148    fn transaction_proof(
149        &self,
150        _meta: &Self::Metadata,
151        _vid: &VidCommonQueryData<MockTypes>,
152        _index: &TransactionIndex<MockTypes>,
153    ) -> Option<Self::InclusionProof> {
154        Some(MockInclusionProof(self.clone()))
155    }
156}
157
158#[derive(
159    Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
160)]
161pub struct MockTypes;
162
163impl NodeType for MockTypes {
164    type BlockHeader = MockHeader;
165    type BlockPayload = MockPayload;
166    type SignatureKey = BLSPubKey;
167    type Transaction = MockTransaction;
168    type InstanceState = TestInstanceState;
169    type ValidatedState = TestValidatedState;
170    type Membership = StrictMembership<MockTypes, StaticStakeTable<BLSPubKey, SchnorrPubKey>>;
171    type BuilderSignatureKey = BLSPubKey;
172    type StateSignatureKey = SchnorrPubKey;
173}
174
175pub const MOCK_UPGRADE: Upgrade = Upgrade::new(version(0, 1), version(0, 2));
176
177pub type MockBase = StaticVersion<0, 1>;
178
179pub type MockMembership = StrictMembership<MockTypes, StaticStakeTable<BLSPubKey, SchnorrPubKey>>;
180pub type MockQuorumProposal = QuorumProposal<MockTypes>;
181pub type MockNetwork = MemoryNetwork<BLSPubKey>;
182
183pub type MockStorage = TestStorage<MockTypes>;
184
185#[derive(
186    Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
187)]
188pub struct MockNodeImpl;
189
190impl NodeImplementation<MockTypes> for MockNodeImpl {
191    type Network = MockNetwork;
192    type Storage = MockStorage;
193}
194
195pub type MockMerkleTree = UniversalMerkleTree<usize, Sha3Digest, usize, 8, Sha3Node>;
196
197impl MerklizedState<MockTypes, 8> for MockMerkleTree {
198    type Key = usize;
199    type Entry = usize;
200    type T = Sha3Node;
201    type Commit = Self::Commitment;
202    type Digest = Sha3Digest;
203
204    fn state_type() -> &'static str {
205        "test_tree"
206    }
207
208    fn header_state_commitment_field() -> &'static str {
209        "test_merkle_tree_root"
210    }
211
212    fn tree_height() -> usize {
213        12
214    }
215
216    fn insert_path(
217        &mut self,
218        key: Self::Key,
219        proof: &MerkleProof<Self::Entry, Self::Key, Self::T, 8>,
220    ) -> anyhow::Result<()> {
221        match proof.elem() {
222            Some(elem) => self.remember(key, elem, proof)?,
223            None => self.non_membership_remember(key, proof)?,
224        }
225        Ok(())
226    }
227}