mod.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. use smol::Executor;
  2. use async_std::sync::Arc;
  3. use halo2_proofs::arithmetic::Field;
  4. use log::{debug, error, info};
  5. use std::fmt;
  6. use rand::rngs::OsRng;
  7. use std::{thread, time::Duration};
  8. use crate::zk::circuit::{BurnContract, LeadContract, MintContract};
  9. use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
  10. pub mod types;
  11. pub mod consts;
  12. pub mod utils;
  13. use crate::{
  14. blockchain::{Blockchain},
  15. consensus::{
  16. clock::{Clock, Ticks},
  17. Block, BlockInfo, Header, Metadata,
  18. LeadProof,
  19. },
  20. crypto::{
  21. address::Address,
  22. coin::OwnCoin,
  23. constants::MERKLE_DEPTH,
  24. keypair::{PublicKey, SecretKey},
  25. util::poseidon_hash,
  26. leadcoin::LeadCoin,
  27. merkle_node::MerkleNode,
  28. note::{EncryptedNote, Note},
  29. nullifier::Nullifier,
  30. proof::{Proof, ProvingKey, VerifyingKey},
  31. schnorr::{SchnorrSecret},
  32. },
  33. net::{MessageSubscription, P2p, Settings, SettingsPtr},
  34. node::state::{state_transition, ProgramState, StateUpdate},
  35. tx::{
  36. builder::{
  37. TransactionBuilder, TransactionBuilderClearInputInfo, TransactionBuilderOutputInfo,
  38. },
  39. Transaction,
  40. },
  41. util::{path::expand_path, time::Timestamp},
  42. stakeholder::types::{Float10},
  43. stakeholder::consts::{RADIX_BITS, LOG_T, TREE_LEN, P},
  44. stakeholder::utils::{fbig2base},
  45. Result,
  46. };
  47. use url::Url;
  48. use pasta_curves::pallas;
  49. use group::ff::PrimeField;
  50. pub mod epoch;
  51. pub use epoch::{Epoch, EpochConsensus};
  52. #[derive(Debug)]
  53. pub struct SlotWorkspace {
  54. pub st: blake3::Hash, // hash of the previous block
  55. pub e: u64, // epoch index
  56. pub sl: u64, // relative slot index
  57. pub txs: Vec<Transaction>, // unpublished block transactions
  58. pub root: MerkleNode,
  59. /// merkle root of txs
  60. pub m: Metadata,
  61. pub is_leader: bool,
  62. pub proof: Proof,
  63. pub block: BlockInfo,
  64. }
  65. impl Default for SlotWorkspace {
  66. fn default() -> Self {
  67. Self {
  68. st: blake3::hash(b""),
  69. e: 0,
  70. sl: 0,
  71. txs: vec![],
  72. root: MerkleNode(pallas::Base::zero()),
  73. is_leader: false,
  74. m: Metadata::default(),
  75. proof: Proof::default(),
  76. block: BlockInfo::default(),
  77. }
  78. }
  79. }
  80. impl SlotWorkspace {
  81. pub fn new_block(&self) -> (BlockInfo, blake3::Hash) {
  82. let header = Header::new(self.st, self.e, self.sl, Timestamp::current_time(), self.root);
  83. let block = BlockInfo::new(header, self.txs.clone(), self.m.clone());
  84. let hash = block.blockhash();
  85. (block, hash)
  86. }
  87. pub fn add_tx(&mut self, tx: Transaction) {
  88. self.txs.push(tx);
  89. }
  90. pub fn set_root(&mut self, root: MerkleNode) {
  91. self.root = root;
  92. }
  93. pub fn set_metadata(&mut self, meta: Metadata) {
  94. self.m = meta;
  95. }
  96. pub fn set_sl(&mut self, sl: u64) {
  97. self.sl = sl;
  98. }
  99. pub fn set_st(&mut self, st: blake3::Hash) {
  100. self.st = st;
  101. }
  102. pub fn set_e(&mut self, e: u64) {
  103. self.e = e;
  104. }
  105. pub fn set_proof(&mut self, proof: Proof) {
  106. self.proof = proof;
  107. }
  108. pub fn set_leader(&mut self, alead: bool) {
  109. self.is_leader = alead;
  110. }
  111. }
  112. struct StakeholderState {
  113. /// The entire Merkle tree state
  114. tree: BridgeTree<MerkleNode, MERKLE_DEPTH>,
  115. /// List of all previous and the current Merkle roots.
  116. /// This is the hashed value of all the children.
  117. merkle_roots: Vec<MerkleNode>,
  118. /// Nullifiers prevent double spending
  119. nullifiers: Vec<Nullifier>,
  120. /// All received coins
  121. // NOTE: We need maybe a flag to keep track of which ones are
  122. // spent. Maybe the spend field links to a tx hash:input index.
  123. // We should also keep track of the tx hash:output index where
  124. // this coin was received.
  125. own_coins: Vec<OwnCoin>,
  126. /// Verifying key for the mint zk circuit.
  127. mint_vk: VerifyingKey,
  128. /// Verifying key for the burn zk circuit.
  129. burn_vk: VerifyingKey,
  130. /// Public key of the cashier
  131. cashier_signature_public: PublicKey,
  132. /// Public key of the faucet
  133. faucet_signature_public: PublicKey,
  134. /// List of all our secret keys
  135. secrets: Vec<SecretKey>,
  136. }
  137. impl ProgramState for StakeholderState {
  138. fn is_valid_cashier_public_key(&self, public: &PublicKey) -> bool {
  139. public == &self.cashier_signature_public
  140. }
  141. fn is_valid_faucet_public_key(&self, public: &PublicKey) -> bool {
  142. public == &self.faucet_signature_public
  143. }
  144. fn is_valid_merkle(&self, merkle_root: &MerkleNode) -> bool {
  145. self.merkle_roots.iter().any(|m| m == merkle_root)
  146. }
  147. fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
  148. self.nullifiers.iter().any(|n| n == nullifier)
  149. }
  150. fn mint_vk(&self) -> &VerifyingKey {
  151. &self.mint_vk
  152. }
  153. fn burn_vk(&self) -> &VerifyingKey {
  154. &self.burn_vk
  155. }
  156. }
  157. impl StakeholderState {
  158. fn apply(&mut self, mut update: StateUpdate) {
  159. // Extend our list of nullifiers with the ones from the update
  160. self.nullifiers.append(&mut update.nullifiers);
  161. // Update merkle tree and witnesses
  162. for (coin, enc_note) in update.coins.into_iter().zip(update.enc_notes.into_iter()) {
  163. // Add the new coins to the Merkle tree
  164. let node = MerkleNode(coin.0);
  165. self.tree.append(&node);
  166. // Keep track of all Merkle roots that have existed
  167. self.merkle_roots.push(self.tree.root(0).unwrap());
  168. // If it's our own coin, witness it and append to the vector.
  169. if let Some((note, secret)) = self.try_decrypt_note(enc_note) {
  170. let leaf_position = self.tree.witness().unwrap();
  171. let nullifier = poseidon_hash::<2>([secret.inner(), note.serial]);
  172. let own_coin = OwnCoin {
  173. coin: coin,
  174. note: note,
  175. secret: secret,
  176. nullifier: Nullifier::from(nullifier),
  177. leaf_position: leaf_position
  178. };
  179. self.own_coins.push(own_coin);
  180. }
  181. }
  182. }
  183. fn try_decrypt_note(&self, ciphertext: EncryptedNote) -> Option<(Note, SecretKey)> {
  184. // Loop through all our secret keys...
  185. for secret in &self.secrets {
  186. // .. attempt to decrypt the note ...
  187. if let Ok(note) = ciphertext.decrypt(secret) {
  188. // ... and return the decrypted note for this coin.
  189. return Some((note, *secret))
  190. }
  191. }
  192. // We weren't able to decrypt the note with any of our keys.
  193. None
  194. }
  195. }
  196. pub struct Stakeholder {
  197. pub blockchain: Blockchain, // stakeholder view of the blockchain
  198. pub net: Arc<P2p>,
  199. pub clock: Clock,
  200. pub ownedcoins: Vec<OwnCoin>, // owned stakes
  201. pub epoch: Epoch, // current epoch
  202. pub epoch_consensus: EpochConsensus, // configuration for the epoch
  203. pub lead_pk: ProvingKey,
  204. pub mint_pk: ProvingKey,
  205. pub burn_pk: ProvingKey,
  206. pub lead_vk: VerifyingKey,
  207. pub mint_vk: VerifyingKey,
  208. pub burn_vk: VerifyingKey,
  209. pub playing: bool,
  210. pub workspace: SlotWorkspace,
  211. pub id: i64,
  212. pub cashier_signature_public: PublicKey,
  213. pub faucet_signature_public: PublicKey,
  214. pub cashier_signature_secret: SecretKey,
  215. pub faucet_signature_secret: SecretKey,
  216. //pub subscription: Subscription<Result<ChannelPtr>>,
  217. //pub chanptr : ChannelPtr,
  218. //pub msgsub : MessageSubscription::<BlockInfo>,
  219. }
  220. impl Stakeholder {
  221. pub async fn new(
  222. consensus: EpochConsensus,
  223. settings: Settings,
  224. rel_path: &str,
  225. id: i64,
  226. k: Option<u32>,
  227. ) -> Result<Self> {
  228. let path = expand_path(rel_path).unwrap();
  229. let db = sled::open(&path)?;
  230. let ts = Timestamp::current_time();
  231. let genesis_hash = blake3::hash(b"");
  232. let bc = Blockchain::new(&db, ts, genesis_hash).unwrap();
  233. let eta = pallas::Base::one();
  234. let epoch = Epoch::new(consensus, eta);
  235. let lead_pk = ProvingKey::build(k.unwrap(), &LeadContract::default());
  236. let mint_pk = ProvingKey::build(k.unwrap(), &MintContract::default());
  237. let burn_pk = ProvingKey::build(k.unwrap(), &BurnContract::default());
  238. let lead_vk = VerifyingKey::build(k.unwrap(), &LeadContract::default());
  239. let mint_vk = VerifyingKey::build(k.unwrap(), &MintContract::default());
  240. let burn_vk = VerifyingKey::build(k.unwrap(), &BurnContract::default());
  241. let p2p = P2p::new(settings.clone()).await;
  242. let workspace = SlotWorkspace::default();
  243. let clock = Clock::new(
  244. Some(consensus.get_epoch_len()),
  245. Some(consensus.get_slot_len()),
  246. Some(consensus.get_tick_len()),
  247. settings.peers,
  248. );
  249. let cashier_signature_secret = SecretKey::random(&mut OsRng);
  250. let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret);
  251. let faucet_signature_secret = SecretKey::random(&mut OsRng);
  252. let faucet_signature_public = PublicKey::from_secret(faucet_signature_secret);
  253. debug!(target: LOG_T, "stakeholder constructed");
  254. Ok(Self {
  255. blockchain: bc,
  256. net: p2p,
  257. clock,
  258. ownedcoins: vec![], //TODO should be read from wallet db.
  259. epoch,
  260. epoch_consensus: consensus,
  261. lead_pk,
  262. mint_pk,
  263. burn_pk,
  264. lead_vk,
  265. mint_vk,
  266. burn_vk,
  267. playing: true,
  268. workspace,
  269. id,
  270. cashier_signature_public,
  271. faucet_signature_public,
  272. cashier_signature_secret,
  273. faucet_signature_secret,
  274. })
  275. }
  276. /*
  277. /// wrapper on schnorr public verify
  278. pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
  279. info!(target: LOG_T, "verify()");
  280. self.keypair.public.verify(message, signature)
  281. }
  282. */
  283. pub fn get_leadprovkingkey(&self) -> ProvingKey {
  284. info!(target: LOG_T, "get_leadprovkingkey()");
  285. self.lead_pk.clone()
  286. }
  287. pub fn get_mintprovkingkey(&self) -> ProvingKey {
  288. info!(target: LOG_T, "get_mintprovkingkey()");
  289. self.mint_pk.clone()
  290. }
  291. pub fn get_burnprovkingkey(&self) -> ProvingKey {
  292. info!(target: LOG_T, "get_burnprovkingkey()");
  293. self.burn_pk.clone()
  294. }
  295. pub fn get_leadverifyingkey(&self) -> VerifyingKey {
  296. info!(target: LOG_T, "get_leadverifyingkey()");
  297. self.lead_vk.clone()
  298. }
  299. pub fn get_mintverifyingkey(&self) -> VerifyingKey {
  300. info!(target: LOG_T, "get_mintverifyingkey()");
  301. self.mint_vk.clone()
  302. }
  303. pub fn get_burnverifyingkey(&self) -> VerifyingKey {
  304. info!(target: LOG_T, "get_burnverifyingkey()");
  305. self.burn_vk.clone()
  306. }
  307. /// get list stakeholder peers on the p2p network for synchronization
  308. pub fn get_peers(&self) -> Vec<Url> {
  309. info!(target: LOG_T, "get_peers()");
  310. let settings: SettingsPtr = self.net.settings();
  311. settings.peers.clone()
  312. }
  313. async fn init_network(&self) -> Result<()> {
  314. info!(target: LOG_T, "init_network()");
  315. let exec = Arc::new(Executor::new());
  316. self.net.clone().start(exec.clone()).await?;
  317. exec.spawn(self.net.clone().run(exec.clone())).detach();
  318. info!(target: LOG_T, "net initialized");
  319. Ok(())
  320. }
  321. pub fn get_net(&self) -> Arc<P2p> {
  322. info!(target: LOG_T, "get_net()");
  323. //TODO use P2p ptr not to overwrite wrappers
  324. self.net.clone()
  325. }
  326. /// add new blockinfo to the blockchain
  327. pub fn add_block(&self, block: BlockInfo) {
  328. info!(target: LOG_T, "add_block()");
  329. let blocks = [block];
  330. let _len = self.blockchain.add(&blocks);
  331. }
  332. pub fn add_tx(&mut self, tx: Transaction) {
  333. info!(target: LOG_T, "add_tx()");
  334. self.workspace.add_tx(tx);
  335. }
  336. /// extract leader selection lottery randomness \eta
  337. /// it's the hash of the previous lead proof
  338. /// converted to pallas base
  339. pub fn get_eta(&self) -> pallas::Base {
  340. info!(target: LOG_T, "get_eta()");
  341. let proof_tx_hash = self.blockchain.get_last_proof_hash().unwrap();
  342. let mut bytes: [u8; 32] = *proof_tx_hash.as_bytes();
  343. // read first 254 bits
  344. bytes[30] = 0;
  345. bytes[31] = 0;
  346. pallas::Base::from_repr(bytes).unwrap()
  347. }
  348. pub fn valid_block(&self, _blk: BlockInfo) -> bool {
  349. info!(target: LOG_T, "valid_block()");
  350. //TODO implement
  351. true
  352. }
  353. /// listen to the network,
  354. /// for new transactions.
  355. pub fn sync_tx(&self) {
  356. //TODO
  357. }
  358. /// listen to the network channels,
  359. /// receive new messages, or blocks,
  360. /// validate the block proof, and the transactions,
  361. /// if so add the proof to metadata if stakeholder isn't the lead.
  362. pub async fn sync_block(&self) {
  363. info!(target: LOG_T, "syncing blocks");
  364. for chanptr in self.net.channels().lock().await.values() {
  365. let message_subsytem = chanptr.get_message_subsystem();
  366. message_subsytem.add_dispatch::<BlockInfo>().await;
  367. //TODO start channel if isn't started yet
  368. //let info = chanptr.get_info();
  369. let msg_sub: MessageSubscription<BlockInfo> =
  370. chanptr.subscribe_msg::<BlockInfo>().await.expect("missing blockinfo");
  371. let res = msg_sub.receive().await.unwrap();
  372. let blk: BlockInfo = (*res).to_owned();
  373. //TODO validate the block proof, and transactions.
  374. if self.valid_block(blk.clone()) {
  375. //TODO if valid only.
  376. let _len = self.blockchain.add(&[blk]);
  377. } else {
  378. error!(target: LOG_T, "received block is invalid!");
  379. }
  380. }
  381. }
  382. pub async fn background(&mut self, hardlimit: Option<u8>) {
  383. info!(target: LOG_T, "background");
  384. let _ = self.init_network().await;
  385. let _ = self.clock.sync().await;
  386. let mut c: u8 = 0;
  387. let lim: u8 = hardlimit.unwrap_or(0);
  388. while self.playing {
  389. if c > lim && lim > 0 {
  390. break
  391. }
  392. // clock ticks slot begins
  393. // initialize the epoch if it's the time
  394. // check for leadership
  395. match self.clock.ticks().await {
  396. Ticks::GENESIS { e, sl } => {
  397. //TODO (res) any initialization happening here?
  398. self.new_epoch(e, sl);
  399. self.new_slot(e, sl);
  400. }
  401. Ticks::NEWEPOCH { e, sl } => {
  402. self.new_epoch(e, sl);
  403. self.new_slot(e, sl);
  404. }
  405. Ticks::NEWSLOT { e, sl } => self.new_slot(e, sl),
  406. Ticks::TOCKS => {
  407. info!(target: LOG_T, "tocks");
  408. // slot is about to end.
  409. // sync, and validate.
  410. // no more transactions to be received/send to the end of slot.
  411. if self.workspace.is_leader {
  412. info!(target: LOG_T, "[leadership won]");
  413. //craete block
  414. let (block_info, _block_hash) = self.workspace.new_block();
  415. //add the block to the blockchain
  416. self.add_block(block_info.clone());
  417. let block: Block = Block::from(block_info.clone());
  418. // publish the block
  419. //TODO (fix) before publishing the workspace tx root need to be set.
  420. let _ret = self.net.broadcast(block).await;
  421. } else {
  422. //
  423. self.sync_block().await;
  424. }
  425. }
  426. Ticks::IDLE => continue,
  427. Ticks::OUTOFSYNC => {
  428. error!(target: LOG_T, "clock/blockchain are out of sync");
  429. // clock, and blockchain are out of sync
  430. let _ = self.clock.sync().await;
  431. self.sync_block().await;
  432. }
  433. }
  434. thread::sleep(Duration::from_millis(1000));
  435. c += 1;
  436. }
  437. }
  438. fn get_f(&self) -> Float10 {
  439. //TODO (res) should be function of the average time to end of slot
  440. // in the previous epoch.
  441. let one : Float10 = Float10::from_str_native("1")
  442. .unwrap()
  443. .with_precision(RADIX_BITS)
  444. .value();
  445. let two : Float10 = Float10::from_str_native("2")
  446. .unwrap()
  447. .with_precision(RADIX_BITS)
  448. .value();
  449. one/two
  450. }
  451. /// on the onset of the epoch, layout the new the competing coins
  452. /// assuming static stake during the epoch, enforced by the commitment to competing coins
  453. /// in the epoch's gen2esis data.
  454. fn new_epoch(&mut self, e: u64, sl: u64) {
  455. info!(target: LOG_T, "[new epoch] {}", self);
  456. let eta = self.get_eta();
  457. let mut epoch = Epoch::new(self.epoch_consensus, eta);
  458. // total stake
  459. // let rel_sl = self.workspace.sl;
  460. // let epochs = self.workspace.e;
  461. // let epoch_len = self.epoch_consensus.get_epoch_len();
  462. // let abs_sl = rel_sl + epochs * epoch_len;
  463. //
  464. let f = self.get_f();
  465. let total_stake = self.epoch.consensus.total_stake(e, sl);
  466. let one : Float10 = Float10::from_str_native("1")
  467. .unwrap()
  468. .with_precision(RADIX_BITS)
  469. .value();
  470. let two : Float10 = Float10::from_str_native("2")
  471. .unwrap()
  472. .with_precision(RADIX_BITS)
  473. .value();
  474. //TODO should set f precision here
  475. /*
  476. let f : Float10 = Float10::try_from(f_val)
  477. .unwrap()
  478. .with_precision(RADIX_BITS)
  479. .value();
  480. */
  481. let field_p = Float10::from_str_native(P)
  482. .unwrap()
  483. .with_precision(RADIX_BITS)
  484. .value();
  485. let total_sigma = Float10::try_from(total_stake)
  486. .unwrap()
  487. .with_precision(RADIX_BITS)
  488. .value();
  489. let x = one - f;
  490. info!("x: {}", x);
  491. // also ln small x should work normally.
  492. let c = x.ln();
  493. info!("c: {}", c);
  494. let sigma1_fbig = c.clone()/total_sigma.clone() * field_p.clone();
  495. info!("sigma1: {}", sigma1_fbig);
  496. //TODO in sigma calculation get rad if exp is neg
  497. let sigma1 : pallas::Base = fbig2base(sigma1_fbig);
  498. info!("sigma1 base: {:?}", sigma1);
  499. let sigma2_fbig = c.clone()/total_sigma.clone() * c.clone()/total_sigma.clone() * field_p.clone()/two.clone();
  500. info!("sigma2: {}", sigma2_fbig);
  501. let sigma2 : pallas::Base = fbig2base(sigma2_fbig);
  502. info!("sigma2 base: {:?}", sigma2);
  503. epoch.create_coins(sigma1, sigma2, self.ownedcoins.clone()); // set epoch interal fields working space with competing coins
  504. self.epoch = epoch.clone();
  505. }
  506. /// at the begining of the slot
  507. /// stakeholder need to play the lottery for the slot.
  508. /// FIXME if the stakeholder is not winning, staker can try different coins before,
  509. /// commiting it's coins, to maximize success, thus,
  510. /// the lottery proof need to be conditioned on the slot itself, and previous proof.
  511. /// this will encourage each potential leader to play with honesty.
  512. /// TODO this is fixed by commiting to the stakers at epoch genesis slot
  513. /// * `e` - epoch index
  514. /// * `sl` - slot relative index
  515. fn new_slot(&mut self, e: u64, sl: u64) {
  516. info!(target: LOG_T, "[new slot] {}, e:{}, rel sl:{}", self, e, sl);
  517. let st: blake3::Hash = if e > 0 || (e == 0 && sl > 0) {
  518. self.workspace.block.blockhash()
  519. } else {
  520. blake3::hash(b"")
  521. };
  522. // set workspace
  523. self.workspace.set_sl(sl);
  524. self.workspace.set_e(e);
  525. self.workspace.set_st(st);
  526. let mut winning_coin_idx: usize = 0;
  527. let won = self.epoch.is_leader(sl, &mut winning_coin_idx);
  528. let proof = if won {
  529. self.epoch.get_proof(sl, winning_coin_idx, &self.get_leadprovkingkey())
  530. } else {
  531. Proof::new(vec![])
  532. };
  533. self.workspace.set_leader(won);
  534. self.workspace.set_proof(proof.clone());
  535. let coin = self.epoch.get_coin(sl as usize, winning_coin_idx as usize);
  536. let keypair = coin.keypair.unwrap();
  537. let addr = Address::from(keypair.public);
  538. let sign = keypair.secret.sign(proof.as_ref());
  539. let meta =
  540. Metadata::new(sign, addr, self.get_eta().to_repr(), LeadProof::from(proof), vec![]);
  541. self.workspace.set_metadata(meta);
  542. //
  543. if won {
  544. //TODO (res) verify the coin is finalized
  545. // could be finalized in later slot accord to the finalization policy that is WIP.
  546. let owned_coin =
  547. self.finalize_coin(&self.epoch.get_coin(sl as usize, winning_coin_idx as usize));
  548. self.ownedcoins.push(owned_coin);
  549. }
  550. }
  551. //TODO (res) validate the owncoin is the same winning leadcoin
  552. pub fn finalize_coin(&self, coin: &LeadCoin) -> OwnCoin {
  553. info!(target: LOG_T, "finalize coin");
  554. let keypair = coin.keypair.unwrap();
  555. let mut state = StakeholderState {
  556. tree: BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(TREE_LEN),
  557. merkle_roots: vec![],
  558. nullifiers: vec![],
  559. own_coins: vec![],
  560. mint_vk: self.mint_vk.clone(),
  561. burn_vk: self.burn_vk.clone(),
  562. cashier_signature_public: self.cashier_signature_public,
  563. faucet_signature_public: self.faucet_signature_public,
  564. secrets: vec![keypair.secret],
  565. };
  566. let token_id = pallas::Base::random(&mut OsRng);
  567. let builder = TransactionBuilder {
  568. clear_inputs: vec![TransactionBuilderClearInputInfo {
  569. value: coin.value.unwrap(),
  570. token_id,
  571. signature_secret: self.cashier_signature_secret,
  572. }],
  573. inputs: vec![],
  574. outputs: vec![TransactionBuilderOutputInfo {
  575. value: coin.value.unwrap(),
  576. token_id,
  577. public: keypair.public,
  578. }],
  579. };
  580. let tx = builder.build(&self.mint_pk, &self.burn_pk).unwrap();
  581. tx.verify(&state.mint_vk, &state.burn_vk).unwrap();
  582. let _note = tx.outputs[0].enc_note.decrypt(&keypair.secret).unwrap();
  583. let update = state_transition(&state, tx).unwrap();
  584. state.apply(update);
  585. state.own_coins[0].clone()
  586. }
  587. }
  588. impl fmt::Display for Stakeholder {
  589. fn fmt(&self, formater: &mut fmt::Formatter) -> fmt::Result {
  590. formater.write_fmt(format_args!("stakeholder with id: {}", self.id))
  591. }
  592. }