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::{implementations::MemoryNetwork, NodeImplementation};
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, ViewNumber},
22    signature_key::{BLSPubKey, SchnorrPubKey},
23    traits::node_implementation::{NodeType, Versions},
24};
25use jf_merkle_tree_compat::{
26    prelude::{MerkleProof, Sha3Digest, Sha3Node},
27    universal_merkle_tree::UniversalMerkleTree,
28    ForgetableMerkleTreeScheme, ForgetableUniversalMerkleTreeScheme,
29};
30use serde::{Deserialize, Serialize};
31use vbs::version::StaticVersion;
32
33use crate::{
34    availability::{
35        QueryableHeader, QueryablePayload, TransactionIndex, VerifiableInclusion,
36        VidCommonQueryData,
37    },
38    explorer::traits::{ExplorerHeader, ExplorerTransaction},
39    merklized_state::MerklizedState,
40    types::HeightIndexed,
41    VidCommon,
42};
43
44pub type MockHeader = TestBlockHeader;
45pub type MockPayload = TestBlockPayload;
46pub type MockTransaction = TestTransaction;
47
48pub fn mock_transaction(payload: Vec<u8>) -> MockTransaction {
49    TestTransaction::new(payload)
50}
51
52impl QueryableHeader<MockTypes> for MockHeader {
53    type NamespaceId = i64;
54    type NamespaceIndex = i64;
55
56    fn namespace_id(&self, i: &i64) -> Option<i64> {
57        // Test types only support a single namespace.
58        if *i == 0 {
59            Some(0)
60        } else {
61            None
62        }
63    }
64
65    fn namespace_size(&self, i: &i64, payload_size: usize) -> u64 {
66        // Test types only support a single namespace.
67        if *i == 0 {
68            payload_size as u64
69        } else {
70            0
71        }
72    }
73}
74
75impl ExplorerHeader<MockTypes> for MockHeader {
76    type BalanceAmount = i128;
77    type WalletAddress = [u8; 32];
78    type ProposerId = [u8; 32];
79
80    fn proposer_id(&self) -> Self::ProposerId {
81        [0; 32]
82    }
83
84    fn fee_info_account(&self) -> Self::WalletAddress {
85        [0; 32]
86    }
87
88    fn fee_info_balance(&self) -> Self::BalanceAmount {
89        0
90    }
91
92    fn reward_balance(&self) -> Self::BalanceAmount {
93        0
94    }
95
96    fn namespace_ids(&self) -> Vec<i64> {
97        vec![0]
98    }
99}
100
101impl ExplorerTransaction<MockTypes> for MockTransaction {
102    fn namespace_id(&self) -> i64 {
103        0
104    }
105
106    fn payload_size(&self) -> u64 {
107        self.bytes().len() as u64
108    }
109}
110
111impl HeightIndexed for MockHeader {
112    fn height(&self) -> u64 {
113        self.block_number
114    }
115}
116
117/// A naive inclusion proof for `MockPayload` and `MockTransaction`.
118#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
119pub struct MockInclusionProof(MockPayload);
120
121impl VerifiableInclusion<MockTypes> for MockInclusionProof {
122    fn verify(
123        &self,
124        _metadata: &TestMetadata,
125        tx: &MockTransaction,
126        _payload_commitment: &VidCommitment,
127        _common: &VidCommon,
128    ) -> bool {
129        self.0.transactions.contains(tx)
130    }
131}
132
133impl QueryablePayload<MockTypes> for MockPayload {
134    type Iter<'a> = <Vec<TransactionIndex<MockTypes>> as IntoIterator>::IntoIter;
135    type InclusionProof = MockInclusionProof;
136
137    fn len(&self, _meta: &Self::Metadata) -> usize {
138        self.transactions.len()
139    }
140
141    fn iter(&self, meta: &Self::Metadata) -> Self::Iter<'_> {
142        (0..<TestBlockPayload as QueryablePayload<MockTypes>>::len(self, meta))
143            .map(|i| TransactionIndex {
144                ns_index: 0,
145                position: i as u32,
146            })
147            .collect::<Vec<_>>()
148            .into_iter()
149    }
150
151    fn transaction(
152        &self,
153        _meta: &Self::Metadata,
154        index: &TransactionIndex<MockTypes>,
155    ) -> Option<Self::Transaction> {
156        self.transactions.get(index.position as usize).cloned()
157    }
158
159    fn transaction_proof(
160        &self,
161        _meta: &Self::Metadata,
162        _vid: &VidCommonQueryData<MockTypes>,
163        _index: &TransactionIndex<MockTypes>,
164    ) -> Option<Self::InclusionProof> {
165        Some(MockInclusionProof(self.clone()))
166    }
167}
168
169#[derive(
170    Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
171)]
172pub struct MockTypes;
173
174impl NodeType for MockTypes {
175    type View = ViewNumber;
176    type Epoch = ViewNumber;
177    type BlockHeader = MockHeader;
178    type BlockPayload = MockPayload;
179    type SignatureKey = BLSPubKey;
180    type Transaction = MockTransaction;
181    type InstanceState = TestInstanceState;
182    type ValidatedState = TestValidatedState;
183    type Membership = StrictMembership<MockTypes, StaticStakeTable<BLSPubKey, SchnorrPubKey>>;
184    type BuilderSignatureKey = BLSPubKey;
185    type StateSignatureKey = SchnorrPubKey;
186}
187
188#[derive(Clone, Debug, Copy)]
189pub struct MockVersions {}
190
191impl Versions for MockVersions {
192    type Base = StaticVersion<0, 1>;
193    type Upgrade = StaticVersion<0, 2>;
194    const UPGRADE_HASH: [u8; 32] = [
195        1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
196        0, 0,
197    ];
198    type Epochs = StaticVersion<0, 4>;
199    type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
200}
201
202/// A type alias for the mock base version
203pub type MockBase = <MockVersions as Versions>::Base;
204
205pub type MockMembership = StrictMembership<MockTypes, StaticStakeTable<BLSPubKey, SchnorrPubKey>>;
206pub type MockQuorumProposal = QuorumProposal<MockTypes>;
207pub type MockNetwork = MemoryNetwork<BLSPubKey>;
208
209pub type MockStorage = TestStorage<MockTypes>;
210
211#[derive(
212    Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
213)]
214pub struct MockNodeImpl;
215
216impl NodeImplementation<MockTypes> for MockNodeImpl {
217    type Network = MockNetwork;
218    type Storage = MockStorage;
219}
220
221pub type MockMerkleTree = UniversalMerkleTree<usize, Sha3Digest, usize, 8, Sha3Node>;
222
223impl MerklizedState<MockTypes, 8> for MockMerkleTree {
224    type Key = usize;
225    type Entry = usize;
226    type T = Sha3Node;
227    type Commit = Self::Commitment;
228    type Digest = Sha3Digest;
229
230    fn state_type() -> &'static str {
231        "test_tree"
232    }
233
234    fn header_state_commitment_field() -> &'static str {
235        "test_merkle_tree_root"
236    }
237
238    fn tree_height() -> usize {
239        12
240    }
241
242    fn insert_path(
243        &mut self,
244        key: Self::Key,
245        proof: &MerkleProof<Self::Entry, Self::Key, Self::T, 8>,
246    ) -> anyhow::Result<()> {
247        match proof.elem() {
248            Some(elem) => self.remember(key, elem, proof)?,
249            None => self.non_membership_remember(key, proof)?,
250        }
251        Ok(())
252    }
253}