1mod http_server;
7
8use linera_base::{
9 crypto::{AccountPublicKey, Signer},
10 data_types::{Amount, BlockHeight, Epoch, Round, Timestamp},
11 identifiers::{AccountOwner, ChainId},
12};
13use linera_execution::{
14 committee::{Committee, ValidatorState},
15 system::Recipient,
16 Message, MessageKind, Operation, ResourceControlPolicy, SystemOperation,
17};
18
19pub use self::http_server::HttpServer;
20use crate::{
21 block::ConfirmedBlock,
22 data_types::{
23 BlockProposal, IncomingBundle, PostedMessage, ProposedBlock, SignatureAggregator, Vote,
24 },
25 types::{CertificateValue, GenericCertificate},
26};
27
28pub fn make_child_block(parent: &ConfirmedBlock) -> ProposedBlock {
30 let parent_header = &parent.block().header;
31 ProposedBlock {
32 epoch: parent_header.epoch,
33 chain_id: parent_header.chain_id,
34 incoming_bundles: vec![],
35 operations: vec![],
36 previous_block_hash: Some(parent.hash()),
37 height: parent_header.height.try_add_one().unwrap(),
38 authenticated_signer: parent_header.authenticated_signer,
39 timestamp: parent_header.timestamp,
40 }
41}
42
43pub fn make_first_block(chain_id: ChainId) -> ProposedBlock {
45 ProposedBlock {
46 epoch: Epoch::ZERO,
47 chain_id,
48 incoming_bundles: vec![],
49 operations: vec![],
50 previous_block_hash: None,
51 height: BlockHeight::ZERO,
52 authenticated_signer: None,
53 timestamp: Timestamp::default(),
54 }
55}
56
57#[allow(async_fn_in_trait)]
59pub trait BlockTestExt: Sized {
60 fn with_authenticated_signer(self, authenticated_signer: Option<AccountOwner>) -> Self;
62
63 fn with_operation(self, operation: impl Into<Operation>) -> Self;
65
66 fn with_transfer(self, owner: AccountOwner, recipient: Recipient, amount: Amount) -> Self;
68
69 fn with_simple_transfer(self, chain_id: ChainId, amount: Amount) -> Self;
71
72 fn with_incoming_bundle(self, incoming_bundle: IncomingBundle) -> Self;
74
75 fn with_timestamp(self, timestamp: impl Into<Timestamp>) -> Self;
77
78 fn with_epoch(self, epoch: impl Into<Epoch>) -> Self;
80
81 fn with_burn(self, amount: Amount) -> Self;
83
84 async fn into_first_proposal<S: Signer + ?Sized>(
87 self,
88 owner: AccountOwner,
89 signer: &S,
90 ) -> Result<BlockProposal, S::Error> {
91 self.into_proposal_with_round(owner, signer, Round::MultiLeader(0))
92 .await
93 }
94
95 async fn into_proposal_with_round<S: Signer + ?Sized>(
97 self,
98 owner: AccountOwner,
99 signer: &S,
100 round: Round,
101 ) -> Result<BlockProposal, S::Error>;
102}
103
104impl BlockTestExt for ProposedBlock {
105 fn with_authenticated_signer(mut self, authenticated_signer: Option<AccountOwner>) -> Self {
106 self.authenticated_signer = authenticated_signer;
107 self
108 }
109
110 fn with_operation(mut self, operation: impl Into<Operation>) -> Self {
111 self.operations.push(operation.into());
112 self
113 }
114
115 fn with_transfer(self, owner: AccountOwner, recipient: Recipient, amount: Amount) -> Self {
116 self.with_operation(SystemOperation::Transfer {
117 owner,
118 recipient,
119 amount,
120 })
121 }
122
123 fn with_simple_transfer(self, chain_id: ChainId, amount: Amount) -> Self {
124 self.with_transfer(AccountOwner::CHAIN, Recipient::chain(chain_id), amount)
125 }
126
127 fn with_burn(self, amount: Amount) -> Self {
128 self.with_operation(SystemOperation::Transfer {
129 owner: AccountOwner::CHAIN,
130 recipient: Recipient::Burn,
131 amount,
132 })
133 }
134
135 fn with_incoming_bundle(mut self, incoming_bundle: IncomingBundle) -> Self {
136 self.incoming_bundles.push(incoming_bundle);
137 self
138 }
139
140 fn with_timestamp(mut self, timestamp: impl Into<Timestamp>) -> Self {
141 self.timestamp = timestamp.into();
142 self
143 }
144
145 fn with_epoch(mut self, epoch: impl Into<Epoch>) -> Self {
146 self.epoch = epoch.into();
147 self
148 }
149
150 async fn into_proposal_with_round<S: Signer + ?Sized>(
151 self,
152 owner: AccountOwner,
153 signer: &S,
154 round: Round,
155 ) -> Result<BlockProposal, S::Error> {
156 BlockProposal::new_initial(owner, round, self, signer).await
157 }
158}
159
160pub trait VoteTestExt<T: CertificateValue>: Sized {
161 fn into_certificate(self) -> GenericCertificate<T>;
163}
164
165impl<T: CertificateValue> VoteTestExt<T> for Vote<T> {
166 fn into_certificate(self) -> GenericCertificate<T> {
167 let state = ValidatorState {
168 network_address: "".to_string(),
169 votes: 100,
170 account_public_key: AccountPublicKey::test_key(1),
171 };
172 let committee = Committee::new(
173 vec![(self.public_key, state)].into_iter().collect(),
174 ResourceControlPolicy::only_fuel(),
175 );
176 SignatureAggregator::new(self.value, self.round, &committee)
177 .append(self.public_key, self.signature)
178 .unwrap()
179 .unwrap()
180 }
181}
182
183pub trait MessageTestExt: Sized {
185 fn to_posted(self, index: u32, kind: MessageKind) -> PostedMessage;
186}
187
188impl<T: Into<Message>> MessageTestExt for T {
189 fn to_posted(self, index: u32, kind: MessageKind) -> PostedMessage {
190 PostedMessage {
191 authenticated_signer: None,
192 grant: Amount::ZERO,
193 refund_grant_to: None,
194 kind,
195 index,
196 message: self.into(),
197 }
198 }
199}