Skip to content

Commit b8253e6

Browse files
committed
Add VoteBallotBoxesWrapper
1 parent c788c07 commit b8253e6

File tree

5 files changed

+145
-88
lines changed

5 files changed

+145
-88
lines changed

core/src/box_kind/ballot_box.rs

Lines changed: 104 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::convert::TryInto;
2-
31
use crate::{
42
contracts::ballot::{BallotContract, BallotContractError},
53
oracle_config::{BallotBoxWrapperParameters, CastBallotBoxVoteParameters},
@@ -108,11 +106,7 @@ impl BallotBoxWrapper {
108106
.get_register(NonMandatoryRegisterId::R6.into())
109107
.ok_or(BallotBoxError::NoPoolBoxAddressInR6)?
110108
.try_extract_into::<Digest32>()?;
111-
let pb: Digest32 = base16::decode(pool_box_address_hash)
112-
.unwrap()
113-
.try_into()
114-
.unwrap();
115-
if pb != register_pool_box_address_hash {
109+
if *pool_box_address_hash != register_pool_box_address_hash {
116110
warn!("Pool box address in R6 register differs to config. Could be due to vote.");
117111
}
118112

@@ -153,6 +147,76 @@ pub struct BallotBoxWrapperInputs<'a> {
153147
pub update_nft_token_id: &'a TokenId,
154148
}
155149

150+
/// A Ballot Box with vote parameters guaranteed to be set
151+
#[derive(Clone, Debug)]
152+
pub struct VoteBallotBoxWrapper {
153+
ergo_box: ErgoBox,
154+
vote_parameters: CastBallotBoxVoteParameters,
155+
contract: BallotContract,
156+
}
157+
158+
impl VoteBallotBoxWrapper {
159+
pub fn new(ergo_box: ErgoBox, inputs: BallotBoxWrapperInputs) -> Result<Self, BallotBoxError> {
160+
let ballot_token_id = &ergo_box
161+
.tokens
162+
.as_ref()
163+
.ok_or(BallotBoxError::NoBallotToken)?
164+
.get(0)
165+
.ok_or(BallotBoxError::NoBallotToken)?
166+
.token_id;
167+
if *ballot_token_id != *inputs.ballot_token_id {
168+
return Err(BallotBoxError::UnknownBallotTokenId);
169+
}
170+
171+
if ergo_box
172+
.get_register(NonMandatoryRegisterId::R4.into())
173+
.ok_or(BallotBoxError::NoGroupElementInR4)?
174+
.try_extract_into::<EcPoint>()
175+
.is_err()
176+
{
177+
return Err(BallotBoxError::NoGroupElementInR4);
178+
}
179+
if ergo_box
180+
.get_register(NonMandatoryRegisterId::R5.into())
181+
.ok_or(BallotBoxError::NoUpdateBoxCreationHeightInR5)?
182+
.try_extract_into::<i32>()
183+
.is_err()
184+
{
185+
return Err(BallotBoxError::NoUpdateBoxCreationHeightInR5);
186+
}
187+
188+
let pool_box_address_hash = ergo_box
189+
.get_register(NonMandatoryRegisterId::R6.into())
190+
.ok_or(BallotBoxError::NoPoolBoxAddressInR6)?
191+
.try_extract_into::<Digest32>()?;
192+
193+
let reward_token_id = ergo_box
194+
.get_register(NonMandatoryRegisterId::R7.into())
195+
.ok_or(BallotBoxError::NoRewardTokenIdInR7)?
196+
.try_extract_into::<TokenId>()?;
197+
let reward_token_quantity = ergo_box
198+
.get_register(NonMandatoryRegisterId::R8.into())
199+
.ok_or(BallotBoxError::NoRewardTokenQuantityInR8)?
200+
.try_extract_into::<i64>()? as u32;
201+
202+
let contract = BallotContract::from_ergo_tree(ergo_box.ergo_tree.clone(), inputs.into())?;
203+
let vote_parameters = CastBallotBoxVoteParameters {
204+
pool_box_address_hash,
205+
reward_token_id,
206+
reward_token_quantity,
207+
};
208+
Ok(Self {
209+
ergo_box,
210+
contract,
211+
vote_parameters,
212+
})
213+
}
214+
215+
pub fn vote_parameters(&self) -> &CastBallotBoxVoteParameters {
216+
&self.vote_parameters
217+
}
218+
}
219+
156220
impl BallotBox for BallotBoxWrapper {
157221
fn contract(&self) -> &BallotContract {
158222
&self.contract
@@ -186,6 +250,39 @@ impl BallotBox for BallotBoxWrapper {
186250
}
187251
}
188252

253+
impl BallotBox for VoteBallotBoxWrapper {
254+
fn contract(&self) -> &BallotContract {
255+
&self.contract
256+
}
257+
258+
fn ballot_token(&self) -> Token {
259+
self.ergo_box
260+
.tokens
261+
.as_ref()
262+
.unwrap()
263+
.get(0)
264+
.unwrap()
265+
.clone()
266+
}
267+
268+
fn min_storage_rent(&self) -> u64 {
269+
self.contract.min_storage_rent()
270+
}
271+
272+
fn ballot_token_owner(&self) -> ProveDlog {
273+
self.ergo_box
274+
.get_register(NonMandatoryRegisterId::R4.into())
275+
.unwrap()
276+
.try_extract_into::<EcPoint>()
277+
.unwrap()
278+
.into()
279+
}
280+
281+
fn get_box(&self) -> &ErgoBox {
282+
&self.ergo_box
283+
}
284+
}
285+
189286
#[allow(clippy::too_many_arguments)]
190287
pub fn make_local_ballot_box_candidate(
191288
contract: &BallotContract,

core/src/cli_commands/update_pool.rs

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use ergo_lib::{
1111
ergo_box::{box_value::BoxValue, ErgoBox, NonMandatoryRegisterId},
1212
token::Token,
1313
},
14-
ergotree_ir::mir::constant::Constant,
1514
ergotree_ir::serialization::SigmaSerializable,
1615
wallet::{
1716
box_selector::{BoxSelection, BoxSelector, BoxSelectorError, SimpleBoxSelector},
@@ -24,13 +23,13 @@ use log::{error, info};
2423
use std::convert::TryInto;
2524

2625
use crate::{
27-
box_kind::{make_pool_box_candidate, BallotBox, BallotBoxWrapper, PoolBox, PoolBoxWrapper},
26+
box_kind::{make_pool_box_candidate, BallotBox, PoolBox, PoolBoxWrapper, VoteBallotBoxWrapper},
2827
cli_commands::ergo_explorer_transaction_link,
2928
contracts::pool::PoolContract,
3029
contracts::pool::PoolContractInputs,
3130
node_interface::{current_block_height, get_wallet_status, sign_and_submit_transaction},
32-
oracle_config::{OracleConfig, ORACLE_CONFIG},
33-
oracle_state::{BallotBoxesSource, OraclePool, PoolBoxSource, StageError, UpdateBoxSource},
31+
oracle_config::{CastBallotBoxVoteParameters, OracleConfig, ORACLE_CONFIG},
32+
oracle_state::{OraclePool, PoolBoxSource, StageError, UpdateBoxSource, VoteBallotBoxesSource},
3433
wallet::WalletDataSource,
3534
};
3635
use derive_more::From;
@@ -190,7 +189,7 @@ fn display_update_diff(
190189
#[allow(clippy::too_many_arguments)]
191190
fn build_update_pool_box_tx(
192191
pool_box_source: &dyn PoolBoxSource,
193-
ballot_boxes: &dyn BallotBoxesSource,
192+
ballot_boxes: &dyn VoteBallotBoxesSource,
194193
wallet: &dyn WalletDataSource,
195194
update_box: &dyn UpdateBoxSource,
196195
new_pool_contract: PoolContract,
@@ -201,13 +200,18 @@ fn build_update_pool_box_tx(
201200
let update_box = update_box.get_update_box()?;
202201
let min_votes = update_box.min_votes();
203202
let old_pool_box = pool_box_source.get_pool_box()?;
204-
let pool_box_hash = Constant::from(blake2b256_hash(
203+
let pool_box_hash = blake2b256_hash(
205204
&new_pool_contract
206205
.ergo_tree()
207206
.sigma_serialize_bytes()
208207
.unwrap(),
209-
));
208+
);
210209
let reward_tokens = new_reward_tokens.unwrap_or_else(|| old_pool_box.reward_token());
210+
let vote_parameters = CastBallotBoxVoteParameters {
211+
pool_box_address_hash: pool_box_hash,
212+
reward_token_id: reward_tokens.token_id.clone(),
213+
reward_token_quantity: *reward_tokens.amount.as_u64() as u32, // TODO: Change vote parameters to i64
214+
};
211215
// Find ballot boxes that are voting for the new pool hash
212216
let mut sorted_ballot_boxes = ballot_boxes.get_ballot_boxes()?;
213217
// Sort in descending order of ballot token amounts. If two boxes have the same amount of ballot tokens, also compare box value, in case some boxes were incorrectly created below minStorageRent
@@ -224,28 +228,10 @@ fn build_update_pool_box_tx(
224228
sorted_ballot_boxes.reverse();
225229

226230
let mut votes_cast = 0;
227-
let vote_ballot_boxes: Vec<BallotBoxWrapper> = ballot_boxes
231+
let vote_ballot_boxes: Vec<VoteBallotBoxWrapper> = ballot_boxes
228232
.get_ballot_boxes()?
229233
.into_iter()
230-
.filter(|ballot_box| {
231-
let ballot_box = ballot_box.get_box();
232-
ballot_box
233-
.additional_registers
234-
.get(NonMandatoryRegisterId::R5)
235-
== Some(&update_box.get_box().creation_info().0.into())
236-
&& ballot_box
237-
.additional_registers
238-
.get(NonMandatoryRegisterId::R6)
239-
== Some(&pool_box_hash)
240-
&& ballot_box
241-
.additional_registers
242-
.get(NonMandatoryRegisterId::R7)
243-
== Some(&reward_tokens.token_id.clone().into())
244-
&& ballot_box
245-
.additional_registers
246-
.get(NonMandatoryRegisterId::R8)
247-
== Some(&(*reward_tokens.amount.as_u64() as i64).into())
248-
})
234+
.filter(|ballot_box| *ballot_box.vote_parameters() == vote_parameters)
249235
.scan(&mut votes_cast, |votes_cast, ballot_box| {
250236
**votes_cast += *ballot_box.ballot_token().amount.as_u64();
251237
Some(ballot_box)
@@ -378,8 +364,8 @@ mod tests {
378364

379365
use crate::{
380366
box_kind::{
381-
make_local_ballot_box_candidate, make_pool_box_candidate, BallotBoxWrapper,
382-
PoolBoxWrapper, PoolBoxWrapperInputs, UpdateBoxWrapper, UpdateBoxWrapperInputs,
367+
make_local_ballot_box_candidate, make_pool_box_candidate, PoolBoxWrapper,
368+
PoolBoxWrapperInputs, UpdateBoxWrapper, UpdateBoxWrapperInputs, VoteBallotBoxWrapper,
383369
},
384370
contracts::{
385371
ballot::{BallotContract, BallotContractInputs},
@@ -496,11 +482,7 @@ mod tests {
496482
let secret = DlogProverInput::random();
497483
let ballot_box_parameters = BallotBoxWrapperParameters {
498484
contract_parameters: ballot_contract_parameters.clone(),
499-
vote_parameters: Some(crate::oracle_config::CastBallotBoxVoteParameters {
500-
pool_box_address_hash: base16::encode_lower(&pool_box_hash),
501-
reward_token_id: new_reward_tokens.token_id.clone(),
502-
reward_token_quantity: *new_reward_tokens.amount.as_u64() as u32,
503-
}),
485+
vote_parameters: None,
504486
ballot_token_owner_address: AddressEncoder::new(
505487
ballot_contract_parameters.p2s.network(),
506488
)
@@ -526,7 +508,7 @@ mod tests {
526508
ErgoBox::from_box_candidate(&ballot_box_candidate, force_any_val::<TxId>(), 0)
527509
.unwrap();
528510
ballot_boxes.push(
529-
BallotBoxWrapper::new(
511+
VoteBallotBoxWrapper::new(
530512
ballot_box,
531513
crate::box_kind::BallotBoxWrapperInputs {
532514
parameters: &ballot_box_parameters,
@@ -594,7 +576,6 @@ mod tests {
594576
change_address,
595577
)
596578
.unwrap();
597-
println!("{}", serde_json::to_string(&update_tx.spending_tx).unwrap());
598579

599580
wallet.sign_transaction(update_tx, &ctx, None).unwrap();
600581
}

core/src/oracle_config.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use crate::{
88
datapoint_source::{DataPointSource, ExternalScript, PredefinedDataPointSource},
99
};
1010
use anyhow::anyhow;
11-
use ergo_lib::ergotree_ir::chain::{address::NetworkPrefix, token::TokenId};
11+
use ergo_lib::{
12+
ergo_chain_types::Digest32,
13+
ergotree_ir::chain::{address::NetworkPrefix, token::TokenId},
14+
};
1215
use log::LevelFilter;
1316
use serde::{Deserialize, Serialize};
1417

@@ -48,9 +51,9 @@ pub struct BallotBoxWrapperParameters {
4851
pub ballot_token_owner_address: String,
4952
}
5053

51-
#[derive(Debug, Clone, Deserialize, Serialize)]
54+
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
5255
pub struct CastBallotBoxVoteParameters {
53-
pub pool_box_address_hash: String,
56+
pub pool_box_address_hash: Digest32,
5457
pub reward_token_id: TokenId,
5558
pub reward_token_quantity: u32,
5659
}

0 commit comments

Comments
 (0)