From d726710ef9e5574d4601bb4aca253c8ba1a45080 Mon Sep 17 00:00:00 2001 From: Murisi Tarusenga Date: Fri, 26 Jan 2024 17:02:16 +0200 Subject: [PATCH 01/16] Changed the note scanning algorithm to not require additional context. --- crates/core/src/types/storage.rs | 1 + crates/sdk/src/masp.rs | 257 ++++++++---------- ...9C0FD9A4E019CE37AABDC5D0E4B738FE06034B.bin | Bin 0 -> 10105 bytes ...D4D70154B89179E7DA6F14C700AAE1EC531E80.bin | Bin 2045 -> 2045 bytes ...753FB3BE606A5729D43A6EA8F79007D34F6C60.bin | Bin 2045 -> 2045 bytes ...AA6B8D85E10E17ED9D098B9C6B8C6795B1E0F3.bin | Bin 0 -> 2045 bytes ...2A3AC62CC602036F676E17820AD9CDD04DB3F5.bin | Bin 0 -> 12076 bytes ...0F3AD4FA4AB61D0B965BB9ED02971491A2B7FC.bin | Bin 2045 -> 2045 bytes ...21C4A7EB97EAC95F77B0410D41305EEF3C766F.bin | Bin 0 -> 8608 bytes ...16BE737B7C747CD18D3B832DEC3C9DDCF3DBF8.bin | Bin 0 -> 4895 bytes ...DF787F70D27FE1DE4CEFD4756B6753AB603FCF.bin | Bin 0 -> 2045 bytes ...80F84F6B712C682DD639AF812F29AF23E4AB7F.bin | Bin 0 -> 6393 bytes ...DBE3DA9201B7C90E74A7B6C2B9B7320F006872.bin | Bin 0 -> 6393 bytes ...346C4D5419EB8C2C4174F5DC1317D493122486.bin | Bin 0 -> 6910 bytes ...83E61BED82F25C4452CA41B769C3BABEB62D2B.bin | Bin 2045 -> 2045 bytes ...06FB77DB730FFFE562F2565B0431F7A901CC9A.bin | Bin 0 -> 2045 bytes ...48447BC02F4A27D5ECAEE75DD468D66DE97346.bin | Bin 0 -> 2045 bytes ...07ECEFBCDCC2ABB01BC7956857DFF45C81123C.bin | Bin 0 -> 6177 bytes ...1E2DCE33145F68A217FD50B065966646F59116.bin | Bin 2045 -> 2045 bytes ...5852DCD946FCC03040DF7A58FDA0B6CC4919AA.bin | Bin 0 -> 7875 bytes ...C387A0A9919A436A15C6DEC3834051B7CC7993.bin | Bin 0 -> 7650 bytes ...926C88FA3742B7F3A45DC0E1227236BC835003.bin | Bin 0 -> 6910 bytes ...A81A7DF315190329C7C2F708876D51F60D2D60.bin | Bin 4895 -> 4895 bytes ...B78DD77AA5620AC08519F73AB740B5A44AFA65.bin | Bin 0 -> 5412 bytes ...FBE1500FF70DC4F2365C83D9BB9015D3C28CE1.bin | Bin 0 -> 2045 bytes ...5A0AD04432D0D4BB8B2488EA5E836837B00394.bin | Bin 0 -> 2045 bytes ...9BC3BBACE79DF98801EB8154EA1904597854A1.bin | Bin 4679 -> 4679 bytes ...F7858007C4DA521F8E3BF250A46E9342178EEB.bin | Bin 5660 -> 5660 bytes wasm/checksums.json | 48 ++-- 29 files changed, 131 insertions(+), 175 deletions(-) create mode 100644 test_fixtures/masp_proofs/2AB777063F53A1E6F66DB635DD9C0FD9A4E019CE37AABDC5D0E4B738FE06034B.bin create mode 100644 test_fixtures/masp_proofs/5DE7FF931D7864F0C05FD54926AA6B8D85E10E17ED9D098B9C6B8C6795B1E0F3.bin create mode 100644 test_fixtures/masp_proofs/693468170864DF8C1A8C13FE2C2A3AC62CC602036F676E17820AD9CDD04DB3F5.bin create mode 100644 test_fixtures/masp_proofs/7198F6516381EEB67048E3099D21C4A7EB97EAC95F77B0410D41305EEF3C766F.bin create mode 100644 test_fixtures/masp_proofs/7A240D86DB78C8E1478FB0857D16BE737B7C747CD18D3B832DEC3C9DDCF3DBF8.bin create mode 100644 test_fixtures/masp_proofs/7B6C8C638FEE08497ACAEB06BFDF787F70D27FE1DE4CEFD4756B6753AB603FCF.bin create mode 100644 test_fixtures/masp_proofs/84320514AEC06D9AADC35DEF5C80F84F6B712C682DD639AF812F29AF23E4AB7F.bin create mode 100644 test_fixtures/masp_proofs/849D9E73D858B17BBB5856FAC2DBE3DA9201B7C90E74A7B6C2B9B7320F006872.bin create mode 100644 test_fixtures/masp_proofs/891CCBE84265DFA7F35C8E5F08346C4D5419EB8C2C4174F5DC1317D493122486.bin create mode 100644 test_fixtures/masp_proofs/B13164F18807523FAB9840F34106FB77DB730FFFE562F2565B0431F7A901CC9A.bin create mode 100644 test_fixtures/masp_proofs/B7C738AE39C44060FD6EA5D7C648447BC02F4A27D5ECAEE75DD468D66DE97346.bin create mode 100644 test_fixtures/masp_proofs/B88A2DB72E3A0A624B9076C5A707ECEFBCDCC2ABB01BC7956857DFF45C81123C.bin create mode 100644 test_fixtures/masp_proofs/C83BAD95A33CB66390611EF8155852DCD946FCC03040DF7A58FDA0B6CC4919AA.bin create mode 100644 test_fixtures/masp_proofs/C9D7CDFED7CB968E7743BE392EC387A0A9919A436A15C6DEC3834051B7CC7993.bin create mode 100644 test_fixtures/masp_proofs/CA9143A071C194759B72139C6B926C88FA3742B7F3A45DC0E1227236BC835003.bin create mode 100644 test_fixtures/masp_proofs/D38C391DF4F1F69AB04682F0C1B78DD77AA5620AC08519F73AB740B5A44AFA65.bin create mode 100644 test_fixtures/masp_proofs/D5A372904527694939249FA0AAFBE1500FF70DC4F2365C83D9BB9015D3C28CE1.bin create mode 100644 test_fixtures/masp_proofs/DBE07FDEDBF79BBC814D3EB70E5A0AD04432D0D4BB8B2488EA5E836837B00394.bin diff --git a/crates/core/src/types/storage.rs b/crates/core/src/types/storage.rs index 1ac99d11b4..da1ed2920e 100644 --- a/crates/core/src/types/storage.rs +++ b/crates/core/src/types/storage.rs @@ -1463,6 +1463,7 @@ impl GetEventNonce for InnerEthEventsQueue { PartialEq, Ord, PartialOrd, + Hash, )] pub struct IndexedTx { /// The block height of the indexed tx diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index c3cf8d1bf3..4e18ec7ecd 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -525,10 +525,11 @@ pub struct ShieldedContext { /// Location where this shielded context is saved #[borsh(skip)] pub utils: U, - /// The last indexed transaction to be processed in this context - pub last_indexed: Option, /// The commitment tree produced by scanning all transactions up to tx_pos pub tree: CommitmentTree, + /// Maps viewing keys to the block height to which they are synced. + /// In particular, the height given by the value *has been scanned*. + pub vk_heights: BTreeMap>, /// Maps viewing keys to applicable note positions pub pos_map: HashMap>, /// Maps a nullifier to the note position to which it applies @@ -550,6 +551,8 @@ pub struct ShieldedContext { pub asset_types: HashMap, /// Maps note positions to their corresponding viewing keys pub vk_map: HashMap, + /// Maps a shielded tx to the index of its first output note. + pub tx_note_map: BTreeMap, } /// Default implementation to ease construction of TxContexts. Derive cannot be @@ -558,7 +561,8 @@ impl Default for ShieldedContext { fn default() -> ShieldedContext { ShieldedContext:: { utils: U::default(), - last_indexed: None, + vk_heights: BTreeMap::new(), + tx_note_map: BTreeMap::default(), tree: CommitmentTree::empty(), pos_map: HashMap::default(), nf_map: HashMap::default(), @@ -586,33 +590,38 @@ impl ShieldedContext { self.utils.save(self).await } - /// Merge data from the given shielded context into the current shielded - /// context. It must be the case that the two shielded contexts share the - /// same last transaction ID and share identical commitment trees. - pub fn merge(&mut self, new_ctx: ShieldedContext) { - debug_assert_eq!(self.last_indexed, new_ctx.last_indexed); - // Merge by simply extending maps. Identical keys should contain - // identical values, so overwriting should not be problematic. - self.pos_map.extend(new_ctx.pos_map); - self.nf_map.extend(new_ctx.nf_map); - self.note_map.extend(new_ctx.note_map); - self.memo_map.extend(new_ctx.memo_map); - self.div_map.extend(new_ctx.div_map); - self.witness_map.extend(new_ctx.witness_map); - self.spents.extend(new_ctx.spents); - self.asset_types.extend(new_ctx.asset_types); - self.vk_map.extend(new_ctx.vk_map); - // The deltas are the exception because different keys can reveal - // different parts of the same transaction. Hence each delta needs to be - // merged separately. - for (height, (ep, ntfer_delta, ntx_delta)) in new_ctx.delta_map { - let (_ep, tfer_delta, tx_delta) = self - .delta_map - .entry(height) - .or_insert((ep, TransferDelta::new(), TransactionDelta::new())); - tfer_delta.extend(ntfer_delta); - tx_delta.extend(ntx_delta); + /// Update the merkle tree of witnesses the first time we + /// scan a new MASP transaction. + fn update_witness_map( + &mut self, + indexed_tx: IndexedTx, + shielded: &Transaction, + ) -> Result<(), Error> { + let mut note_pos = self.tree.size(); + self.tx_note_map.insert(indexed_tx, note_pos); + for so in shielded + .sapling_bundle() + .map_or(&vec![], |x| &x.shielded_outputs) + { + // Create merkle tree leaf node from note commitment + let node = Node::new(so.cmu.to_repr()); + // Update each merkle tree in the witness map with the latest + // addition + for (_, witness) in self.witness_map.iter_mut() { + witness.append(node).map_err(|()| { + Error::Other("note commitment tree is full".to_string()) + })?; + } + self.tree.append(node).map_err(|()| { + Error::Other("note commitment tree is full".to_string()) + })?; + // Finally, make it easier to construct merkle paths to this new + // note + let witness = IncrementalWitness::::from_tree(&self.tree); + self.witness_map.insert(note_pos, witness); + note_pos += 1; } + Ok(()) } /// Fetch the current state of the multi-asset shielded pool into a @@ -623,74 +632,42 @@ impl ShieldedContext { sks: &[ExtendedSpendingKey], fvks: &[ViewingKey], ) -> Result<(), Error> { - // First determine which of the keys requested to be fetched are new. - // Necessary because old transactions will need to be scanned for new - // keys. - let mut unknown_keys = Vec::new(); + // add new viewing keys for esk in sks { let vk = to_viewing_key(esk).vk; - if !self.pos_map.contains_key(&vk) { - unknown_keys.push(vk); - } + self.vk_heights.entry(vk).or_default(); } for vk in fvks { - if !self.pos_map.contains_key(vk) { - unknown_keys.push(*vk); - } + self.vk_heights.entry(*vk).or_default(); } - - // If unknown keys are being used, we need to scan older transactions - // for any unspent notes let native_token = query_native_token(client).await?; - let (txs, mut tx_iter); - if !unknown_keys.is_empty() { - // Load all transactions accepted until this point - txs = Self::fetch_shielded_transfers(client, None).await?; - tx_iter = txs.iter(); - // Do this by constructing a shielding context only for unknown keys - let mut tx_ctx = Self { - utils: self.utils.clone(), - ..Default::default() - }; - for vk in unknown_keys { - tx_ctx.pos_map.entry(vk).or_insert_with(BTreeSet::new); + // the latest block height which has been added to the witness Merkle + // tree + let Some(least_idx) = self.vk_heights.values().min().cloned() else { + return Ok(()); + }; + let last_witnessed_tx = self.tx_note_map.keys().max().cloned(); + // get the bounds on the block heights to fetch + let start_idx = std::cmp::min(last_witnessed_tx, least_idx); + // Load all transactions accepted until this point + let txs = Self::fetch_shielded_transfers(client, start_idx).await?; + + for (indexed_tx, (epoch, tx, stx)) in txs.into_iter() { + if Some(indexed_tx) > last_witnessed_tx { + self.update_witness_map(indexed_tx, &stx)?; } - // Update this unknown shielded context until it is level with self - while tx_ctx.last_indexed != self.last_indexed { - if let Some((indexed_tx, (epoch, changed_keys, stx))) = - tx_iter.next() - { - tx_ctx.scan_tx( - *indexed_tx, - *epoch, - changed_keys, - stx, - native_token.clone(), - )?; - } else { - break; - } + let mut vk_heights = BTreeMap::new(); + std::mem::swap(&mut vk_heights, &mut self.vk_heights); + for (vk, h) in vk_heights + .iter_mut() + .filter(|(_vk, h)| **h < Some(indexed_tx)) + { + self.scan_tx(indexed_tx, epoch, &tx, &stx, vk, native_token.clone())?; + *h = Some(indexed_tx); } - // Merge the context data originating from the unknown keys into the - // current context - self.merge(tx_ctx); - } else { - // Load only transactions accepted from last_txid until this point - txs = Self::fetch_shielded_transfers(client, self.last_indexed) - .await?; - tx_iter = txs.iter(); - } - // Now that we possess the unspent notes corresponding to both old and - // new keys up until tx_pos, proceed to scan the new transactions. - for (indexed_tx, (epoch, changed_keys, stx)) in &mut tx_iter { - self.scan_tx( - *indexed_tx, - *epoch, - changed_keys, - stx, - native_token.clone(), - )?; + std::mem::swap(&mut vk_heights, &mut self.vk_heights); } + Ok(()) } @@ -945,82 +922,62 @@ impl ShieldedContext { epoch: Epoch, tx_changed_keys: &BTreeSet, shielded: &Transaction, + vk: &ViewingKey, native_token: Address, ) -> Result<(), Error> { // For tracking the account changes caused by this Transaction let mut transaction_delta = TransactionDelta::new(); + let mut note_pos = self.tx_note_map[&indexed_tx]; // Listen for notes sent to our viewing keys for so in shielded .sapling_bundle() .map_or(&vec![], |x| &x.shielded_outputs) { - // Create merkle tree leaf node from note commitment - let node = Node::new(so.cmu.to_repr()); - // Update each merkle tree in the witness map with the latest - // addition - for (_, witness) in self.witness_map.iter_mut() { - witness.append(node).map_err(|()| { - Error::Other("note commitment tree is full".to_string()) - })?; - } - let note_pos = self.tree.size(); - self.tree.append(node).map_err(|()| { - Error::Other("note commitment tree is full".to_string()) - })?; - // Finally, make it easier to construct merkle paths to this new - // note - let witness = IncrementalWitness::::from_tree(&self.tree); - self.witness_map.insert(note_pos, witness); // Let's try to see if any of our viewing keys can decrypt latest // note - let mut pos_map = HashMap::new(); - std::mem::swap(&mut pos_map, &mut self.pos_map); - for (vk, notes) in pos_map.iter_mut() { - let decres = try_sapling_note_decryption::<_, OutputDescription<<::SaplingAuth as masp_primitives::transaction::components::sapling::Authorization>::Proof>>( - &NETWORK, - 1.into(), - &PreparedIncomingViewingKey::new(&vk.ivk()), - so, + let notes = self.pos_map.entry(*vk).or_default(); + let decres = try_sapling_note_decryption::<_, OutputDescription<<::SaplingAuth as masp_primitives::transaction::components::sapling::Authorization>::Proof>>( + &NETWORK, + 1.into(), + &PreparedIncomingViewingKey::new(&vk.ivk()), + so, + ); + // So this current viewing key does decrypt this current note... + if let Some((note, pa, memo)) = decres { + // Add this note to list of notes decrypted by this viewing + // key + notes.insert(note_pos); + // Compute the nullifier now to quickly recognize when spent + let nf = note.nf( + &vk.nk, + note_pos.try_into().map_err(|_| { + Error::Other("Can not get nullifier".to_string()) + })?, ); - // So this current viewing key does decrypt this current note... - if let Some((note, pa, memo)) = decres { - // Add this note to list of notes decrypted by this viewing - // key - notes.insert(note_pos); - // Compute the nullifier now to quickly recognize when spent - let nf = note.nf( - &vk.nk, - note_pos.try_into().map_err(|_| { - Error::Other("Can not get nullifier".to_string()) - })?, - ); - self.note_map.insert(note_pos, note); - self.memo_map.insert(note_pos, memo); - // The payment address' diversifier is required to spend - // note - self.div_map.insert(note_pos, *pa.diversifier()); - self.nf_map.insert(nf, note_pos); - // Note the account changes - let balance = transaction_delta - .entry(*vk) - .or_insert_with(I128Sum::zero); - *balance += I128Sum::from_nonnegative( - note.asset_type, - note.value as i128, + self.note_map.insert(note_pos, note); + self.memo_map.insert(note_pos, memo); + // The payment address' diversifier is required to spend + // note + self.div_map.insert(note_pos, *pa.diversifier()); + self.nf_map.insert(nf, note_pos); + // Note the account changes + let balance = + transaction_delta.entry(*vk).or_insert_with(I128Sum::zero); + *balance += I128Sum::from_nonnegative( + note.asset_type, + note.value as i128, + ) + .map_err(|()| { + Error::Other( + "found note with invalid value or asset type" + .to_string(), ) - .map_err(|()| { - Error::Other( - "found note with invalid value or asset type" - .to_string(), - ) - })?; - - self.vk_map.insert(note_pos, *vk); - break; - } + })?; + self.vk_map.insert(note_pos, *vk); } - std::mem::swap(&mut pos_map, &mut self.pos_map); + note_pos += 1; } + // Cancel out those of our notes that have been spent for ss in shielded .sapling_bundle() @@ -1172,8 +1129,6 @@ impl ShieldedContext { change: -amount.change(), }, ); - self.last_indexed = Some(indexed_tx); - self.delta_map .insert(indexed_tx, (epoch, transfer_delta, transaction_delta)); Ok(()) diff --git a/test_fixtures/masp_proofs/2AB777063F53A1E6F66DB635DD9C0FD9A4E019CE37AABDC5D0E4B738FE06034B.bin b/test_fixtures/masp_proofs/2AB777063F53A1E6F66DB635DD9C0FD9A4E019CE37AABDC5D0E4B738FE06034B.bin new file mode 100644 index 0000000000000000000000000000000000000000..5fd246bed0b1bd2888e4c42d995eec4090049572 GIT binary patch literal 10105 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 Lv0pi8e_#9u_`u6S literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/2B6C3CEF478B4971AF997B08C8D4D70154B89179E7DA6F14C700AAE1EC531E80.bin b/test_fixtures/masp_proofs/2B6C3CEF478B4971AF997B08C8D4D70154B89179E7DA6F14C700AAE1EC531E80.bin index 896302b0a08d269fd8a34f058423f58b29ea1a40..928780e08149c1c7cbbf747edb541e9311cfe51e 100644 GIT binary patch delta 601 zcmey%|Ce9q^?wLpWME*p;PWwG+j@dP&5wtQE21Y%w|Y^Nm>(WD^Y(YXuKR7%-b~cd zR3NCP)RUl^jrZ!92r8Of!>r(-FI!PEW#v4XS+hRt6g*z8Q){KH$X{1C-FV4`*jvx0 zEA#}deaG>rH}Edc?P8Z%|M{0)F;iF`)O@#Zcj2O@E3ZQ*-(faUh@GiCMa^(+5ZlHK zLz~V$PuY25T(1Q6?tQ%1?p&O&J_5JjD#q)fXA7)K%<$>yt*XoHv>Ml`T@oD87mE^0>zZL9g d2=kBH^4V;`+2%FxcTLVx*!wh&Z}LNS830E7Hwgd$ delta 601 zcmey%|Ce9q^?wLpWME)uxXN6huwG^P@$c!$EAE}QdLooM`|q!*-CrV?otrDtxp<8fFEDi()TVDBEj?+a~4Px4mie?D*w;H{jRT_qGw+-(SnL zI#9m6uCRqaDdNeT{+ZunXKb{HdU4Qqg0Hg9c_*XLE3&Ix%}HZ8$Qvp(lr>{1Woc@n3N z&(xh(WD^Y(YXuKR7%-b~cd zR3NCP)RUl^jrZ!92r8Of!>r&S`se%X7cKL;ne{k2Uk7CDTYbP+EZaJktK{W(frt0& z`?`cCh+HYO={R&!KR07LPspcJ4zs7dZLgWC`IaH&pm50KJIp2u%@yAc*-X?<;oblD zl1YZ)ua8&L%=D@JPZdcOdEYx5dp`<4 zofN!kM|<1GDTfcN_H;e3@+nXvdEcXkxlb4C@A_)H=+D%;iT7p%)oT>wE_YL(9ICvd zGi8p}w)~wex315dRwH|I|KEjc9!~L`(JfWA@mYFBeG+$m_+HU^-P-iLU2*1NhQ)U* zd0kJ(Z(N)2w3n|evf$Wl-L;axjDH<`*51bXJ^thz&YbBJbOk-sGu};iN@|Y~j$I;h zvG>k&b%ypm(zi5vq^}k{Q7bf(p0~wCrXyP}C1=i=pV>2?y|Qqa{!eAq{1Eu9dxi8J;I+b3?-UG^fv!xnInx|4p3xux6r; zrUF4VrJe-UY`j;;L{QP>8fFED;${5TvM;}}-tpuACpOOcsy1P7Kc2tke1u(B!gBXt zk$KZuvhM3~uB`p87JJm{$^?!jYK*r&OH5}y*KFgUZuMP$@*QRqg^7O{S1ia8zq8!% zv()L>{ei-_xLry#S=62|Em3Z9nU}lSfJK2xpy!N%)-mIv1Nr+5C$RW51W!(23#=#P zTLyWqU(f&qQ;YB0N&UDgzDbU!F_Gb5@(Kk-mDP_Uy4*{{FR`>SSvB6d@rVUnX{FLB?}^)%p~_PhHD@Deug%zu~mRNocj~QSB#b@!o_|cGUlzH(x*Pu~eEZ3xgY=+&{M;&#vNT$v7Y1LdYJb`h1gLx2hBb1wDeYRgLhzXSyWC}}ein>umiC&sWRvDJsW3U_lb z$oPeB6FV3EYj%csp1&BY_ItLw?KW@!7-e_7cq!WSKtMsxWIsFqDju$`s~=*y687$~ z-TKBwZL)fyNO0nY|BY_>x`kbj)dKj+T)ziz{5vy~fji}8_{@LD=6b!FetgI2FTC5l zHF|m1&fB%4Vn&Z)Yx{fZftb{!969S+y7?r3!CG|P2M zt!}*@pYU{PyVvjY_D>VmJru54#_geV!}Cy9NkqK(pP6UWi)Y?_e_+W;n+*9w*?i5c z?Ye(jp4DyiXY-r%L%(?6wea~DRG9lCBV<-3t>zRD< zrpkmr^PEEt&A-3%gVO^}!<~lCQ*yjsF_}FuZw{UJQPpaRj9jGjS+_Ee+g*B_51uNE zIVKQXaV+WAmcv#`**hn?E}U7tK;d7uV`(XWU0=R_LF%8S*4*q7dki~5xbhF?9ag&_ zdP2!o@|^Mh|EKT2&TyCeP~=wdCS-B-4yNaKmo4}n>l+-j@~_`gLz{^cvqf9KPf)3r zwqt(qGLAQ}Ft+QL$*{38M>)?NRSbR)70? zn=SXKZtGjwjU^iS*X1J&^RKBoEpHOq?PUA>jXl%198s=CkL2PLk8fxZX)1m3_sE^1 z6Rr!6v59?I9T0K6eZo?`D=#Oftk`)++si*hQ0++htm*sMm?HYDnLeM~a&<%5Cu!UL zhrFgl_WCOSI>)WgCms|YwoJ*ZX<@NheRG~ngkqbX=2Y z-q&nDd|WMU`Nz5+%Uf=(KBv^ushIgC$|vHMd_|?LvyW`4=jF9qU!AVpXH~{|NoLjo zBRO;Vc>DVDvNMr+Jn@;6X3I0PF(uzTzG%{B*8B! zshf!L&2nFwwdBa7hABrit3O&z7EA2&@43*nOZt&kzHwgM=k1G67QfzI^wvnuqvN-f z>cMjvl}j0e7do%?YGYo;cf;Y4`jx)OvV*_67o820t8h~(k`5puQ=!%^OB$YR{t_qZ z6fE*`Yl`sPBzSDGA=DxrSpDy?uv^BCAxd$b#BNiHoWb7?RRZK``ZFX zhJ_*5MVx~Im&Go7aO_sf&-WHvuYKuURGIbT{o2byjB9ch%@40xATGJ_X=McGYxYgL zHa5+?`Km8mmu^n8)Hvr_G5ufjE5F^6uQhY`yVdVlz%e&%gZuCJDIJREuhqu<(`Lz; zJc(0#)oX@YK}RRogs3%(6`y_yE^p^|eEE50``+X1J>AOJt>-$_O;f6veL_vvI(@C6 zWxsmTP04yU-v6$bjS4NjM60i*Pm@%-CV50t_LozCFIUr^#_bobCruP~^qpc^`75A^ P2UaA5t5zt71xf<|bCBA@ literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/693468170864DF8C1A8C13FE2C2A3AC62CC602036F676E17820AD9CDD04DB3F5.bin b/test_fixtures/masp_proofs/693468170864DF8C1A8C13FE2C2A3AC62CC602036F676E17820AD9CDD04DB3F5.bin new file mode 100644 index 0000000000000000000000000000000000000000..e2b6c5b4ead3c8f85f66d1fa6b329bd616288bdd GIT binary patch literal 12076 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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/6A12E11EEAA83A0D00BF7470DD0F3AD4FA4AB61D0B965BB9ED02971491A2B7FC.bin b/test_fixtures/masp_proofs/6A12E11EEAA83A0D00BF7470DD0F3AD4FA4AB61D0B965BB9ED02971491A2B7FC.bin index 492c021d126d71f56ba59a02b19fe5e59fc312f7..0e726100161b4d3fe8b85a20f64c47d6ccc896ae 100644 GIT binary patch delta 637 zcmey%|CitJ^?wLpWME)Oy8ryw`R6U_(SKOxm)-xq^N@%11HYdapU7kCgN01Ze*5rxY`>fT=e!$*uMQ+3U<$(GwbDU z*A!Q?y4 zy6VlgjvMxzUSat9LHG?{`(Ulz5;?Elgk9n63eGp4vqpZgW6+6pFKYg6HegX;5}0`V zVzdOq);71w`Hz1;D72iMz!q3fR2V=57ep<7@HyaCjP2Vs?Xnl{gdS;~wRy!YRg;X5+neg*dO8esOvEBM3@^-stAKeA8N6O?=}ln*uFngm-jC^5u0xJZkBf0jBQt* ziB6qdw^{F*>lxQn?i*aX5p^s4KFm1zI9jrHvR-bDTu4jOwk)G}zwiEf%dh#e$#w4e z*&9v?gg#tZzJV#&+eA0%Q1}(Yt@4_;OBKs~O$s*ZK2+*h{Je%~@+zfO`dOz45v*>I~$$#mxs-H zs=#NP=-50jCMUO50s%~X7nr>#Uu1F5ouZ|+c(MK(r-JU+ZBOR86r`T~yy~mvaS+$9ochw#pQ=AcgwBapeb4SyX?U2L zboQmDWW9c9ZtUd`y$5APdM`Uxqi1WLcUp=rX=GFgeRWgJ z|Ba<%SNN=~3Ln)Y!jVfp6>$EZee>N-|06T|E_|<7*kC!$$TC~Xfot)Dn?H|6#@26P z_FXjl>R*{pPgX5BzgDbD<@{@Pm(w}>Y`(iqjgV(+5Ngkv$2j>Ry9fspFr9$_04vo) A7ytkO diff --git a/test_fixtures/masp_proofs/7198F6516381EEB67048E3099D21C4A7EB97EAC95F77B0410D41305EEF3C766F.bin b/test_fixtures/masp_proofs/7198F6516381EEB67048E3099D21C4A7EB97EAC95F77B0410D41305EEF3C766F.bin new file mode 100644 index 0000000000000000000000000000000000000000..2fa21a2cdc62d33ec4a77ec7c7bdccdad55a3728 GIT binary patch literal 8608 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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/891CCBE84265DFA7F35C8E5F08346C4D5419EB8C2C4174F5DC1317D493122486.bin b/test_fixtures/masp_proofs/891CCBE84265DFA7F35C8E5F08346C4D5419EB8C2C4174F5DC1317D493122486.bin new file mode 100644 index 0000000000000000000000000000000000000000..be73968fd29dd1357085a023d67c528d893a25d4 GIT binary patch literal 6910 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 A0{{R3 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/B0876E15DE7B2C742912E048F583E61BED82F25C4452CA41B769C3BABEB62D2B.bin b/test_fixtures/masp_proofs/B0876E15DE7B2C742912E048F583E61BED82F25C4452CA41B769C3BABEB62D2B.bin index dd3f26ba0b5e09c55eede5979d2697289b2a04d7..988eb94e354b6a2873d41af4f4225237d7911fee 100644 GIT binary patch delta 633 zcmey%|Cit3^?wLpWME)Oy8ryw`R6U_(SKOxm)-xq^N@%11HYd=<-n-HV!kn+;eLm;^4p_!;uV z?UUXey-kAay2EEqPGAeHCnf-(;R>euH5uxBzC2fSpL5sGe{GHFw|R5oCOuR+G$m!Z zm0k9BevMsWH$J2_N9!kWXFWD+YFHlJbjv4^@pfC<44y@c3Z%cSv+w#Le`(T(V`&XS z2D|FH_g$*6b>DN;(c)6_-rU2719>L+JZDU~vL@{QsZa8M0v|@I?$JD$zv$~dyFXov zg#NSL{KO=nZe_Ur-undpx3x}%T{eFm7ey|fWEs#meGC8W2}?M42c+LoO*}vCOkTGj zlON~7DJ!Pm-`<+S6>X$m6WJ;s7}Wp5?#I7&>pKk_rx+RhH&QIWwqwqtlP!B1zq$QY wINOk|EtM6K9@xWhblW3secLhv_k!I8CwP)gYsJJ5OEOG;$S%SGN@E}Z08KPJ^Z)<= delta 633 zcmey%|Cit3^?wLpWME)8;(E|za@C)QUw>%D>^Xf-_pv!^xbODFmUCUJ?Ckzmu4kBH zT0YT0RfV9soKqbWD_sez1Ddz-Q56$W3MV%(%Q*NMtX;&fF2D9jK=`A@Vot^4Yi$z} z7MLfsuJ0~XeA<7k;z{|Qy*H%xGuF-FslF%ESN`nLwJ)Au`MgCM-%mdu%`o{6v#$F5 zsF)*rPOq3=cx-0N1^1~f`_0xX{K$9E`09JZ;L<_+d;3ZsYpb#C+ibw1z$CEbT=?v+ z!mENiS#zqHFEt*UoWK@XPfP$n!xcEcOpHEbGV)XHIS~R&wK=QS0h*f6PYW4LuO?z!QG>#k%<$Pc;&t>^seR&=q zskmst{#oBNT2p`IJZ64xmYXrD+VZLCg*eBn2bRA&Dfn-@b|BxOlEOdx7eCy!&-{z1 z+m5M8_nfPrR!u&dc<~0$_lAfy``Xrv-&vZlif`wpc%yj#rq8GQvT98X>X*)UTEqT$ xsatkpWZR1?SM#qe-=&}B diff --git a/test_fixtures/masp_proofs/B13164F18807523FAB9840F34106FB77DB730FFFE562F2565B0431F7A901CC9A.bin b/test_fixtures/masp_proofs/B13164F18807523FAB9840F34106FB77DB730FFFE562F2565B0431F7A901CC9A.bin new file mode 100644 index 0000000000000000000000000000000000000000..cd3c95a2647acf30e9011caf86a628b14ce33184 GIT binary patch literal 2045 zcmaF;9|9N|7#QjulAG4vpE6mypj>itzbseNSxz0L77a9@QIlb;#iR}wgpQ?!*~C|6YJuGf6Fr#{>|D| z*t*YnS+(|LF6}`@>o1XhQZd)#vM+-DIz|yE;?7Z%Pg0F)=Q~^GpZl zvR(N0bhT_*_tbA7hmV308v;x~pL3}%S6f#4|0O68Kxvzi*wl$5KQRVesA1aU_hN%G zcZbh6)*S1S&!Q~97A^JlVfp>+#Sxw77y2G)W@YMBscsSsmE2qQ==hD^oHY#hPr3f% z{r-dfre3{{?BUcO%K70v9)@h@I!gI}CcUt5Wwbn1^yy!ckHM)K%#$pX-n+!lcDd*j zE$5@fx%c!6osty&U8VZZqs+5k@$cD_?#b`CIR0VBqM%swm0uXXMY`ur`K~qbpYi1< zhc3z2-1$C#^*N!X&$V9MkgT0ixL!z3Q?fflIO0NO7I$8Y*QqB_j4Ui6LESbtwpQ<$ z9smBT@zM?VLfRb)g^oCFmbY8X{`{y`)wLqFH3f=~Hhfz)-P0{iY3A;4OZ~%=#C)_E zS1Kni*<}9OZ0Dj3)k&o{ib5M!7ESVseG{$ba!kKdMzS!@Vzri~*o|*F-g9;b*<=_6 zD`fH3J?Qx8$J1~}_CTvFo11~j*_pdvR^4`6zP56DK5ysR=|S(8ADr9&TrPP12T_;# z|92<2+Xh{k^&~2y@ad`&a}Vv13Gc7E)W$k%G}k0CNNlKe)8jL54ihMm7s>vrQeWi9 zqM70|hs|hG;XG51WA2wGFlIhHw4-Rb+n&Ye7`CglT%9su>-^wB_usK7S`aJ8OjUcH6xh>O&OrmmB@hepvir z&hPNa0V(kT-PI{ObAI@I^)yAo#nOYyy4-;)@uy6Dnz>cdYfmq{>lrt)6$W5ZmWGiptt_WT$TfejSXw(%u`<+ z5%KY!jNvU|mX9|6Tdv;buIlZs+ro8ZXKG*kYmZ-sC$2Pe+-KeNV9Gw11_eL4)vG$9 zAM)K>zSMk8#9Qs4W&H&nyFMsfUK1+!>%_jCZe}YHm+1zTiTrmyo%ynu_uQG5cZ=V> zKj5`{Cwt<`rCCdkJZhM7RI~b{)nu{6KL4HzZM&o&Y2_Q|#eLqs_+;_x-9>MWsQx)XD{9{vr5PNa?rMxsb^)aw&%>>r$a+cdUBPk4qHt%meebcO)mz_Z?_#QL7TzehNB+?AzK#4p zXWZSw=cstzYpvz)Qyz-85ufJ@1}~7>&Gq7%J^z#q2YWAklz4X9yJ+h+4Iv5M$?tkT z`((yc^5pX!JHdLn{hiJBgMV)wwN51o$%}bO!MuH8N?5jURCc3|H@OP z=P>i@9|!5XZuiVIye6E{h~M|*%=~p9ZVRinEZ4r)G;epnn~c@7)l7Xh-g^~v_Z}Wup${;wL&>CHUJu@+SdR8 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/B7C738AE39C44060FD6EA5D7C648447BC02F4A27D5ECAEE75DD468D66DE97346.bin b/test_fixtures/masp_proofs/B7C738AE39C44060FD6EA5D7C648447BC02F4A27D5ECAEE75DD468D66DE97346.bin new file mode 100644 index 0000000000000000000000000000000000000000..30b622be46123f4fdf9af7af6099c9c2d55ff5d7 GIT binary patch literal 2045 zcmaF;9|9N|7#Jds3t86JLR1uA2R zy}DIYP2rizY?jkfZuZuj``A5vK;jIqfo2h9kUZBfsJ&nctQkarG&8(>Fi~9U|=Y6m4bLIPV9q+1&Eg#Jc$4-|~!wf3tQKwl4SD z*?&yvToi}e+9f{cKl=Rg{&3bgnvgwA_4ztyH`#0LuFh2Nn^MDgOpMF$Jk!CsY!|*g zT`gPIJ@p&N;iF*0h5!@L=UnQ`)s~h1e+dc%P_kwuHg)32PmE2R(^%WtUQC@EZ-4o@ za>z54C0_qiWG^WCZmT@_(c1aNv||@`sU@5|W_fjg`OB+^-|^k&ku_bV@c94a#Rn!^ zKlG^Akv*LHLpeXZ$HS1#Tt_MY&!iU?u8fwaiaz~I@-a9ygL#sL(tDTq*)A8IX1|)H zcVy4$72F>(m#hk?EZeQPUPRXX=(JxIw-esny8T1e?t#F@_Tmrjc~ib?P5ftk`N^S6 z@-=t9&tH8`Xz6pU7dIqpXB4g%lGBvz&Jd2cP?^P@*Wz{RNfaXsOGr?+&5f5Zb$hLuH=ykg%(tGOK0@05`&jI&s+Whr*!TaNdf-9a`PM!^bM zymb#cKKk)A+>t%dD$C|(U~+cm?w3`!-IlMdoSx6yxpsQc`{f7c_CJ>kUjISVW&Z!& z3GTK*S7tqliYR=#s>IwwJ7mK9t1h*%&Kk`%NemJjYTfks%$vgmO5{bdzpB(1`LSrG z_{?E5np8N?)Z>`@r3s9g4-f4qTJE-I@i~U=DlJ#1OxQX<_}{NQo2&OS=TH3cw&m03 zqmvV!Oq}IYcOa$Uh=&i){Nv)9TTHq#@0-ux$tODF2CO9nXSL_!tJzlV zyeDILOPJ-OjsKRbx4El&yX&@a9od=M7ysJhm*I&k%^dexH$9lL&!s`ZPj2<9j_8Mc z_m(d;UlZ|GJ7`&dfyb^73YXV}%KbXAFQ=Q?O2lQlL1iNUolj@JG=FjLEbMl8WfN|9 zH*(>noTXVyjy!6Za#XYWqt#@w#6JI?3vIikA8F+q=f!>AzW8ME>)l0fjpRH!eoLty zJeN_qlrear^IESq=4E_093H7(>5D8o_^W%-*)X{ZHF@rg_;11PyPAhuQ)h80Gq1FL{;Op5tq=FE z8eNuTwE1*&K}tcxG^uUzKRp^}=I1}tD6Z*KW$ENC6#pjpFyz`s4UzijRWhvU={)8e zc?B0O%=BF$R-In-QnhK#r1fh%tggI`e7Rt6#&_0EdyZr4tiR0c*}X}qK>XRHy!Olo z%CcYV+4}!Y`~OYp9?P=5rq>^>k1ffM+0?0Xxbow_+4lsGOo_05mp^auhc{cKq^5rL O;D8m$;HnkMfw2MPALKFs literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/B88A2DB72E3A0A624B9076C5A707ECEFBCDCC2ABB01BC7956857DFF45C81123C.bin b/test_fixtures/masp_proofs/B88A2DB72E3A0A624B9076C5A707ECEFBCDCC2ABB01BC7956857DFF45C81123C.bin new file mode 100644 index 0000000000000000000000000000000000000000..155287509e7d8dd4a037217e44a19304f7d446ea GIT binary patch literal 6177 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 delta 601 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 m@-(Y%C&>_T{f&BL7vW#0WE!3hKjIyi*jZXq}c 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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/D1DF6FEDD8C02C1506E1DCA61CA81A7DF315190329C7C2F708876D51F60D2D60.bin b/test_fixtures/masp_proofs/D1DF6FEDD8C02C1506E1DCA61CA81A7DF315190329C7C2F708876D51F60D2D60.bin index 8357cbe5ed1cb99b84554487ffc9a07d4392a450..1a4531f734866a3b3129105b299a1bc6860905d2 100644 GIT binary patch delta 1358 zcmbQQHeb!)^?wLp00KrJPP+g6*ZJoy>d}8#=9k_7zVncW^aH=2JWDp0_KNN{WPU%< zK-NRoE&K#O|IXajD?tmi6<02M? zSk)4?dM1LZfNpo#?c};yUZ&#irkl+^9|8M#5NmNmDtYo9bb)%U=atEIz zaJ2guGM&#aT4r%BGS^z;Y|x$P;&n4@TE9$Qz^SBAv)-w%-!MASO-*@r!Jgl@BlmxM zUs+#m8vgx7R#VL1E1Ms2eqnOBQ?1ptV1}-X?R|bWw%Yg8`X94u+<8#Gg)w&h^FFDG zHaA$_9TZy9_|@z;|3O8mshYOGaPCqTK z2L1fa8}U@+zFgkRg@P^ITlbr1{N9|!tH4w*?Q^@MRpg}FWI@Uk|M^io?X zz|!9D;2&+=JT z`&BQ~`HV+)*DX@M!T!O>$ymO(QsK#4M*PuK&-|X@;a65r8iD~rX=IY@BG0y6y>nNn zDt)nTQr~y;QdijY-38^s)&0!}(2Ss{3aVMW^`!XTlV+m6uV!2 zC$AoQ>;7HTF^K=ZY{CDW$JtlwUj%Kx63%?>Usq`x|I^PmmNXSyW@$7{cE2?5+Mf#^ zaZ6@%?sMhYuDPd^w|w8rrPEpR0&Ap0Yl;up&40DVpi|m>+qNB>BVJq0`bM6{2a)=B9;a_S=gocS*^})bgD)N6%Zl%Lm+g1FJAO;O z-6!53Dgiu?c%yBaDz@r83Rj!4#Li-?S&`hY6xLkF^L%GG8y5u^~qEZ0yVEbMb%V+cqbLmI)~?|2N@^ZsYW3 zm1FI#izlp(@ykoPnXz1dLtVDm{u?KzO}??t{o@LbNps9A`eXj{&zPR&wNpA*{mb$` z3C?`xeNuNO)!V<`F!@w>#pCyk%#%MbDH(C5`j*rkT=;Y8Ld)ZyeUJC3TJU==UpIY) zXXJC2f42*ES)EI}Qgzzm$rE$mkyxj`d-bn=y4DM|37P5Nn z^XJiyIWFzo-cE4VLGQ zbexR1kpFLKXy3GDOj&!c%y>L6$!>Z~mF|t^y7fowcHjF~)lnysAg;#q!M3Vz_qEHM z?^XV>v`vUSYs`F-x9?L_$bsMuz5f}^)C4s-c6n^qN9Qvw&5paegeSy%=Df5w=x delta 1358 zcmbQQHeb!)^?wLp00KrJu6IaoT6=%WWbJ}-$;th)Tuo;=b(C5(B%Lx}lsvrI=`qnj z)+6Ta!{%E~+t(jEeV64K-;%GJ173K}x$JFJYIks5>y{0&ATxX)Krrj^D99!f4L|vt4hs5Q1 z&RZ)hOd7a6r~GRvj@n*__asi>o3bo zOqVvOXFOBBrCBSldu)cL;OCi(JT6oQ?dSDoFn?J@=wuzbzzg|fi1J2oZ_>I zGgup3WF#>^*|#O2e{Q7aWw)BrL$cy4Z!zMJrut3~hKFBSL1_pE2&Iulvs2zK>*>y0 zWp;`0u<@LCTEb>A>r)Pz@)vc6Y$+4hw3D{=h_JCSj7Z3RddEdBZ*xU}r!B+5^{P6G zr6LbXrd(sP&5mEaX{E6H>puuDIuGvYqcTI~1ng zvERXaXvd>i#okXx|Hsd;d0=+^+nTzGJTE>rsQ4w=e^NZ*X4$vq-Kzjch3-9y7p!Jo z&Aw_9A$Bz4rn3K0{W;Et*YkJ}m^`X9xmF|^w}E$q{vTGA)6MPSw?1l`DtO$!yuN-7 z-&6hXx!&u4s;qiqz5dgo2}c$@j6VOK*WFiKURB%l&_N5M@T0n0%~V?Z{+aWL3(B|b zVChzEj9|O->bPD$cg;`1mT8$6btXA{KH@S(Wt*Xca;0ojz?6Ec`|b%Er_U6~pK|-( z)YHzpbA>_kK5tdy@TP_7E2c|q_;fF;x87!9eZJVF<$eb|Gq$(Nm`hA*P%y6c%(W2i z-^x3sp-wwBG`C~RiC3R1AMKl=%Jxu6$2i<|+MY?i2YT{Fd;beG9T)6dx_8F|=7p;J zgzb$umqD+jhoh!6|P9ZFKq0f4kAO*)m^YL2F}=XZ;MVIafEeJwDd3 z{zSk7#kKYOvc4>Ad^V+=DSL55#HH(di;BNTAC>4Yj8@){}#v2u1D;cicx{x83Z{gds zGR6j%?Y<}+))QYl_4mbXk2ap~ktpBB<;E$dy!X|EhSzSN&ek`5d0*wU^ZDXmsc*AS ze0z76^P2hRZ3osyWCEmTz&wu?^a*?!cz!#AvqCMW>G8u1$4zSnrhxOfD>@&6G#V(=8HoGdBHX2m8 UuzJTgWv%A~6>=ajnORr{0M2}I_y7O^ diff --git a/test_fixtures/masp_proofs/D38C391DF4F1F69AB04682F0C1B78DD77AA5620AC08519F73AB740B5A44AFA65.bin b/test_fixtures/masp_proofs/D38C391DF4F1F69AB04682F0C1B78DD77AA5620AC08519F73AB740B5A44AFA65.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d9b720476074e63e2b18bb5dd3684488b8ebb83 GIT binary patch literal 5412 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 abitcT(F8(q*m(bUw*GmR{(J9l-#-924Hn-3 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/D5A372904527694939249FA0AAFBE1500FF70DC4F2365C83D9BB9015D3C28CE1.bin b/test_fixtures/masp_proofs/D5A372904527694939249FA0AAFBE1500FF70DC4F2365C83D9BB9015D3C28CE1.bin new file mode 100644 index 0000000000000000000000000000000000000000..9ba262b0f395cf26c1f7114e31617f887bdce89c GIT binary patch literal 2045 zcmaF;9|9N|7#MCZls76{9xWcpe2K?QbbsG6o#p1H|03(S{vG1Yo3!f$!^5wvKxGWE zSGS6)DLgZo&2n1G&E9%*AG?PSNSxs{&@7@1lIQvbwHHi*HG>F{W`>s!CW=eFoLxCJ z^Q6S9Y?K40hTCVQ>j)tTyjQ)(EGiE$a8XF52S?ZUUG zt7Xf&r+x!Dd=!k>5MToOoJ)PV+OpFBFF}C-O4f|TrcNCBi7`B9!R5{^h99!Y^QhD**$dU)M{m04P5G`h@t^VKCxorDQMg`6PE)cwLpb6>Wfpf{i`S_qQH(4sAwk_XH?~&qm>vKA ztMSqe_d?no3Wbh1ZI-uN%>MkSR@Jp4wlxKck2ZW;Hr>-LO=;%tZ%h5dlEi$p7*{GM zF4<)M+HB{d4An`cH;O_VRu)b2ihUEU=5kEGQ%15d&SJHerPz&cIo@-22ias81uJCn z);;L>=*QD=NA^IgESsBw$=R8^Usm0ATfVk(dOmOG+UY^>mmi$l|6DG3{RdH(`Tut( zxZ4I@ne`+pqVVae5_1pjkO}Xvy41!xYc$s+F-UBvb<^WBZw?bEkr&DSs#0I%$D*0y zGl$J+QsF#Pk7MqaCNO3`JhY=|x!az_=NPuDv|ODsVe9Kk>)gmQSCL zPEL3-ah6Zrfs}$H9zHztkBe(=G3m;@Z$5t~KRauL@^;(38|p(8@|PR^&wg0^Vb1UH z$pIceB~?a{LixPKIe;os>;~gR@?q4@67vP^m@IMQ{CHuUFSP?tL!~r zE1l)F=)B?K$JT2Mw<<)s{Cb;bw*JZsx6{&*cW$eFKcKh%$Xu2Khm8$u=gd=I91-#H zo{ZrwVU~|J{#&lz=C11PuG_+OWM^t${A-V2h9|BxbKGa$^kB+9mj(qtxz(#Wq95|z zTfWqMO~hO6pk@699=kp$TwW6@_v^&IoNi_-5tr!(m5Ka!KArip>A}hBRcZ|l&)=_d zozJf%yEJRbkw*3D+BdvVnytvQX7oRMCy}RhGk(@`zZzv%gA!BOmcKz*rFAGvrZ{Jp5c0cf1hhw*uMz>HJcRY zpPM|b^OTIo?U;zu1uxbmAIw?Lzw=9$H2dSq1$%e;n}={kt^K_In&oZo_-m`=E&wtCZ$SF`^Ip@Lu`Lov*)G`Rlf6CHUNJ`(ux28 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/DBE07FDEDBF79BBC814D3EB70E5A0AD04432D0D4BB8B2488EA5E836837B00394.bin b/test_fixtures/masp_proofs/DBE07FDEDBF79BBC814D3EB70E5A0AD04432D0D4BB8B2488EA5E836837B00394.bin new file mode 100644 index 0000000000000000000000000000000000000000..d39344547dbc331604dab3d6c2a89d96ee44b084 GIT binary patch literal 2045 zcmaF;9|9N|7#P++Jg{)Q+%Tg=Z$SSx!s2*;{Y!WB2d@i8H(gnnjdBIj1_H_JS#}W)K0=%<%HTL~*H?vn!{D zoMkZKaKH9|S19!9x4a3HpBdj*5;&1lw3T7wydS(~bIVr~>*9ld%QF`K&DvGiy4-7L z|1qI+Q5`QbethHU0KO8I{#y|8d)v^-Vx>0gqM!KoR{lPr|pyTs3Sx#%=|epJkn zJ*QXvxq6&ukx}^1I8oD-=TYxjrfhMuHmDFhp(wF7d}_S?QTMzl-?b+GGrs)f&?Whr zJKyK8J}0#Fxz>vtlC?7m*9*yMN_J-mM_j1P;?8UFI`t%qk%c8BsN3eo*6JOzm%tra z2OS^%cpC1=9%z+ib2BhGJ9GETs@rbM*H%u?=j~iOJ?Q=NgLC_z%LT9hAnG#z|Lz2L z+n_76o1VFD%cBH3S6>WlnXG*f)$ zuo+D%oM-BB%>B{?#>|I@b`&jl+q3u_!*-RHt5YUyoge(~SDww)dztem{&?H+>GRRa z2~Q@@@~JzJQgFn>hiCqAam_6zU77dI=kMfaXN^$aZo79weTYK-a-;v*4~sv{`5itv zASFJayEgS=Qa>d=XGp8GGAm+aKkfc^`~kuXl2)dmFIpe8+B;z2|GC zv%D6aH$42$g-DlQZ}ZI7UwPqnS~~L1ZME+Q^wuAl%W~kbv0?3;dFqQJB0k=e zF}x+r^3leB%hlW5RlVJHTeyzwOzn$*?eWX-#Fb`_`>dNDOxfqspx`IBdR0gCL%w^< zmzuAMc&i<>tiQlx*9V2mYeMCIo!FPt&1@y>opuk^j!8Ghd!>`IE3)-E8jRT?(_D=CyQV2E_!Pu=h5+7O7-Bm zjLM~q!3&+&dbKexPh6{kSOeaL$3+s9CSKy@)t?an80W`D@wN=zqMY_nW(W~@B0fMzj>(M{eSJg>XYr&dXG%Lb6>5D5>+X+ z%B}D6ytiVfc))|wm#T}zrX|NJovBZs;j_Hx!Vw$i(sCbe&S%qS7#upp^)~wR(l_iJ Oup${;wL&>8P#OTZ?AfLO literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/E1D883F9C9E7FD5C51D39AE1809BC3BBACE79DF98801EB8154EA1904597854A1.bin b/test_fixtures/masp_proofs/E1D883F9C9E7FD5C51D39AE1809BC3BBACE79DF98801EB8154EA1904597854A1.bin index a25fa32cf0c24c8d7437caad4c3549b2c087aa26..8cac916954e11697d45eb755016e7092e6fb521d 100644 GIT binary patch delta 1228 zcmajc{W}u~0KjouOhYm+3ERvPIaecMtt^z6Jua_}(#wU;Y%6cOHF4V-ze?t&b|=76jE2%2@ZUlwub=8LV66D?nbL!Vqe)(zgte}5i2#?sL>IBu)KssB%* zLD@jxde7vSx}+7j{;MJKrMR1+XZNnoeOildZt>)!SF5{$`g2(wHNP}Sc%VEkF zqsEzrHE9I+wpn?OhxmsD?($|NLN}>N5myGBT@gMN%npCO=Z!ilc+ekYi~N(g*i=ms ziZS5NK;KJw`K6KKMAf{TZ4I@c{B)-AUAUz%XuVN} zJZ~?1F#r5Sm{->#p9G?rL%GQ&o`|Zr1ZZa(ZcF|*`E>x`` zaKs7|1dz!`oh9gv?u`0+5v{HeJ?e)o@ptL~uZ;-dFUQ_Le&+_~-C)UzfwgpwZzMM@_F|qZEzX^0mgZSC@SWXZF;j z2A&heIQ`1OT&g8s442bG7>sr(&alp5iv5ig1}U6-PPCixwi0keh4RaIkpA`vfuH{O zOWIu@xYYJNRYv8sWY{6RrT>Ht8^b(3CX;Txa)*~0>Nh#b$YJl_`%w&n6s7-0W?Wx+ zt+TxK!tB*(y~vGueN)?du!pAGB7Uy9uWYT{Y(GEqP$c8HXXitood#+^4F=Y{U^lSf zT83jeyJFZL3Q^+c4oP}SYH4O7k@rR(mm$8-y7nM`-h9SB%eKkA{%10^f@y8(qbKdH zlwylw2dr#b1F7fDO4M5h8rKG8v0yCY%b0Rovjg{j2xyt)EYJdN*0hKmHY9UnU1^gd zFLR7>WgAF+90osQX_~me@mTP%>Mbe`2=B*U5N}8p@s+thA}#}BeT@YN(+>AWK4ZYD zZ_uG9=UCJvLQ*z-iRs*)7KLx($1Ph-GaSN-d97D&jz7$G_wr)&oO_vKj6$Yr7UBuf zHWq0`f3)oma*^=V;B234_1nM+{nlOEX~ANPcGHqKm|f%a2-T_+zD0$$1Zr1tN@KMr zM`2IeNG*szIC+96stWIEqRN%Gcjwv)uV!Q@osHZ?eaDzTHFZ>@Hht(i;$;->p&;TNA?KY>IB*hjG#MrG>CKkaI>XV(nGCk?g{Kvq zM@G1&?2LEmi$hkWB4fptk~v%z);q}>HkgtC1wYwmaI$Ed!Z?H&00Ma%`c6HX(r!>* z422#j2_jnkF0a^}rW#1wS8LK7!J966jJ8X6^m4jYnK#qn-vJp@$)?MuVrIdTmQ57X f{iL2Aes33)6hq>e5rKwsm delta 1228 zcmajc=|2+;0KoA%R>=%=q>wctS(I8l>XU_>4^Qr9q^IU+9~3hZ8e+{NW<{AOo3z|! zMa`L<+oMZpo@B+J0RKk2jE{yM;ZNtI;Rx(Ah(v9 z=urUIUph=TUJ9JyGbQvwfCo)tsz_0^W0lDU|~Z{r{BxrVM4I zp(*4x797dB@0d_~VdUb;Y3SBH^qeA?-271&$7E^X6g(}W!wZ3>vI8%Ns+OSkD%>jH zoLdQtrg+C4ytay>E^mQBoqS9pQmr-=qo362h_y!PL+MbR9a?JeUgV=q(t5p><)9{4 zMzVu4N$HH!c4xADeWT4dCPRAmK7Q$jSlCckL+y36P*&9OEcU$hq~gcn1zObbRfMBs zVnA#=)6G4F`WT+(LX86*f(9RYI!Ep_VVafZ3+7(xQ8cd~dmHwQ>?|ZeL2dH4t*jmp zRGIKnnh?O3ew?D<>ZKa7FIE1C`EO++|TdILGdhZgY)e^L;FDjra#=8B#udg2z?~#n_3HhX|`VN#J5;!xw@z zaM?4`g8xAe^m2Oy?VBj5(6?xpnf@5`Ue9ESTBB?!)v8KPHh?EEFbo`}ZJyo@s1Cau z&K;cQ8;mA;4>#O}kI-7L@)m8v*Cg^nEu&X25I`z)_Qn`RO#p00fd_gwODa-j()H7V z-7serTFp&sy&rAdwSwbk z+6Jyr+rOy-DPNAYl3OHo*hU6T+*kJ1MN=4U_$H(t<&J|s; z#s_0RS_t@%vZ@hKBzH($?OrUL!xr<~Ug)HV_^L~|S$%!P*`uq-5R0At>Jpj+vL|TI z>uk(VH@voLV!>L%u>Llqk6BYS$}1VCQ!`+Z#9qk$hMHZl#^yAgWP-Txp$yep*kVb$ fHeZ1h&>Yxkf5}n{c22{@`;Np?Z(50J3NiZ|PB~@= diff --git a/test_fixtures/masp_proofs/EF7D15FBFB9CC557CC8F9D4D18F7858007C4DA521F8E3BF250A46E9342178EEB.bin b/test_fixtures/masp_proofs/EF7D15FBFB9CC557CC8F9D4D18F7858007C4DA521F8E3BF250A46E9342178EEB.bin index e23e43bbb9a9fbbead67a8221989e232e624ca41..ab64d432336b662a53010693926fe9fa92455083 100644 GIT binary patch delta 1994 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 hF}onxMO^{OBt=>B Date: Sat, 27 Jan 2024 18:03:00 +0200 Subject: [PATCH 02/16] Added changelog entry. --- .changelog/unreleased/improvements/2458-masp-scanning.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/2458-masp-scanning.md diff --git a/.changelog/unreleased/improvements/2458-masp-scanning.md b/.changelog/unreleased/improvements/2458-masp-scanning.md new file mode 100644 index 0000000000..cafbd11a83 --- /dev/null +++ b/.changelog/unreleased/improvements/2458-masp-scanning.md @@ -0,0 +1,2 @@ +- Simplified the transaction fetching algorithm to enable it to be saved to + storage more frequently. ([\#2458](https://github.com/anoma/namada/pull/2458)) \ No newline at end of file From c76ca3fc8dc6eb26d126b3533245b8ad8a895095 Mon Sep 17 00:00:00 2001 From: satan Date: Tue, 30 Jan 2024 16:45:24 +0100 Subject: [PATCH 03/16] Moved fetch calls completely from other calls. Updated cli. Fixed tests --- Cargo.lock | 11 - crates/apps/src/lib/bench_utils.rs | 13 +- crates/apps/src/lib/cli.rs | 91 ++++++ crates/apps/src/lib/cli/client.rs | 35 ++ crates/apps/src/lib/client/masp.rs | 158 +++++++++ crates/apps/src/lib/client/mod.rs | 1 + crates/apps/src/lib/client/rpc.rs | 6 +- crates/core/src/types/masp.rs | 7 + crates/sdk/src/args.rs | 22 +- crates/sdk/src/masp.rs | 203 ++++++++++-- crates/tests/src/integration/masp.rs | 304 +++++++++++++++++- ...16D6748146469C7DF33C28DA6F65749E40AD45.bin | Bin 0 -> 10105 bytes wasm/checksums.json | 48 +-- 13 files changed, 808 insertions(+), 91 deletions(-) create mode 100644 crates/apps/src/lib/client/masp.rs create mode 100644 test_fixtures/masp_proofs/ACA50A646C6CEA7751373605BE16D6748146469C7DF33C28DA6F65749E40AD45.bin diff --git a/Cargo.lock b/Cargo.lock index ce8eed2b4f..7a6294c0d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3773,7 +3773,6 @@ dependencies = [ "glob", "libc", "libz-sys", - "tikv-jemalloc-sys", "zstd-sys", ] @@ -7340,16 +7339,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tikv-jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "time" version = "0.3.30" diff --git a/crates/apps/src/lib/bench_utils.rs b/crates/apps/src/lib/bench_utils.rs index ea9e463340..9391e4aabc 100644 --- a/crates/apps/src/lib/bench_utils.rs +++ b/crates/apps/src/lib/bench_utils.rs @@ -695,12 +695,9 @@ impl ShieldedUtils for BenchShieldedUtils { // Atomicity is required to prevent other client instances from reading // corrupt data. std::fs::rename( - tmp_path.clone(), + tmp_path, self.context_dir.0.path().to_path_buf().join(FILE_NAME), )?; - // Finally, remove our temporary file to allow future saving of shielded - // contexts. - std::fs::remove_file(tmp_path)?; Ok(()) } } @@ -983,9 +980,13 @@ impl BenchShieldedCtx { .wallet .find_spending_key(ALBERT_SPENDING_KEY, None) .unwrap(); - async_runtime - .block_on(self.shielded.fetch( + self.shielded = async_runtime + .block_on(crate::client::masp::syncing( + self.shielded, &self.shell, + &StdIo, + 1, + None, &[spending_key.into()], &[], )) diff --git a/crates/apps/src/lib/cli.rs b/crates/apps/src/lib/cli.rs index 8cb65ebcd5..8586eb4bb4 100644 --- a/crates/apps/src/lib/cli.rs +++ b/crates/apps/src/lib/cli.rs @@ -267,6 +267,7 @@ pub mod cmds { .subcommand(QueryMetaData::def().display_order(5)) // Actions .subcommand(SignTx::def().display_order(6)) + .subcommand(ShieldedSync::def().display_order(6)) .subcommand(GenIbcShieldedTransafer::def().display_order(6)) // Utils .subcommand(Utils::def().display_order(7)) @@ -346,6 +347,7 @@ pub mod cmds { let add_to_eth_bridge_pool = Self::parse_with_ctx(matches, AddToEthBridgePool); let sign_tx = Self::parse_with_ctx(matches, SignTx); + let shielded_sync = Self::parse_with_ctx(matches, ShieldedSync); let gen_ibc_shielded = Self::parse_with_ctx(matches, GenIbcShieldedTransafer); let utils = SubCmd::parse(matches).map(Self::WithoutContext); @@ -397,6 +399,7 @@ pub mod cmds { .or(query_metadata) .or(query_account) .or(sign_tx) + .or(shielded_sync) .or(gen_ibc_shielded) .or(utils) } @@ -483,6 +486,7 @@ pub mod cmds { QueryValidatorState(QueryValidatorState), QueryRewards(QueryRewards), SignTx(SignTx), + ShieldedSync(ShieldedSync), GenIbcShieldedTransafer(GenIbcShieldedTransafer), } @@ -1344,6 +1348,29 @@ pub mod cmds { } } + #[derive(Clone, Debug)] + pub struct ShieldedSync(pub args::ShieldedSync); + + impl SubCmd for ShieldedSync { + const CMD: &'static str = "shielded-sync"; + + fn parse(matches: &ArgMatches) -> Option { + matches + .subcommand_matches(Self::CMD) + .map(|matches| ShieldedSync(args::ShieldedSync::parse(matches))) + } + + fn def() -> App { + App::new(Self::CMD) + .about( + "Sync the local shielded context with MASP notes owned by \ + the provided viewing / spending keys up to an optional \ + specified block height.", + ) + .add_args::>() + } + } + #[derive(Clone, Debug)] pub struct Bond(pub args::Bond); @@ -2878,6 +2905,8 @@ pub mod args { Err(_) => config::get_default_namada_folder(), }), ); + pub const BATCH_SIZE_OPT: ArgDefault = + arg_default("batch-size", DefaultFn(|| 1)); pub const BLOCK_HEIGHT: Arg = arg("block-height"); pub const BLOCK_HEIGHT_OPT: ArgOpt = arg_opt("height"); pub const BRIDGE_POOL_GAS_AMOUNT: ArgDefault = @@ -3061,6 +3090,8 @@ pub mod args { pub const SIGNATURES: ArgMulti = arg_multi("signatures"); pub const SOURCE: Arg = arg("source"); pub const SOURCE_OPT: ArgOpt = SOURCE.opt(); + pub const SPENDING_KEYS: ArgMulti = + arg_multi("spending-keys"); pub const STEWARD: Arg = arg("steward"); pub const SOURCE_VALIDATOR: Arg = arg("source-validator"); pub const STORAGE_KEY: Arg = arg("storage-key"); @@ -3097,6 +3128,8 @@ pub mod args { pub const VALUE: Arg = arg("value"); pub const VOTER_OPT: ArgOpt = arg_opt("voter"); pub const VIEWING_KEY: Arg = arg("key"); + pub const VIEWING_KEYS: ArgMulti = + arg_multi("viewing-keys"); pub const VP: ArgOpt = arg_opt("vp"); pub const WALLET_ALIAS_FORCE: ArgFlag = flag("wallet-alias-force"); pub const WASM_CHECKSUMS_PATH: Arg = arg("wasm-checksums-path"); @@ -5608,6 +5641,63 @@ pub mod args { } } + impl Args for ShieldedSync { + fn parse(matches: &ArgMatches) -> Self { + let ledger_address = LEDGER_ADDRESS_DEFAULT.parse(matches); + let batch_size = BATCH_SIZE_OPT.parse(matches); + let last_query_height = BLOCK_HEIGHT_OPT.parse(matches); + let spending_keys = SPENDING_KEYS.parse(matches); + let viewing_keys = VIEWING_KEYS.parse(matches); + Self { + ledger_address, + batch_size, + last_query_height, + spending_keys, + viewing_keys, + } + } + + fn def(app: App) -> App { + app.arg(LEDGER_ADDRESS_DEFAULT.def().help(LEDGER_ADDRESS_ABOUT)) + .arg(BATCH_SIZE_OPT.def().help( + "Optional batch size which determines how many txs to \ + fetch before caching locally. Default is 1.", + )) + .arg(BLOCK_HEIGHT_OPT.def().help( + "Option block height to sync up to. Default is latest.", + )) + .arg(SPENDING_KEYS.def().help( + "List of new spending keys with which to check note \ + ownership. These will be added to the shielded context.", + )) + .arg(VIEWING_KEYS.def().help( + "List of new viewing keys with which to check note \ + ownership. These will be added to the shielded context.", + )) + } + } + + impl CliToSdk> for ShieldedSync { + fn to_sdk(self, ctx: &mut Context) -> ShieldedSync { + let chain_ctx = ctx.borrow_mut_chain_or_exit(); + ShieldedSync { + ledger_address: (), + batch_size: self.batch_size, + last_query_height: self.last_query_height, + spending_keys: self + .spending_keys + .iter() + .map(|sk| chain_ctx.get_cached(sk)) + .collect(), + viewing_keys: self + .viewing_keys + .iter() + .map(|vk| chain_ctx.get_cached(vk)) + .collect(), + } + } + } + impl CliToSdk> for GenIbcShieldedTransafer { @@ -5893,6 +5983,7 @@ pub mod args { type Keypair = WalletKeypair; type PublicKey = WalletPublicKey; type TendermintAddress = tendermint_config::net::Address; + type SpendingKey = WalletSpendingKey; type TransferSource = WalletTransferSource; type TransferTarget = WalletTransferTarget; type ViewingKey = WalletViewingKey; diff --git a/crates/apps/src/lib/cli/client.rs b/crates/apps/src/lib/cli/client.rs index b7f41dc6a2..3b6ac4bfe8 100644 --- a/crates/apps/src/lib/cli/client.rs +++ b/crates/apps/src/lib/cli/client.rs @@ -1,4 +1,5 @@ use color_eyre::eyre::Result; +use masp_primitives::zip32::ExtendedFullViewingKey; use namada::types::io::Io; use namada_sdk::{Namada, NamadaImpl}; @@ -315,6 +316,40 @@ impl CliApi { tx::submit_validator_metadata_change(&namada, args) .await?; } + Sub::ShieldedSync(ShieldedSync(mut args)) => { + let client = client.unwrap_or_else(|| { + C::from_tendermint_address(&mut args.ledger_address) + }); + client.wait_until_node_is_synced(&io).await?; + let args = args.to_sdk(&mut ctx); + let mut chain_ctx = ctx.take_chain_or_exit(); + let vks = chain_ctx + .wallet + .get_viewing_keys() + .values() + .copied() + .map(|vk| ExtendedFullViewingKey::from(vk).fvk.vk) + .chain(args.viewing_keys.into_iter().map(|vk| { + ExtendedFullViewingKey::from(vk).fvk.vk + })) + .collect::>(); + let sks = args + .spending_keys + .into_iter() + .map(|sk| sk.into()) + .collect::>(); + let _ = chain_ctx.shielded.load().await; + crate::client::masp::syncing( + chain_ctx.shielded, + &client, + &io, + args.batch_size, + args.last_query_height, + &sks, + &vks, + ) + .await?; + } // Eth bridge Sub::AddToEthBridgePool(args) => { let args = args.0; diff --git a/crates/apps/src/lib/client/masp.rs b/crates/apps/src/lib/client/masp.rs new file mode 100644 index 0000000000..a27b39a83d --- /dev/null +++ b/crates/apps/src/lib/client/masp.rs @@ -0,0 +1,158 @@ +use std::fmt::Debug; + +use color_eyre::owo_colors::OwoColorize; +use masp_primitives::sapling::ViewingKey; +use masp_primitives::transaction::Transaction; +use masp_primitives::zip32::ExtendedSpendingKey; +use namada::proof_of_stake::Epoch; +use namada::token::Transfer; +use namada::types::storage::IndexedTx; +use namada_sdk::error::Error; +use namada_sdk::io::Io; +use namada_sdk::masp::{ + ProgressLogger, ProgressType, ShieldedContext, ShieldedUtils, +}; +use namada_sdk::queries::Client; +use namada_sdk::types::storage::BlockHeight; +use namada_sdk::{display, display_line, MaybeSend, MaybeSync}; + +pub async fn syncing< + U: ShieldedUtils + MaybeSend + MaybeSync, + C: Client + Sync, + IO: Io, +>( + mut shielded: ShieldedContext, + client: &C, + io: &IO, + batch_size: u64, + last_query_height: Option, + sks: &[ExtendedSpendingKey], + fvks: &[ViewingKey], +) -> Result, Error> { + let shutdown_signal = async { + let (tx, rx) = tokio::sync::oneshot::channel(); + namada_sdk::control_flow::shutdown_send(tx).await; + rx.await + }; + + display_line!(io, "{}", "==== Shielded sync started ====".on_white()); + display_line!(io, "\n\n"); + let logger = CliLogger::new(io); + let sync = async move { + shielded + .fetch(client, &logger, last_query_height, batch_size, sks, fvks) + .await + .map(|_| shielded) + }; + tokio::select! { + sync = sync => { + let shielded = sync?; + display!(io, "Syncing finished\n"); + Ok(shielded) + }, + sig = shutdown_signal => { + sig.map_err(|e| Error::Other(e.to_string()))?; + display!(io, "\n"); + Ok(ShieldedContext::default()) + }, + } +} + +pub struct CliLogging<'io, T, IO: Io> { + items: Vec, + index: usize, + length: usize, + io: &'io IO, + r#type: ProgressType, +} + +impl<'io, T: Debug, IO: Io> CliLogging<'io, T, IO> { + fn new(items: I, io: &'io IO, r#type: ProgressType) -> Self + where + I: IntoIterator, + { + let items: Vec<_> = items.into_iter().collect(); + Self { + length: items.len(), + items, + index: 0, + io, + r#type, + } + } +} + +impl<'io, T: Debug, IO: Io> Iterator for CliLogging<'io, T, IO> { + type Item = T; + + fn next(&mut self) -> Option { + if self.index == 0 { + self.items = { + let mut new_items = vec![]; + std::mem::swap(&mut new_items, &mut self.items); + new_items.into_iter().rev().collect() + }; + } + if self.items.is_empty() { + return None; + } + self.index += 1; + let percent = (100 * self.index) / self.length; + let completed: String = vec!['#'; percent].iter().collect(); + let incomplete: String = vec!['.'; 100 - percent].iter().collect(); + display_line!(self.io, "\x1b[2A\x1b[J"); + match self.r#type { + ProgressType::Fetch => display_line!( + self.io, + "Fetched block {:?} of {:?}", + self.items.last().unwrap(), + self.items[0] + ), + ProgressType::Scan => display_line!( + self.io, + "Scanning {} of {}", + self.index, + self.length + ), + } + display!(self.io, "[{}{}] ~~ {} %", completed, incomplete, percent); + self.io.flush(); + self.items.pop() + } +} + +/// A progress logger for the CLI +#[derive(Debug, Clone)] +pub struct CliLogger<'io, IO: Io> { + io: &'io IO, +} + +impl<'io, IO: Io> CliLogger<'io, IO> { + pub fn new(io: &'io IO) -> Self { + Self { io } + } +} + +impl<'io, IO: Io> ProgressLogger for CliLogger<'io, IO> { + type Fetch = CliLogging<'io, u64, IO>; + type Scan = + CliLogging<'io, (IndexedTx, (Epoch, Transfer, Transaction)), IO>; + + fn io(&self) -> &IO { + self.io + } + + fn fetch(&self, items: I) -> Self::Fetch + where + I: IntoIterator, + { + CliLogging::new(items, self.io, ProgressType::Fetch) + } + + fn scan(&self, items: I) -> Self::Scan + where + I: IntoIterator, + { + CliLogging::new(items, self.io, ProgressType::Scan) + } +} diff --git a/crates/apps/src/lib/client/mod.rs b/crates/apps/src/lib/client/mod.rs index 8862c5a564..7ad6d57e5f 100644 --- a/crates/apps/src/lib/client/mod.rs +++ b/crates/apps/src/lib/client/mod.rs @@ -1,3 +1,4 @@ +pub mod masp; pub mod rpc; pub mod tx; pub mod utils; diff --git a/crates/apps/src/lib/client/rpc.rs b/crates/apps/src/lib/client/rpc.rs index cedc239b3f..5852af8400 100644 --- a/crates/apps/src/lib/client/rpc.rs +++ b/crates/apps/src/lib/client/rpc.rs @@ -137,6 +137,7 @@ pub async fn query_transfers( let transfers = shielded .query_tx_deltas( context.client(), + context.io(), &query_owner, &query_token, &wallet.get_viewing_keys(), @@ -878,11 +879,6 @@ pub async fn query_shielded_balance( { let mut shielded = context.shielded_mut().await; let _ = shielded.load().await; - let fvks: Vec<_> = viewing_keys - .iter() - .map(|fvk| ExtendedFullViewingKey::from(*fvk).fvk.vk) - .collect(); - shielded.fetch(context.client(), &[], &fvks).await.unwrap(); // Precompute asset types to increase chances of success in decoding let _ = shielded.precompute_asset_types(context).await; // Save the update state so that future fetches can be short-circuited diff --git a/crates/core/src/types/masp.rs b/crates/core/src/types/masp.rs index 61b63dab60..64b18eb6b9 100644 --- a/crates/core/src/types/masp.rs +++ b/crates/core/src/types/masp.rs @@ -202,6 +202,13 @@ impl From } } +impl From for masp_primitives::sapling::ViewingKey { + fn from(value: ExtendedViewingKey) -> Self { + let fvk = masp_primitives::zip32::ExtendedFullViewingKey::from(value); + fvk.fvk.vk + } +} + impl serde::Serialize for ExtendedViewingKey { fn serialize( &self, diff --git a/crates/sdk/src/args.rs b/crates/sdk/src/args.rs index e8d2cbcdd2..af3d0a584e 100644 --- a/crates/sdk/src/args.rs +++ b/crates/sdk/src/args.rs @@ -11,7 +11,7 @@ use namada_core::types::ethereum_events::EthAddress; use namada_core::types::keccak::KeccakHash; use namada_core::types::key::{common, SchemeType}; use namada_core::types::masp::PaymentAddress; -use namada_core::types::storage::Epoch; +use namada_core::types::storage::{BlockHeight, Epoch}; use namada_core::types::time::DateTimeUtc; use namada_core::types::{storage, token}; use namada_governance::cli::onchain::{ @@ -61,6 +61,8 @@ pub trait NamadaTypes: Clone + std::fmt::Debug { type EthereumAddress: Clone + std::fmt::Debug; /// Represents a viewing key type ViewingKey: Clone + std::fmt::Debug; + /// Represents a spending key + type SpendingKey: Clone + std::fmt::Debug; /// Represents the owner of a balance type BalanceOwner: Clone + std::fmt::Debug; /// Represents a public key @@ -101,6 +103,7 @@ impl NamadaTypes for SdkTypes { type Keypair = namada_core::types::key::common::SecretKey; type PublicKey = namada_core::types::key::common::PublicKey; type TendermintAddress = tendermint_config::net::Address; + type SpendingKey = namada_core::types::masp::ExtendedSpendingKey; type TransferSource = namada_core::types::masp::TransferSource; type TransferTarget = namada_core::types::masp::TransferTarget; type ViewingKey = namada_core::types::masp::ExtendedViewingKey; @@ -1806,6 +1809,23 @@ pub struct SignTx { pub owner: C::Address, } +#[derive(Clone, Debug)] +/// Sync notes from MASP owned by the provided spending / +/// viewing keys. Syncing can be told to stop at a given +/// block height. +pub struct ShieldedSync { + /// The ledger address + pub ledger_address: C::TendermintAddress, + /// The number of txs to fetch before caching + pub batch_size: u64, + /// Height to sync up to. Defaults to most recent + pub last_query_height: Option, + /// Spending keys used to determine note ownership + pub spending_keys: Vec, + /// Viewing keys used to determine note ownership + pub viewing_keys: Vec, +} + /// Query PoS commission rate #[derive(Clone, Debug)] pub struct QueryCommissionRate { diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 4e18ec7ecd..ddfd733a27 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -518,6 +518,61 @@ pub type TransferDelta = HashMap; /// Represents the changes that were made to a list of shielded accounts pub type TransactionDelta = HashMap; +#[derive(Debug, Clone)] +/// A marker type indicating that the shielded context is currently +/// syncing. +pub enum Syncing {} + +#[derive(Debug, Clone)] +/// A marker type indicating that the shielded context is not currently +/// syncing. +pub enum NotSyncing {} + +pub trait SyncStatus {} + +impl SyncStatus for NotSyncing {} + +impl SyncStatus for Syncing {} + +/// A cache of fetched indexed transactions. +/// +/// The cache is designed so that it either contains +/// all transactions from a given height, or none. +#[derive(BorshSerialize, BorshDeserialize, Debug, Default, Clone)] +pub struct Unscanned { + txs: BTreeMap, +} + +impl Unscanned { + fn extend(&mut self, items: I) + where + I: IntoIterator, + { + self.txs.extend(items.into_iter()); + } + + fn contains_height(&self, height: u64) -> bool { + self.txs.keys().any(|k| k.height.0 == height) + } + + /// We remove all indices from blocks that have been entirely scanned. + /// If a block is only partially scanned, we leave all the events in the + /// cache. + fn scanned(&mut self, ix: &IndexedTx) { + self.txs.retain(|i, _| i.height >= ix.height); + } +} + +impl IntoIterator for Unscanned { + type IntoIter = + btree_map::IntoIter; + type Item = (IndexedTx, (Epoch, Transfer, Transaction)); + + fn into_iter(self) -> Self::IntoIter { + self.txs.into_iter() + } +} + /// Represents the current state of the shielded pool from the perspective of /// the chosen viewing keys. #[derive(BorshSerialize, BorshDeserialize, Debug)] @@ -553,6 +608,8 @@ pub struct ShieldedContext { pub vk_map: HashMap, /// Maps a shielded tx to the index of its first output note. pub tx_note_map: BTreeMap, + /// A cache of fetched indexed txs. + pub unscanned: Unscanned, } /// Default implementation to ease construction of TxContexts. Derive cannot be @@ -574,6 +631,7 @@ impl Default for ShieldedContext { delta_map: BTreeMap::default(), asset_types: HashMap::default(), vk_map: HashMap::default(), + unscanned: Default::default(), } } } @@ -626,9 +684,12 @@ impl ShieldedContext { /// Fetch the current state of the multi-asset shielded pool into a /// ShieldedContext - pub async fn fetch( + pub async fn fetch( &mut self, client: &C, + logger: &impl ProgressLogger, + last_query_height: Option, + _batch_size: u64, sks: &[ExtendedSpendingKey], fvks: &[ViewingKey], ) -> Result<(), Error> { @@ -640,6 +701,10 @@ impl ShieldedContext { for vk in fvks { self.vk_heights.entry(*vk).or_default(); } + self.utils + .save(self) + .await + .map_err(|e| Error::Other(e.to_string()))?; let native_token = query_native_token(client).await?; // the latest block height which has been added to the witness Merkle // tree @@ -648,11 +713,27 @@ impl ShieldedContext { }; let last_witnessed_tx = self.tx_note_map.keys().max().cloned(); // get the bounds on the block heights to fetch - let start_idx = std::cmp::min(last_witnessed_tx, least_idx); + let start_idx = + std::cmp::min(last_witnessed_tx, least_idx).map(|ix| ix.height); // Load all transactions accepted until this point - let txs = Self::fetch_shielded_transfers(client, start_idx).await?; + // N.B. the cache is a hash map + self.unscanned.extend( + self.fetch_shielded_transfers( + client, + logger, + start_idx, + last_query_height, + ) + .await?, + ); + // persist the cache in case of interruptions. + self.utils + .save(self) + .await + .map_err(|e| Error::Other(e.to_string()))?; - for (indexed_tx, (epoch, tx, stx)) in txs.into_iter() { + let txs = logger.scan(self.unscanned.clone()); + for (indexed_tx, (epoch, tx, stx)) in txs { if Some(indexed_tx) > last_witnessed_tx { self.update_witness_map(indexed_tx, &stx)?; } @@ -665,7 +746,13 @@ impl ShieldedContext { self.scan_tx(indexed_tx, epoch, &tx, &stx, vk, native_token.clone())?; *h = Some(indexed_tx); } + // possibly remove unneeded elements from the cache. + self.unscanned.scanned(&indexed_tx); std::mem::swap(&mut vk_heights, &mut self.vk_heights); + self.utils + .save(self) + .await + .map_err(|e| Error::Other(e.to_string()))?; } Ok(()) @@ -673,9 +760,12 @@ impl ShieldedContext { /// Obtain a chronologically-ordered list of all accepted shielded /// transactions from a node. - pub async fn fetch_shielded_transfers( + pub async fn fetch_shielded_transfers( + &self, client: &C, - last_indexed_tx: Option, + logger: &impl ProgressLogger, + last_indexed_tx: Option, + last_query_height: Option, ) -> Result< BTreeMap< IndexedTx, @@ -691,14 +781,17 @@ impl ShieldedContext { let last_block_height = query_block(client) .await? .map_or_else(BlockHeight::first, |block| block.height); + let last_query_height = last_query_height.unwrap_or(last_block_height); let mut shielded_txs = BTreeMap::new(); // Fetch all the transactions we do not have yet let first_height_to_query = - last_indexed_tx.map_or_else(|| 1, |last| last.height.0); - let first_idx_to_query = - last_indexed_tx.map_or_else(|| 0, |last| last.index.0 + 1); - for height in first_height_to_query..=last_block_height.0 { + last_indexed_tx.map_or_else(|| 1, |last| last.0); + let heights = logger.fetch(first_height_to_query..=last_query_height.0); + for height in heights { + if self.unscanned.contains_height(height) { + continue; + } // Get the valid masp transactions at the specified height let epoch = query_epoch_at_height(client, height.into()) .await? @@ -710,16 +803,10 @@ impl ShieldedContext { )) })?; - let first_index_to_query = if height == first_height_to_query { - Some(TxIndex(first_idx_to_query)) - } else { - None - }; - let txs_results = match get_indexed_masp_events_at_height( client, height.into(), - first_index_to_query, + None, ) .await? { @@ -1837,18 +1924,11 @@ impl ShieldedContext { } // We want to fund our transaction solely from supplied spending key let spending_key = spending_key.map(|x| x.into()); - let spending_keys: Vec<_> = spending_key.into_iter().collect(); { // Load the current shielded context given the spending key we // possess let mut shielded = context.shielded_mut().await; let _ = shielded.load().await; - shielded - .fetch(context.client(), &spending_keys, &[]) - .await?; - // Save the update state so that future fetches can be - // short-circuited - let _ = shielded.save().await; } // Determine epoch in which to submit potential shielded transaction let epoch = rpc::query_epoch(context.client()).await?; @@ -2278,9 +2358,10 @@ impl ShieldedContext { /// transactions. If an owner is specified, then restrict the set to only /// transactions crediting/debiting the given owner. If token is specified, /// then restrict set to only transactions involving the given token. - pub async fn query_tx_deltas( + pub async fn query_tx_deltas( &mut self, client: &C, + io: &IO, query_owner: &Either>, query_token: &Option
, viewing_keys: &HashMap, @@ -2295,7 +2376,8 @@ impl ShieldedContext { .values() .map(|fvk| ExtendedFullViewingKey::from(*fvk).fvk.vk) .collect(); - self.fetch(client, &[], &fvks).await?; + self.fetch(client, &DefaultLogger::new(io), None, 1, &[], &fvks) + .await?; // Save the update state so that future fetches can be short-circuited let _ = self.save().await; // Required for filtering out rejected transactions from Tendermint @@ -3583,14 +3665,67 @@ pub mod fs { // Atomically update the old shielded context file with new data. // Atomicity is required to prevent other client instances from // reading corrupt data. - std::fs::rename( - tmp_path.clone(), - self.context_dir.join(FILE_NAME), - )?; - // Finally, remove our temporary file to allow future saving of - // shielded contexts. - std::fs::remove_file(tmp_path)?; - Ok(()) + std::fs::rename(tmp_path, self.context_dir.join(FILE_NAME)) } } } + +/// A enum to indicate how to log sync progress depending on +/// whether sync is currently fetch or scanning blocks. +#[derive(Debug, Copy, Clone)] +pub enum ProgressType { + Fetch, + Scan, +} + +pub trait ProgressLogger { + type Fetch: Iterator; + type Scan: Iterator; + + fn io(&self) -> &IO; + + fn fetch(&self, items: I) -> Self::Fetch + where + I: IntoIterator; + + fn scan(&self, items: I) -> Self::Scan + where + I: IntoIterator; +} + +/// The default type for logging sync progress. +#[derive(Debug, Clone)] +pub struct DefaultLogger<'io, IO: Io> { + io: &'io IO, +} + +impl<'io, IO: Io> DefaultLogger<'io, IO> { + pub fn new(io: &'io IO) -> Self { + Self { io } + } +} + +impl<'io, IO: Io> ProgressLogger for DefaultLogger<'io, IO> { + type Fetch = as IntoIterator>::IntoIter; + type Scan = as IntoIterator>::IntoIter; + + fn io(&self) -> &IO { + self.io + } + + fn fetch(&self, items: I) -> Self::Fetch + where + I: IntoIterator, + { + let items: Vec<_> = items.into_iter().collect(); + items.into_iter() + } + + fn scan(&self, items: I) -> Self::Scan + where + I: IntoIterator, + { + let items: Vec<_> = items.into_iter().collect(); + items.into_iter() + } +} diff --git a/crates/tests/src/integration/masp.rs b/crates/tests/src/integration/masp.rs index deef3c1061..527dab7e08 100644 --- a/crates/tests/src/integration/masp.rs +++ b/crates/tests/src/integration/masp.rs @@ -54,6 +54,21 @@ fn masp_incentives() -> Result<()> { )?; node.assert_success(); + // sync the shielded context + run( + &node, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + AB_VIEWING_KEY, + "--node", + validator_one_rpc, + ], + )?; + node.assert_success(); + // Assert BTC balance at VK(A) is 1 let captured = CapturedOutput::of(|| { run( @@ -95,6 +110,14 @@ fn masp_incentives() -> Result<()> { // Wait till epoch boundary node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert BTC balance at VK(A) is still 1 let captured = CapturedOutput::of(|| { run( @@ -157,6 +180,14 @@ fn masp_incentives() -> Result<()> { // Wait till epoch boundary node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert BTC balance at VK(A) is still 1 let captured = CapturedOutput::of(|| { run( @@ -239,6 +270,14 @@ fn masp_incentives() -> Result<()> { )?; node.assert_success(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert ETH balance at VK(B) is 0.001 let captured = CapturedOutput::of(|| { run( @@ -280,6 +319,14 @@ fn masp_incentives() -> Result<()> { // Wait till epoch boundary node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert ETH balance at VK(B) is still 0.001 let captured = CapturedOutput::of(|| { run( @@ -341,7 +388,6 @@ fn masp_incentives() -> Result<()> { // Wait till epoch boundary node.next_epoch(); - // Send 0.001 ETH from SK(B) to Christel run( &node, @@ -364,6 +410,14 @@ fn masp_incentives() -> Result<()> { )?; node.assert_success(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert ETH balance at VK(B) is 0 let captured = CapturedOutput::of(|| { run( @@ -384,6 +438,13 @@ fn masp_incentives() -> Result<()> { assert!(captured.contains("No shielded eth balance found")); node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert VK(B) retains the NAM rewards dispensed in the correct // amount. @@ -406,6 +467,13 @@ fn masp_incentives() -> Result<()> { assert!(captured.contains("nam: 0.719514")); node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert NAM balance at MASP pool is // the accumulation of rewards from the shielded assets (BTC and ETH) @@ -452,6 +520,14 @@ fn masp_incentives() -> Result<()> { )?; node.assert_success(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert BTC balance at VK(A) is 0 let captured = CapturedOutput::of(|| { run( @@ -512,6 +588,13 @@ fn masp_incentives() -> Result<()> { // Wait till epoch boundary node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert NAM balance at VK(A) is the rewards dispensed earlier // (since VK(A) has no shielded assets, no further rewards should @@ -578,7 +661,13 @@ fn masp_incentives() -> Result<()> { // Wait till epoch boundary to prevent conversion expiry during transaction // construction node.next_epoch(); - + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Send all NAM rewards from SK(B) to Christel run( &node, @@ -603,7 +692,13 @@ fn masp_incentives() -> Result<()> { // Wait till epoch boundary node.next_epoch(); - + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Send all NAM rewards from SK(A) to Bertha run( &node, @@ -626,6 +721,14 @@ fn masp_incentives() -> Result<()> { )?; node.assert_success(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert NAM balance at VK(A) is 0 let captured = CapturedOutput::of(|| { run( @@ -645,6 +748,13 @@ fn masp_incentives() -> Result<()> { assert!(captured.result.is_ok()); assert!(captured.contains("No shielded nam balance found")); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert NAM balance at VK(B) is 0 let captured = CapturedOutput::of(|| { run( @@ -750,7 +860,20 @@ fn spend_unconverted_asset_type() -> Result<()> { for _ in 0..5 { node.next_epoch(); } - + // sync the shielded context + run( + &node, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + AB_VIEWING_KEY, + "--node", + validator_one_rpc, + ], + )?; + node.assert_success(); // 4. Check the shielded balance let captured = CapturedOutput::of(|| { run( @@ -812,6 +935,20 @@ fn masp_pinned_txs() -> Result<()> { // Wait till epoch boundary let _ep0 = node.next_epoch(); + // sync shielded context + run( + &node, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AC_VIEWING_KEY, + "--node", + validator_one_rpc, + ], + )?; + node.assert_success(); + // Assert PPA(C) cannot be recognized by incorrect viewing key let captured = CapturedOutput::with_input(AB_VIEWING_KEY.into()).run(|| { @@ -881,6 +1018,14 @@ fn masp_pinned_txs() -> Result<()> { // This makes it more consistent for some reason? let _ep2 = node.next_epoch(); + // sync shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert PPA(C) has the 20 BTC transaction pinned to it let captured = CapturedOutput::with_input(AC_VIEWING_KEY.into()).run(|| { @@ -924,6 +1069,14 @@ fn masp_pinned_txs() -> Result<()> { // Wait till epoch boundary let _ep1 = node.next_epoch(); + // sync shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // Assert PPA(C) does not NAM pinned to it on epoch boundary let captured = CapturedOutput::with_input(AC_VIEWING_KEY.into()).run(|| { @@ -978,6 +1131,22 @@ fn masp_txs_and_queries() -> Result<()> { let (mut node, _services) = setup::setup()?; _ = node.next_epoch(); + + // add necessary viewing keys to shielded context + run( + &node, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + AB_VIEWING_KEY, + "--node", + validator_one_rpc, + ], + )?; + node.assert_success(); + let txs_args = vec![ // 0. Attempt to spend 10 BTC at SK(A) to PA(B) ( @@ -1188,11 +1357,22 @@ fn masp_txs_and_queries() -> Result<()> { ]; for (tx_args, tx_result) in &txs_args { - // We ensure transfers don't cross epoch boundaries. - if tx_args[0] == "transfer" { + // sync shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // there is no need to dry run balance queries + let dry_run_args = if tx_args[0] == "transfer" { + // We ensure transfers don't cross epoch boundaries. node.next_epoch(); - } - for &dry_run in &[true, false] { + vec![true, false] + } else { + vec![false] + }; + for &dry_run in &dry_run_args { let tx_args = if dry_run && tx_args[0] == "transfer" { vec![tx_args.clone(), vec!["--dry-run"]].concat() } else { @@ -1304,6 +1484,21 @@ fn wrapper_fee_unshielding() -> Result<()> { node.assert_success(); _ = node.next_epoch(); + // sync shielded context + run( + &node, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + AB_VIEWING_KEY, + "--node", + validator_one_rpc, + ], + )?; + node.assert_success(); + // 2. Valid unshielding run( &node, @@ -1328,6 +1523,14 @@ fn wrapper_fee_unshielding() -> Result<()> { )?; node.assert_success(); + // sync shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); + // 3. Invalid unshielding let tx_args = vec![ "transfer", @@ -1393,6 +1596,20 @@ fn cross_epoch_tx() -> Result<()> { )?; node.assert_success(); + // sync the shielded context + run( + &node, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + "--node", + validator_one_rpc, + ], + )?; + node.assert_success(); + // 2. Generate the tx in the current epoch let tempdir = tempfile::tempdir().unwrap(); run( @@ -1471,6 +1688,19 @@ fn dynamic_assets() -> Result<()> { storage.conversion_state.tokens.retain(|k, _v| *k == nam); tokens }; + // add necessary viewing keys to shielded context + run( + &node, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + "--node", + validator_one_rpc, + ], + )?; + node.assert_success(); // Wait till epoch boundary node.next_epoch(); // Send 1 BTC from Albert to PA @@ -1492,6 +1722,13 @@ fn dynamic_assets() -> Result<()> { ], )?; node.assert_success(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert BTC balance at VK(A) is 1 let captured = CapturedOutput::of(|| { @@ -1543,6 +1780,13 @@ fn dynamic_assets() -> Result<()> { // Wait till epoch boundary node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert BTC balance at VK(A) is still 1 let captured = CapturedOutput::of(|| { @@ -1602,6 +1846,13 @@ fn dynamic_assets() -> Result<()> { ], )?; node.assert_success(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert BTC balance at VK(A) is now 2 let captured = CapturedOutput::of(|| { @@ -1643,6 +1894,13 @@ fn dynamic_assets() -> Result<()> { // Wait till epoch boundary node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert that VK(A) has now received a NAM rewward for second deposit let captured = CapturedOutput::of(|| { @@ -1695,6 +1953,13 @@ fn dynamic_assets() -> Result<()> { // Wait till epoch boundary node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert BTC balance at VK(A) is still 2 let captured = CapturedOutput::of(|| { @@ -1742,6 +2007,13 @@ fn dynamic_assets() -> Result<()> { // Wait till epoch boundary node.next_epoch(); + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert BTC balance at VK(A) is still 2 let captured = CapturedOutput::of(|| { @@ -1783,7 +2055,13 @@ fn dynamic_assets() -> Result<()> { // Wait till epoch boundary node.next_epoch(); - + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert BTC balance at VK(A) is still 2 let captured = CapturedOutput::of(|| { run( @@ -1835,7 +2113,13 @@ fn dynamic_assets() -> Result<()> { // Wait till epoch boundary node.next_epoch(); - + // sync the shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); // Assert BTC balance at VK(A) is still 2 let captured = CapturedOutput::of(|| { run( diff --git a/test_fixtures/masp_proofs/ACA50A646C6CEA7751373605BE16D6748146469C7DF33C28DA6F65749E40AD45.bin b/test_fixtures/masp_proofs/ACA50A646C6CEA7751373605BE16D6748146469C7DF33C28DA6F65749E40AD45.bin new file mode 100644 index 0000000000000000000000000000000000000000..92b0befd053c882b89b6f6906806e95489603364 GIT binary patch literal 10105 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 Date: Tue, 30 Jan 2024 18:11:02 +0100 Subject: [PATCH 04/16] [fix] Some e2e test fixes --- crates/tests/src/e2e/ibc_tests.rs | 21 ++++++++++++++++++++- crates/tests/src/e2e/ledger_tests.rs | 13 +++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs index 4cd825b8c8..21bac52f3d 100644 --- a/crates/tests/src/e2e/ibc_tests.rs +++ b/crates/tests/src/e2e/ibc_tests.rs @@ -1130,7 +1130,7 @@ fn transfer_on_chain( "--node", &rpc, ]; - let mut client = run!(test, Bin::Client, tx_args, Some(40))?; + let mut client = run!(test, Bin::Client, tx_args, Some(120))?; client.exp_string(TX_ACCEPTED)?; client.exp_string(TX_APPLIED_SUCCESS)?; client.assert_success(); @@ -1297,6 +1297,16 @@ fn shielded_transfer( // Send a token to the shielded address on Chain A transfer_on_chain(test_a, ALBERT, AA_PAYMENT_ADDRESS, BTC, 10, ALBERT_KEY)?; + let rpc = get_actor_rpc(test_a, Who::Validator(0)); + let tx_args = vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + "--node", + &rpc, + ]; + let mut client = run!(test_a, Bin::Client, tx_args, Some(120))?; + client.assert_success(); // Send a token from SP(A) on Chain A to PA(B) on Chain B let amount = Amount::native_whole(10).to_string_native(); @@ -1899,6 +1909,15 @@ fn check_shielded_balances( let token_addr = find_address(test_a, BTC)?.to_string(); std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); + let tx_args = vec![ + "shielded-sync", + "--viewing-keys", + AB_VIEWING_KEY, + "--node", + &rpc_b, + ]; + let mut client = run!(test_b, Bin::Client, tx_args, Some(120))?; + client.assert_success(); let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/btc"); let query_args = vec![ "balance", diff --git a/crates/tests/src/e2e/ledger_tests.rs b/crates/tests/src/e2e/ledger_tests.rs index 9c904e095c..48daa1bc71 100644 --- a/crates/tests/src/e2e/ledger_tests.rs +++ b/crates/tests/src/e2e/ledger_tests.rs @@ -739,6 +739,16 @@ fn wrapper_disposable_signer() -> Result<()> { client.exp_string(TX_APPLIED_SUCCESS)?; let _ep1 = epoch_sleep(&test, &validator_one_rpc, 720)?; + let tx_args = vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + "--node", + &validator_one_rpc, + ]; + let mut client = run!(test, Bin::Client, tx_args, Some(120))?; + client.assert_success(); + let tx_args = vec![ "transfer", "--source", @@ -760,6 +770,9 @@ fn wrapper_disposable_signer() -> Result<()> { client.exp_string(TX_ACCEPTED)?; client.exp_string(TX_APPLIED_SUCCESS)?; let _ep1 = epoch_sleep(&test, &validator_one_rpc, 720)?; + let tx_args = vec!["shielded-sync", "--node", &validator_one_rpc]; + let mut client = run!(test, Bin::Client, tx_args, Some(120))?; + client.assert_success(); let tx_args = vec![ "transfer", "--source", From 63921d9783e7786dad275225b80574b301617fd6 Mon Sep 17 00:00:00 2001 From: satan Date: Wed, 31 Jan 2024 10:55:06 +0100 Subject: [PATCH 05/16] [chore] Rebase on main --- Cargo.lock | 11 ++++++ crates/apps/src/lib/cli.rs | 8 ++--- crates/apps/src/lib/cli/client.rs | 4 +-- crates/apps/src/lib/client/masp.rs | 12 +++---- crates/sdk/src/args.rs | 2 +- crates/sdk/src/masp.rs | 58 +++++++++++++++++++----------- 6 files changed, 59 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7a6294c0d8..ce8eed2b4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3773,6 +3773,7 @@ dependencies = [ "glob", "libc", "libz-sys", + "tikv-jemalloc-sys", "zstd-sys", ] @@ -7339,6 +7340,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tikv-jemalloc-sys" +version = "0.5.4+5.3.0-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "time" version = "0.3.30" diff --git a/crates/apps/src/lib/cli.rs b/crates/apps/src/lib/cli.rs index 8586eb4bb4..716b072eb7 100644 --- a/crates/apps/src/lib/cli.rs +++ b/crates/apps/src/lib/cli.rs @@ -5643,7 +5643,7 @@ pub mod args { impl Args for ShieldedSync { fn parse(matches: &ArgMatches) -> Self { - let ledger_address = LEDGER_ADDRESS_DEFAULT.parse(matches); + let ledger_address = LEDGER_ADDRESS.parse(matches); let batch_size = BATCH_SIZE_OPT.parse(matches); let last_query_height = BLOCK_HEIGHT_OPT.parse(matches); let spending_keys = SPENDING_KEYS.parse(matches); @@ -5658,7 +5658,7 @@ pub mod args { } fn def(app: App) -> App { - app.arg(LEDGER_ADDRESS_DEFAULT.def().help(LEDGER_ADDRESS_ABOUT)) + app.arg(LEDGER_ADDRESS.def().help(LEDGER_ADDRESS_ABOUT)) .arg(BATCH_SIZE_OPT.def().help( "Optional batch size which determines how many txs to \ fetch before caching locally. Default is 1.", @@ -5681,7 +5681,7 @@ pub mod args { fn to_sdk(self, ctx: &mut Context) -> ShieldedSync { let chain_ctx = ctx.borrow_mut_chain_or_exit(); ShieldedSync { - ledger_address: (), + ledger_address: self.ledger_address, batch_size: self.batch_size, last_query_height: self.last_query_height, spending_keys: self @@ -5982,8 +5982,8 @@ pub mod args { type EthereumAddress = String; type Keypair = WalletKeypair; type PublicKey = WalletPublicKey; - type TendermintAddress = tendermint_config::net::Address; type SpendingKey = WalletSpendingKey; + type TendermintAddress = tendermint_config::net::Address; type TransferSource = WalletTransferSource; type TransferTarget = WalletTransferTarget; type ViewingKey = WalletViewingKey; diff --git a/crates/apps/src/lib/cli/client.rs b/crates/apps/src/lib/cli/client.rs index 3b6ac4bfe8..d40b529b22 100644 --- a/crates/apps/src/lib/cli/client.rs +++ b/crates/apps/src/lib/cli/client.rs @@ -316,9 +316,9 @@ impl CliApi { tx::submit_validator_metadata_change(&namada, args) .await?; } - Sub::ShieldedSync(ShieldedSync(mut args)) => { + Sub::ShieldedSync(ShieldedSync(args)) => { let client = client.unwrap_or_else(|| { - C::from_tendermint_address(&mut args.ledger_address) + C::from_tendermint_address(&args.ledger_address) }); client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); diff --git a/crates/apps/src/lib/client/masp.rs b/crates/apps/src/lib/client/masp.rs index a27b39a83d..ad23a104c5 100644 --- a/crates/apps/src/lib/client/masp.rs +++ b/crates/apps/src/lib/client/masp.rs @@ -2,15 +2,12 @@ use std::fmt::Debug; use color_eyre::owo_colors::OwoColorize; use masp_primitives::sapling::ViewingKey; -use masp_primitives::transaction::Transaction; use masp_primitives::zip32::ExtendedSpendingKey; -use namada::proof_of_stake::Epoch; -use namada::token::Transfer; -use namada::types::storage::IndexedTx; use namada_sdk::error::Error; use namada_sdk::io::Io; use namada_sdk::masp::{ - ProgressLogger, ProgressType, ShieldedContext, ShieldedUtils, + IndexedNoteEntry, ProgressLogger, ProgressType, ShieldedContext, + ShieldedUtils, }; use namada_sdk::queries::Client; use namada_sdk::types::storage::BlockHeight; @@ -135,8 +132,7 @@ impl<'io, IO: Io> CliLogger<'io, IO> { impl<'io, IO: Io> ProgressLogger for CliLogger<'io, IO> { type Fetch = CliLogging<'io, u64, IO>; - type Scan = - CliLogging<'io, (IndexedTx, (Epoch, Transfer, Transaction)), IO>; + type Scan = CliLogging<'io, IndexedNoteEntry, IO>; fn io(&self) -> &IO { self.io @@ -151,7 +147,7 @@ impl<'io, IO: Io> ProgressLogger for CliLogger<'io, IO> { fn scan(&self, items: I) -> Self::Scan where - I: IntoIterator, + I: IntoIterator, { CliLogging::new(items, self.io, ProgressType::Scan) } diff --git a/crates/sdk/src/args.rs b/crates/sdk/src/args.rs index af3d0a584e..8ab98d3254 100644 --- a/crates/sdk/src/args.rs +++ b/crates/sdk/src/args.rs @@ -102,8 +102,8 @@ impl NamadaTypes for SdkTypes { type EthereumAddress = (); type Keypair = namada_core::types::key::common::SecretKey; type PublicKey = namada_core::types::key::common::PublicKey; - type TendermintAddress = tendermint_config::net::Address; type SpendingKey = namada_core::types::masp::ExtendedSpendingKey; + type TendermintAddress = tendermint_config::net::Address; type TransferSource = namada_core::types::masp::TransferSource; type TransferTarget = namada_core::types::masp::TransferTarget; type ViewingKey = namada_core::types::masp::ExtendedViewingKey; diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index ddfd733a27..6761f3de14 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -113,6 +113,26 @@ pub const OUTPUT_NAME: &str = "masp-output.params"; /// Convert circuit name pub const CONVERT_NAME: &str = "masp-convert.params"; +/// Type alias for convenience and profit +pub type IndexedNoteData = BTreeMap< + IndexedTx, + ( + Epoch, + BTreeSet, + Transaction, + ), +>; + +/// Type alias for the entries of [`IndexedNoteData`] iterators +pub type IndexedNoteEntry = ( + IndexedTx, + ( + Epoch, + BTreeSet, + Transaction, + ), +); + /// Shielded transfer #[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] pub struct ShieldedTransfer { @@ -540,13 +560,13 @@ impl SyncStatus for Syncing {} /// all transactions from a given height, or none. #[derive(BorshSerialize, BorshDeserialize, Debug, Default, Clone)] pub struct Unscanned { - txs: BTreeMap, + txs: IndexedNoteData, } impl Unscanned { fn extend(&mut self, items: I) where - I: IntoIterator, + I: IntoIterator, { self.txs.extend(items.into_iter()); } @@ -564,9 +584,8 @@ impl Unscanned { } impl IntoIterator for Unscanned { - type IntoIter = - btree_map::IntoIter; - type Item = (IndexedTx, (Epoch, Transfer, Transaction)); + type IntoIter = ::IntoIter; + type Item = IndexedNoteEntry; fn into_iter(self) -> Self::IntoIter { self.txs.into_iter() @@ -743,7 +762,14 @@ impl ShieldedContext { .iter_mut() .filter(|(_vk, h)| **h < Some(indexed_tx)) { - self.scan_tx(indexed_tx, epoch, &tx, &stx, vk, native_token.clone())?; + self.scan_tx( + indexed_tx, + epoch, + &tx, + &stx, + vk, + native_token.clone(), + )?; *h = Some(indexed_tx); } // possibly remove unneeded elements from the cache. @@ -766,17 +792,7 @@ impl ShieldedContext { logger: &impl ProgressLogger, last_indexed_tx: Option, last_query_height: Option, - ) -> Result< - BTreeMap< - IndexedTx, - ( - Epoch, - BTreeSet, - Transaction, - ), - >, - Error, - > { + ) -> Result { // Query for the last produced block height let last_block_height = query_block(client) .await? @@ -3680,7 +3696,7 @@ pub enum ProgressType { pub trait ProgressLogger { type Fetch: Iterator; - type Scan: Iterator; + type Scan: Iterator; fn io(&self) -> &IO; @@ -3690,7 +3706,7 @@ pub trait ProgressLogger { fn scan(&self, items: I) -> Self::Scan where - I: IntoIterator; + I: IntoIterator; } /// The default type for logging sync progress. @@ -3707,7 +3723,7 @@ impl<'io, IO: Io> DefaultLogger<'io, IO> { impl<'io, IO: Io> ProgressLogger for DefaultLogger<'io, IO> { type Fetch = as IntoIterator>::IntoIter; - type Scan = as IntoIterator>::IntoIter; + type Scan = as IntoIterator>::IntoIter; fn io(&self) -> &IO { self.io @@ -3723,7 +3739,7 @@ impl<'io, IO: Io> ProgressLogger for DefaultLogger<'io, IO> { fn scan(&self, items: I) -> Self::Scan where - I: IntoIterator, + I: IntoIterator, { let items: Vec<_> = items.into_iter().collect(); items.into_iter() From 6e55d353ee477606b185b054e929e6315b3142a8 Mon Sep 17 00:00:00 2001 From: satan Date: Wed, 31 Jan 2024 12:19:01 +0100 Subject: [PATCH 06/16] I don't know --- Makefile | 2 +- crates/namada/src/ledger/native_vp/masp.rs | 1 - crates/sdk/src/masp.rs | 17 -------- wasm/checksums.json | 48 +++++++++++----------- 4 files changed, 25 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index 3dc399433d..bd85b444d4 100644 --- a/Makefile +++ b/Makefile @@ -193,7 +193,7 @@ test-integration-save-proofs: # Run integration tests without specifying any pre-built MASP proofs option test-integration-slow: RUST_BACKTRACE=$(RUST_BACKTRACE) \ - $(cargo) +$(nightly) test integration::$(TEST_FILTER) --features integration \ + $(cargo) +$(nightly) test $(jobs) integration::$(TEST_FILTER) --features integration \ -Z unstable-options \ -- \ --test-threads=1 \ diff --git a/crates/namada/src/ledger/native_vp/masp.rs b/crates/namada/src/ledger/native_vp/masp.rs index b222aeaf9b..7c3f3dee5c 100644 --- a/crates/namada/src/ledger/native_vp/masp.rs +++ b/crates/namada/src/ledger/native_vp/masp.rs @@ -578,7 +578,6 @@ where return Ok(false); } } - if !(self.valid_spend_descriptions_anchor(&shielded_tx)? && self.valid_convert_descriptions_anchor(&shielded_tx)? && self.valid_nullifiers_reveal(keys_changed, &shielded_tx)?) diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 6761f3de14..4406a514cd 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -537,23 +537,6 @@ pub type TransferDelta = HashMap; /// Represents the changes that were made to a list of shielded accounts pub type TransactionDelta = HashMap; - -#[derive(Debug, Clone)] -/// A marker type indicating that the shielded context is currently -/// syncing. -pub enum Syncing {} - -#[derive(Debug, Clone)] -/// A marker type indicating that the shielded context is not currently -/// syncing. -pub enum NotSyncing {} - -pub trait SyncStatus {} - -impl SyncStatus for NotSyncing {} - -impl SyncStatus for Syncing {} - /// A cache of fetched indexed transactions. /// /// The cache is designed so that it either contains diff --git a/wasm/checksums.json b/wasm/checksums.json index 360952d541..bcf852dfc2 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,26 +1,26 @@ { - "tx_become_validator.wasm": "tx_become_validator.326ac786f8a2d13e05c00f867112bf2eb7fd0205e41702460bdd6615e0a86501.wasm", - "tx_bond.wasm": "tx_bond.c2d8b7c0e18b6b98ab80dac0318e2505696d837a7ecfdf05c53d0f8a850a3642.wasm", - "tx_bridge_pool.wasm": "tx_bridge_pool.b55678331a215efd8af07c061c970e586d5a186529b6d21ecc13d0808d433e3e.wasm", - "tx_change_consensus_key.wasm": "tx_change_consensus_key.5ffbfa39655a9307cb97e10bd3c0ba3d2f083cf191718c154df91b933e9e0e30.wasm", - "tx_change_validator_commission.wasm": "tx_change_validator_commission.090a4c5c46cdf0bb149f82de1dd476632e6c034cdbc85484791d9a6bd4ba1579.wasm", - "tx_change_validator_metadata.wasm": "tx_change_validator_metadata.6b9abec8900ec21ca72d8d28d49d5edc93e1d9003d4b588f721dc7ff475e4f5b.wasm", - "tx_claim_rewards.wasm": "tx_claim_rewards.540284b467fbbd41a206380d23bd4c93d6b65fa2c114b108c0e21b5596054af0.wasm", - "tx_deactivate_validator.wasm": "tx_deactivate_validator.a4b36358fbdabca1061d45ebb943eabadef496c74e9ee16943dc25e93c208cb6.wasm", - "tx_ibc.wasm": "tx_ibc.7eb2b09106b3e182819e8c9d428d64162bca7f1bf2f2ea599d639060ee962d46.wasm", - "tx_init_account.wasm": "tx_init_account.da3a893a6d2669bec7f93add473a4b37018075dd3482021f34c780a9efbcd29f.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.1c293251753a173a8ef8a0c4b2cda09873765fefc431618a98786be3a1c0d67a.wasm", - "tx_reactivate_validator.wasm": "tx_reactivate_validator.e06d10d70658c85bb1223d12d5f673eeeb10310510023a9ef8bfa78a90e24615.wasm", - "tx_redelegate.wasm": "tx_redelegate.691a4875fbf9e136dae7a3c19a5cbc893e0af86a0dedbb37030a4517cc309bbf.wasm", - "tx_resign_steward.wasm": "tx_resign_steward.a7d0b661b0c9c94a663afa2cfd83b413b59c16c5f0dad876ed9573b695201914.wasm", - "tx_reveal_pk.wasm": "tx_reveal_pk.ee74b4b1a4d6e5a025fde573288f114a630839dc23a413ab3d5803cb7545bd35.wasm", - "tx_transfer.wasm": "tx_transfer.3f55838e2cbdc79ea10c3da76118f35a4457c6b386f6be26d9df1e9d00565c7e.wasm", - "tx_unbond.wasm": "tx_unbond.84cd3e6af90ace7b9911a012f9cb3191ae3bcb48d02a936bbeabd5d387aa196e.wasm", - "tx_unjail_validator.wasm": "tx_unjail_validator.6bed337952b9d752ef02a6d4eccd168c8ae60a49a2516263679065d2fff5e9c3.wasm", - "tx_update_account.wasm": "tx_update_account.aa64c34962f4ce2af6ea98e2e9260011073fa0859658f3ff8b614a16e9ff5fed.wasm", - "tx_update_steward_commission.wasm": "tx_update_steward_commission.e5728d726a07ff4d732235d08cf11ffe0154e45a8c1f5f16afae962f2770f1db.wasm", - "tx_vote_proposal.wasm": "tx_vote_proposal.c46d4973fa34d260de849aea655775854ddd917ae535c3792b8c30aef8bced1e.wasm", - "tx_withdraw.wasm": "tx_withdraw.f94f13c6e21675dcee5d36e45df113a15152e65a75f0f0160a260bc810aafe23.wasm", - "vp_implicit.wasm": "vp_implicit.4e65e76c15d91af543ea1ca012eb7734dbb1fdeafc2b92d5db965b300a4605dc.wasm", - "vp_user.wasm": "vp_user.51c1f0e14d5fa6c7b4e787c732e6daf1a037cb481011840a6f8187687384fb39.wasm" + "tx_become_validator.wasm": "tx_become_validator.342d13f80c7db9462b9614b169303ea768f27f2ffa8d3f152eb9fa1e53fbfa05.wasm", + "tx_bond.wasm": "tx_bond.d231d3dd21613198245be912ccc72631730c0052eb58762b771d3014513a63a5.wasm", + "tx_bridge_pool.wasm": "tx_bridge_pool.174239af9711946856652bd641c92b50d64bc3d421efa9ff55e8c2fe5cfd15eb.wasm", + "tx_change_consensus_key.wasm": "tx_change_consensus_key.d4ea4959fb2ee837e22e5e7a40233211560a9fb9514cbc1908baff90371ad873.wasm", + "tx_change_validator_commission.wasm": "tx_change_validator_commission.47409552a74537abbe95b150213fb0bf96ff336f2a614f7098b50cdc5be1c75b.wasm", + "tx_change_validator_metadata.wasm": "tx_change_validator_metadata.5b6d5f26a2e7e496d2400ea0b7822c160712978f2028e95f95a84a4cecb161f5.wasm", + "tx_claim_rewards.wasm": "tx_claim_rewards.4bc11106b3c1f1c5a83b6f434d5c561e441c1414cd0cb1f3456377e19b5ee41c.wasm", + "tx_deactivate_validator.wasm": "tx_deactivate_validator.551aa9604c4493af85fe4135bae091e80a111dff3cac78c134c6332fd8f99b33.wasm", + "tx_ibc.wasm": "tx_ibc.64c7f2f96d18dcd37d5e2f965a55db3150313870521e3f8153920146fe45dded.wasm", + "tx_init_account.wasm": "tx_init_account.183d63f2a1756d94d05c34c492b800cf64469f96fa89c5827ecf9ca76872e7a5.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.f593e476685555d759bf17c8a00b99eb23a395030c1d91860f8533351acac3fb.wasm", + "tx_reactivate_validator.wasm": "tx_reactivate_validator.199726342ab6115ad331fde68cce609868a7260c2e66e825d5834ad8336f93db.wasm", + "tx_redelegate.wasm": "tx_redelegate.ba0412eeecf16911d146eae01cdf3c73c496772a951d11c56f640381af15d68d.wasm", + "tx_resign_steward.wasm": "tx_resign_steward.52930818f481983c1dafff33d7d54fb262b1e817e3f53d631e57d1c148e9d9ca.wasm", + "tx_reveal_pk.wasm": "tx_reveal_pk.573d68c7c0b42eba243c6902aae4002043e95bfc7d9fc2bda7334bf1b9a79ab3.wasm", + "tx_transfer.wasm": "tx_transfer.64672e859ca7a21eed446713857d439af9d3fea465075700611801a6a8d1d69d.wasm", + "tx_unbond.wasm": "tx_unbond.39ba9396dddfdbba866907b8c0c97b2fd0bd01f901dfd22426e53392bd5ee876.wasm", + "tx_unjail_validator.wasm": "tx_unjail_validator.10f93e3d9074e1d2fde280041a2e7b255cc27a974f074d958c532b57e009f1aa.wasm", + "tx_update_account.wasm": "tx_update_account.8a1f1b6a8e0d810e4a29be07331ee07cd8ade875025f0e680f2702aa23e30e9b.wasm", + "tx_update_steward_commission.wasm": "tx_update_steward_commission.dbe2f06f39f42748d45494318308abbc50b037b5d2dcd9663b14e23eb80c4c07.wasm", + "tx_vote_proposal.wasm": "tx_vote_proposal.897e9cee7fd524e16be3bffc37f03cedc188f8a615ea98f6af4478ca309b3bb8.wasm", + "tx_withdraw.wasm": "tx_withdraw.0d8ca0609d9a69149a1414aa6b13d4ebc0e7f8aa1e0946c7e74089d1fc15bb95.wasm", + "vp_implicit.wasm": "vp_implicit.14c5208d7e6b17475b9535e046275b4f448f42d519340a02ff74e4c86c2995e7.wasm", + "vp_user.wasm": "vp_user.e36a0040e31cd98c920399589ea532f068fb56a6d63aa5a27395995c810edd67.wasm" } \ No newline at end of file From 18d5ed94ab9a412d5528c50403be13a332cb2b7a Mon Sep 17 00:00:00 2001 From: satan Date: Wed, 31 Jan 2024 14:09:25 +0100 Subject: [PATCH 07/16] [chore]: Fix integration masp test fixtures --- ...582DAD9FBD3ACA2E0F8314642810FC958594E7.bin | Bin 10105 -> 10105 bytes ...9C0FD9A4E019CE37AABDC5D0E4B738FE06034B.bin | Bin 10105 -> 0 bytes ...D4D70154B89179E7DA6F14C700AAE1EC531E80.bin | Bin 2045 -> 2045 bytes ...FD0A13DAD049EAA1ECA95234C8AB02601FC0F0.bin | Bin 2045 -> 2045 bytes ...11DFBCF2AAA7876CE5FACD48AD18CB552E7349.bin | Bin 2045 -> 2045 bytes ...DB8CE4F984EEA5DE6991947DC46912C5EEEC72.bin | Bin 8392 -> 8392 bytes ...F2741B2A24802E41AF7F56081564BF2A160464.bin | Bin 2045 -> 2045 bytes ...753FB3BE606A5729D43A6EA8F79007D34F6C60.bin | Bin 2045 -> 2045 bytes ...AA6B8D85E10E17ED9D098B9C6B8C6795B1E0F3.bin | Bin 2045 -> 0 bytes ...2A3AC62CC602036F676E17820AD9CDD04DB3F5.bin | Bin 12076 -> 0 bytes ...0F3AD4FA4AB61D0B965BB9ED02971491A2B7FC.bin | Bin 2045 -> 2045 bytes ...21C4A7EB97EAC95F77B0410D41305EEF3C766F.bin | Bin 8608 -> 0 bytes ...DF787F70D27FE1DE4CEFD4756B6753AB603FCF.bin | Bin 2045 -> 0 bytes ...16D6748146469C7DF33C28DA6F65749E40AD45.bin | Bin 10105 -> 0 bytes ...0DF6893C1C09CF3101C402BFE1465005639F14.bin | Bin 14387 -> 14387 bytes ...83E61BED82F25C4452CA41B769C3BABEB62D2B.bin | Bin 2045 -> 2045 bytes ...48447BC02F4A27D5ECAEE75DD468D66DE97346.bin | Bin 2045 -> 0 bytes ...07ECEFBCDCC2ABB01BC7956857DFF45C81123C.bin | Bin 6177 -> 0 bytes ...DC5356710DE7B6F6FA2B23C19412005669DC2B.bin | Bin 10105 -> 10105 bytes ...9384EF0421F46F7732EE62196DEB73ECB4C225.bin | Bin 8608 -> 8608 bytes ...1E2DCE33145F68A217FD50B065966646F59116.bin | Bin 2045 -> 2045 bytes ...5852DCD946FCC03040DF7A58FDA0B6CC4919AA.bin | Bin 7875 -> 0 bytes ...C387A0A9919A436A15C6DEC3834051B7CC7993.bin | Bin 7650 -> 0 bytes ...926C88FA3742B7F3A45DC0E1227236BC835003.bin | Bin 6910 -> 0 bytes ...9AFB3B6AE2AA3ADCACF75E6520A66B2F7D184C.bin | Bin 7875 -> 7875 bytes ...A81A7DF315190329C7C2F708876D51F60D2D60.bin | Bin 4895 -> 4895 bytes ...FBE1500FF70DC4F2365C83D9BB9015D3C28CE1.bin | Bin 2045 -> 0 bytes ...5A0AD04432D0D4BB8B2488EA5E836837B00394.bin | Bin 2045 -> 0 bytes ...9BC3BBACE79DF98801EB8154EA1904597854A1.bin | Bin 4679 -> 4679 bytes ...EF52D368B771AD525817E722EA3E12B0A96971.bin | Bin 7650 -> 7650 bytes ...F7858007C4DA521F8E3BF250A46E9342178EEB.bin | Bin 5660 -> 5660 bytes ...3356453E412F862D949ABE9671C24A3903909E.bin | Bin 2045 -> 2045 bytes ...861C7F98EA4325D94989648024831E350D8F98.bin | Bin 2045 -> 2045 bytes 33 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test_fixtures/masp_proofs/2AB777063F53A1E6F66DB635DD9C0FD9A4E019CE37AABDC5D0E4B738FE06034B.bin delete mode 100644 test_fixtures/masp_proofs/5DE7FF931D7864F0C05FD54926AA6B8D85E10E17ED9D098B9C6B8C6795B1E0F3.bin delete mode 100644 test_fixtures/masp_proofs/693468170864DF8C1A8C13FE2C2A3AC62CC602036F676E17820AD9CDD04DB3F5.bin delete mode 100644 test_fixtures/masp_proofs/7198F6516381EEB67048E3099D21C4A7EB97EAC95F77B0410D41305EEF3C766F.bin delete mode 100644 test_fixtures/masp_proofs/7B6C8C638FEE08497ACAEB06BFDF787F70D27FE1DE4CEFD4756B6753AB603FCF.bin delete mode 100644 test_fixtures/masp_proofs/ACA50A646C6CEA7751373605BE16D6748146469C7DF33C28DA6F65749E40AD45.bin delete mode 100644 test_fixtures/masp_proofs/B7C738AE39C44060FD6EA5D7C648447BC02F4A27D5ECAEE75DD468D66DE97346.bin delete mode 100644 test_fixtures/masp_proofs/B88A2DB72E3A0A624B9076C5A707ECEFBCDCC2ABB01BC7956857DFF45C81123C.bin delete mode 100644 test_fixtures/masp_proofs/C83BAD95A33CB66390611EF8155852DCD946FCC03040DF7A58FDA0B6CC4919AA.bin delete mode 100644 test_fixtures/masp_proofs/C9D7CDFED7CB968E7743BE392EC387A0A9919A436A15C6DEC3834051B7CC7993.bin delete mode 100644 test_fixtures/masp_proofs/CA9143A071C194759B72139C6B926C88FA3742B7F3A45DC0E1227236BC835003.bin delete mode 100644 test_fixtures/masp_proofs/D5A372904527694939249FA0AAFBE1500FF70DC4F2365C83D9BB9015D3C28CE1.bin delete mode 100644 test_fixtures/masp_proofs/DBE07FDEDBF79BBC814D3EB70E5A0AD04432D0D4BB8B2488EA5E836837B00394.bin diff --git a/test_fixtures/masp_proofs/11BBC6FA2A8493A11DD5E488B2582DAD9FBD3ACA2E0F8314642810FC958594E7.bin b/test_fixtures/masp_proofs/11BBC6FA2A8493A11DD5E488B2582DAD9FBD3ACA2E0F8314642810FC958594E7.bin index d8d0752e4d74fc2a475d90ee3fcf3eb99f40c073..809124ae22df903ecf004622ad952eae4623c7d9 100644 GIT binary patch delta 1797 zcmV+g2m1K=PWeu-78oG&?ajh~2TK6V_{fiJT4y=)GiO`xo}X3g5=iaTN&6C$HW)!+ z{$}MlSI_S2-^tgVyL_FhdfuwW81Z)vuexNO6$s6X+mQkXrEjKhC;A|6G9Y#9EqW4c z-b&*HofbwRk#7zl15JaVRZ_99yv1(D0$H#{I)kkn7xF0s;Oe+h`w!YjnzPs#qym5N z>Why&Oj3U>DNnGFCEHXfUCC?n2u&!}WtYG^L%b!Tuwq$C<3H)CdxK);*DhK~5LwnI(fpPfsmJ( zlwaF7wKw0dBcUU*x-gF*&T~X7j3Tr98A{`hH*=@??iuo%c#5xzKVu)199GCnVpU? z)u0n}^p2FAbF+Dz_Oj7F^AhdqT)fMYCy=-8>f1B=S1~$x3&mXpx&RSb>{DOije~6L z3DxIFYw?uAIzsxC6HV^64uClq>#*}AFZrVcws;*Fk_N^(L4Q{Oi}lDJ*a{O0Rg_cQ zH4(FzCtQ1Jdk)ONBJ3QX)Vd;@ee?Rn-y?M9GRfeHK)~{jnN~t1)Co~KwXk_I4`)<2 z5zwk$TW_Z%T|8VT%LAxFy8B?)1H>LnvWx>-b5AUl1-pXkM$5;hIA{F#Zc(So=>l&Z zMZ-cfG-9=+#(!8Y!k;L1rlx6vciXMY;P|qG&Vjn$0Uy)jp^CdM=1Q1uEWuU#IcjsE z9_fAkM!`Vz2;s-4ULjY?@OS*pg@3n&c;M;$DC?@jV#SgR){o}0 z%+rC$!|Kj>#`0O&O@k~!9sUl}Vo<(Uc^BG@Qe58&+aIyeu||3)wzXp~t;67D)}i3k zAcuLBxTGM|$7L7BHPDuF;~2kkF8s-i8k&cpJnCnUp%J=K%Nel#1E4m!I#E)I* zQn5`AkKoCedtgZg!-*@W#yqtHtEk4uixd{<0N^3frjWqX z!{mU!IQ-9Iyw*nuN#imiv5g>%fkyligzp5WI*+?HLHofdNn2-_%>~M4ppL=qE>0yv z$bSQbct(%)lKH|}^g8kBSg&`9Z)y-Wt`wposC2IfLR038(nK$2SPR5v0`^h_ERl7C zw3=1j3UnJ~2sW}PI}tIMv^i7wz2_}sA9yQPTzyq} zRPFxGkL0P+FB1S=Cg6Fk_Bq_ZRgev}1Hck1nktjp1f#xG9BCY4NU5aQF#k0lgnyBs zXHF^scKh6^9UDjf{IcN~1lQkzq4^VM~ delta 1797 zcmV+g2m1K=PWeu-78oF5M}2Fdge!6_?0)-LlCywTHMUSBJ~S|*%Pl}Zbc!;QHW)!+ ztE5MxPYq4l-Vb|8*^d9e!G?6fLr$_R>po#%5YM{6ocbM&&fY&0$nz@poM>%h8e^xo zN*9_YE^P>J1B){RsVJa--FHAs2wvhe!9hm z+PJvM0>kOABcUU*x-gF*&T~X7j3Tr98uAdYxSj|VICK_GNE!?Gj+Z_Aif`s5W` zgZ5;)@WhC_dr;U7=mukQ*zCrvdgGrwaxm%p46w(gT6r;s%u?X+S{I0dz;(`^4y1&$ z4$vh4?)d{_gtlgH zt&ym|?~%9C+o@~j>95n7JKQwcIdr1CZZ)4XbeReCWB`#7Ad?j$Ab*aZrrlK++E(rr zev72;tck_Mh_Ag+531_{m}UT*Q_!%6;In$7DohCrV2w9dYsup% zfwxSt$QTf}rzN#^y?-Ryct#;B-^4R#|JmR2{sa+(gkygFiQTB5`MB(wW6a7(`z}}O zdv3ZZc&@uE%D-h*n7o1}12dDP5Csd?=||VOp?^yNwE6F&8?#O;r(yR7 zjL$Ztd^FlJx9WeF&Zd@`f~|5D#L%pFaC;K{B6mJG(DD=RxmDH0bh}tH%GCR&n*{0? zS!^<5)@gh5-xg-Gla(7BUDN(u`R`0_3o<~J66LF+1xzzCX_bhe?VEvY_5XTHgU)I; z+g11AL1c&B_A?L@pf3nq@!beJ6^a%up#5Pq zOkf%-^Kf~|aMwP_KnIvL9af56R4JqMt8O$|ry=Ra74Ny|)N(?o=IP^L(5MyXd8+RPY};ny*}g=Z&7T>lLU{Ll3LQD&$yzg<2H|lHr?Q40D?x? ziX2-T?k|U~-mza|-qxVyK%0nw`$MN4^-WvQ5RU~BmofHkjjz$NQJ-27;)Y{pt&2M9 z=G(RY)4_O{S+RZVnn_=TV6k*K)gYi2$QnHmqvj)k>VOB` z-+wrdG3y&@b*{^=)t3Gp#3~?;1ahXKUhzF>YomP9fgvBS+U_%I@CAFsKmC#YG_uEq zPS6wwm;Z5*1O@Za+sJ6U$iwXoL0`RKcR#9IxvyqW39LXqq_R5Dz&(I^2cW^u*L-ij@P(M-8D*_XpWGw0 zB4ealezEgP{P)=#W&TCw$tZeWs6gh(9wR;9Hio$QcOfFI>~Wz8FR)>IEH*DD2PDlT z$B8}`g7f35qC_NeZ5|1pC-KBQ4T`$XG|UbVNe7 zDTf*);>nFgzge*@nk-sPN;y$1abXuKUt0q?agSO`=|qSiv}fCI!QkC zlTE1VETX1@h$K={1K+B&5R>dZ$p^1FGh8^|3)q~5|C8spb`S4utwjgKI%iflzdVtm nE}?*qSs*X*excJ&tX>=;n+LSq{|c624A*1SR;cy`lQkzq6C8lF diff --git a/test_fixtures/masp_proofs/2AB777063F53A1E6F66DB635DD9C0FD9A4E019CE37AABDC5D0E4B738FE06034B.bin b/test_fixtures/masp_proofs/2AB777063F53A1E6F66DB635DD9C0FD9A4E019CE37AABDC5D0E4B738FE06034B.bin deleted file mode 100644 index 5fd246bed0b1bd2888e4c42d995eec4090049572..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10105 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 Lv0pi8e_#9u_`u6S diff --git a/test_fixtures/masp_proofs/2B6C3CEF478B4971AF997B08C8D4D70154B89179E7DA6F14C700AAE1EC531E80.bin b/test_fixtures/masp_proofs/2B6C3CEF478B4971AF997B08C8D4D70154B89179E7DA6F14C700AAE1EC531E80.bin index 928780e08149c1c7cbbf747edb541e9311cfe51e..d8c8886e1bb151090fca578f75ba47ed6c30de99 100644 GIT binary patch delta 601 zcmey%|Ce9q^?wLpWME)uxXN6huwG^P@$c!$EAE}QdLooM`|q!*-CrV?otrDtxp<8fFED3Rl;5j*8+Yfer&ME?!6~2jI;PvVoteZG zuTj3duCRqaDdNeT{+ZunXKb{HdU4Qqg0Hg9c_*XLE3{>rM~ShCHWubK2jzkDUJ>gGga%?*;N z8#eWZ)Uy??>0K?(yiH5IU)gUq@5Px>4<}AE+!&&DyI)bmJ;#1=y?B1+^QiU%jn9LO z#HCJ8i1e3SyzH6XuZ;4yoJ~bdG3lk76qGY_?uLk-Z5D}RhFUqt#;tLy_vCbbY?3<6V4U4D-|NL(hdOt;JBOof9Cz%MblV}_E$~t5 zm$bj~y@ii91^6ugl-AgPoXtr0MZ3J$#JK_?6IgT)t>ZFR5pTG#@W08GE%R1ePv3m( cg(2s=&Ug0bT36_C7L>f?`Ju->`60Uu0Fz%Yi~s-t delta 601 zcmey%|Ce9q^?wLpWME*p;PWwG+j@dP&5wtQE21Y%w|Y^Nm>(WD^Y(YXuKR7%-b~cd zR3NCP)RUl^jrZ!92r8Of!>r(-FI!PEW#v4XS+hRt6g*z8Q){KH$X{1C-FV4`*jvx0 zEA#}deaG>rH}Edc?P8Z%|M{0)F;iF`)O@#Zcj2O@E3ZQ*-(faUh@GiCMa^(+5ZlHK zLz~V$PuY25T(1Q6?tQ%1?p&O&J_5JjD#q)fXA7)K%<$>yt*XoHv>Ml`T@oD87mE^0>zZL9g d2=kBH^4V;`+2%FxcTLVx*!wh&Z}LNS830E7Hwgd$ diff --git a/test_fixtures/masp_proofs/3E93E8F4FC3498BA19EF4D4D70FD0A13DAD049EAA1ECA95234C8AB02601FC0F0.bin b/test_fixtures/masp_proofs/3E93E8F4FC3498BA19EF4D4D70FD0A13DAD049EAA1ECA95234C8AB02601FC0F0.bin index 5747b31c0179afb8170fa41f07c7b6564eea08e1..77e172baeb04122600093256d39635d6dd2f5170 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6?yFvd*G@relAdT!CT+1%qbnDe_nsEcNYIZ4a_;sG3LQ|*#{ZdrET^ly zE3|U?XW3gC-i}j)lYI|EtFe19uR6o#?v)D<84Gn2u_P`L(3u40a4JXkf&?~CpX}9W delta 308 zcmV-40n7gV5B(3YoC6?vHkO$Nu29;$R*Q!Q`fNNVB&2`!^2}Wzm}>lJcP7cRyaOcz zf4Bg-LY{FdB5nFQBjCt$QqF{rrmn;F0a*SI)bl*q^Cy;hKZkm5`%t$EC~!mSi?uKs zR>9e<4H2srYx*lwW44a${KYi7blWWR5c2=Aw!~p}6e0x60V+iF6R@20^Amd|`%XyT zHNOOHM;Sn}Ws<@UMC)Fg73VMA%er7|f34gf6J{LJjP;INB5gi?beyeV8Q~s{$sQi8 zF^GF_!>Gk2B?JCExNX+FLLTZ-f=y(-IrI6Jov>ER7}$&r^|ALpJ|z!Z(hP9VMN_NS zvR_UY!;;*#XQV}<%K=qo70u3%$wffVYGDW1I)PswYOTE2?XV+oh!Asd>l8nJI#qs%MqJjV^ zgs|54mE(f&sM;B9zh_hQs#)YiW=pYK8JCH5z0rcNSOn%H_)of9^fp@2fCNT8GvleR z4fh}c;A4z>_SeZYrdxes!a@f7ZkdsQf9i5~mD2DWN}GkY`S6SdL;;hez^*L0MtZ4G zR3rX<)?}YOW%UZ*cpjgixI_Y${WVlFAcP7GVNR3K`d>KQE%AfW)`qUuREa`OtS8

XA&dyaOcz ze}bhV1?#%dcpFV0Q3&@DH0PU47sf;j@G>>IC@K1@o7J zw+{}fzIva*-Q2Qo?YN;jG_No6Icnj~e^<2RCDW@DqLweee)!=77O|%)zr&v})$aRd z!v2$X?-vr>wHgh~heU>wumufG7fC}r@5MIx`i@-@)_eT}l~V^<_P6*tT`SrTC`sLX zv^?h_I%}vknsTV;a(7m>kT@aJP)y(Mv}nG1l+0s;h-5T_)QX0$A4)-$){q>-0!0jy G;RhVvIGgPN diff --git a/test_fixtures/masp_proofs/5355FAACD2BC8B1D4E226738EADB8CE4F984EEA5DE6991947DC46912C5EEEC72.bin b/test_fixtures/masp_proofs/5355FAACD2BC8B1D4E226738EADB8CE4F984EEA5DE6991947DC46912C5EEEC72.bin index c3af4cfd0cd7e2a1bae0ad839683d383c1ef9364..85b3a5b78b993b096ffe52f6b278a44dc4acd706 100644 GIT binary patch delta 1470 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 G;RhV^hLwf@ delta 308 zcmV-40n7gV5B(3YoC6?sWkfd|Uf~oFW~ZM!-qkh8`tAYIL^Xr?`I`qWTSd*YyaOcz ze~#>)k)hpX9=}uG`r?%uMC0r+GUfJescNz(L^3=W)o#E|ckn^lEN(o^DJbBH0H6U{ ztYnuc(Q)oH0f`kj)A)d}K-%-8cV|RK<1Qsu4xSu$~ z*PoR)3Krox?UndFNeTDV((0(d%?XSpe=DZK;E(f-N+zlpte{&s1h<1B-P`Ne=#d94 zO;I%Lf5}+V3H}v`=~kkddmQWr2n%82$R0Kq74i631km7d8nVbZ(i@<62{$yRdxJ*p z#GUJE{1#-w3Nf`Y4ohoAcr}vt{NK0MspwU4tovUBM0x1?HRNFd(FQ?^GLZIR0zeLv G;RhTVpp_8- diff --git a/test_fixtures/masp_proofs/59CC89A38C2D211F8765F502B6753FB3BE606A5729D43A6EA8F79007D34F6C60.bin b/test_fixtures/masp_proofs/59CC89A38C2D211F8765F502B6753FB3BE606A5729D43A6EA8F79007D34F6C60.bin index e572c3e4f0aba6969c471595665702840bf055f6..8a28e3d06019668a1123ba6ec4f279925112b8a9 100644 GIT binary patch delta 610 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 P2UaA5t5zt71xf<|bCBA@ diff --git a/test_fixtures/masp_proofs/693468170864DF8C1A8C13FE2C2A3AC62CC602036F676E17820AD9CDD04DB3F5.bin b/test_fixtures/masp_proofs/693468170864DF8C1A8C13FE2C2A3AC62CC602036F676E17820AD9CDD04DB3F5.bin deleted file mode 100644 index e2b6c5b4ead3c8f85f66d1fa6b329bd616288bdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12076 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 diff --git a/test_fixtures/masp_proofs/6A12E11EEAA83A0D00BF7470DD0F3AD4FA4AB61D0B965BB9ED02971491A2B7FC.bin b/test_fixtures/masp_proofs/6A12E11EEAA83A0D00BF7470DD0F3AD4FA4AB61D0B965BB9ED02971491A2B7FC.bin index 0e726100161b4d3fe8b85a20f64c47d6ccc896ae..f72e509cc8c0dc888776d63e357cb826b0253afa 100644 GIT binary patch delta 637 zcmey%|CitJ^?wLpWME)uxXN6huwG^P@$c!$EAE}QdLooM`|q!*-CrV?otrDtxtQVM zS5}6JhAOHA70Pq{`aiMCg|I@9i5nkRG7+b8awD^}gH?gW-B;~K4q_6=1!9-0&+z^f zz;^$>a;MXyC7FtgGj=iYU10W}e38XHcZ!zQ;>G%FoC>;Mw>_EXQjmJ`^Qy0wlkYI= zs=u10cVy4$6_+2f+%;#Ne|g)6>Io)q^TPEn=!!JVH#K;YTPfUe_S>e-1}q9p0^j_( zN~S;fYy0)_GVQeZP9Z~rE$}4Km{E5GwmfR@h6nplu zf{A0+W665I$>s?vId|9DMlvQoJhj*Su|VVMx!qf?9sk5GX`?>(jj27y(+RI6Lk<^r zT%64MY0Hh<$I1f!l;K=~%S%qeTvCNSl{vuBuW zqNtL@bB$%r{_lqMRdY=v&06|R_w`(4U-4-2&Sf=!)Fc}CCmQ{5*|xuWfBc#c$|k0~ zo-QSynD4Aqo?+YK|KtS=<0~79{eH^-t5;5U@z#>kQq51VvE-TjkX?j>37F16006)~ BLIeN+ delta 637 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 vfU}Xckch<(%q(+6$(@nn46eGsDXV6UC)o&aRvq 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 delta 633 zcmey%|Cit3^?wLpWME)Oy8ryw`R6U_(SKOxm)-xq^N@%11HYd=<-n-HV!kn+;eLm;^4p_!;uV z?UUXey-kAay2EEqPGAeHCnf-(;R>euH5uxBzC2fSpL5sGe{GHFw|R5oCOuR+G$m!Z zm0k9BevMsWH$J2_N9!kWXFWD+YFHlJbjv4^@pfC<44y@c3Z%cSv+w#Le`(T(V`&XS z2D|FH_g$*6b>DN;(c)6_-rU2719>L+JZDU~vL@{QsZa8M0v|@I?$JD$zv$~dyFXov zg#NSL{KO=nZe_Ur-undpx3x}%T{eFm7ey|fWEs#meGC8W2}?M42c+LoO*}vCOkTGj zlON~7DJ!Pm-`<+S6>X$m6WJ;s7}Wp5?#I7&>pKk_rx+RhH&QIWwqwqtlP!B1zq$QY wINOk|EtM6K9@xWhblW3secLhv_k!I8CwP)gYsJJ5OEOG;$S%SGN@E}Z08KPJ^Z)<= diff --git a/test_fixtures/masp_proofs/B7C738AE39C44060FD6EA5D7C648447BC02F4A27D5ECAEE75DD468D66DE97346.bin b/test_fixtures/masp_proofs/B7C738AE39C44060FD6EA5D7C648447BC02F4A27D5ECAEE75DD468D66DE97346.bin deleted file mode 100644 index 30b622be46123f4fdf9af7af6099c9c2d55ff5d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2045 zcmaF;9|9N|7#Jds3t86JLR1uA2R zy}DIYP2rizY?jkfZuZuj``A5vK;jIqfo2h9kUZBfsJ&nctQkarG&8(>Fi~9U|=Y6m4bLIPV9q+1&Eg#Jc$4-|~!wf3tQKwl4SD z*?&yvToi}e+9f{cKl=Rg{&3bgnvgwA_4ztyH`#0LuFh2Nn^MDgOpMF$Jk!CsY!|*g zT`gPIJ@p&N;iF*0h5!@L=UnQ`)s~h1e+dc%P_kwuHg)32PmE2R(^%WtUQC@EZ-4o@ za>z54C0_qiWG^WCZmT@_(c1aNv||@`sU@5|W_fjg`OB+^-|^k&ku_bV@c94a#Rn!^ zKlG^Akv*LHLpeXZ$HS1#Tt_MY&!iU?u8fwaiaz~I@-a9ygL#sL(tDTq*)A8IX1|)H zcVy4$72F>(m#hk?EZeQPUPRXX=(JxIw-esny8T1e?t#F@_Tmrjc~ib?P5ftk`N^S6 z@-=t9&tH8`Xz6pU7dIqpXB4g%lGBvz&Jd2cP?^P@*Wz{RNfaXsOGr?+&5f5Zb$hLuH=ykg%(tGOK0@05`&jI&s+Whr*!TaNdf-9a`PM!^bM zymb#cKKk)A+>t%dD$C|(U~+cm?w3`!-IlMdoSx6yxpsQc`{f7c_CJ>kUjISVW&Z!& z3GTK*S7tqliYR=#s>IwwJ7mK9t1h*%&Kk`%NemJjYTfks%$vgmO5{bdzpB(1`LSrG z_{?E5np8N?)Z>`@r3s9g4-f4qTJE-I@i~U=DlJ#1OxQX<_}{NQo2&OS=TH3cw&m03 zqmvV!Oq}IYcOa$Uh=&i){Nv)9TTHq#@0-ux$tODF2CO9nXSL_!tJzlV zyeDILOPJ-OjsKRbx4El&yX&@a9od=M7ysJhm*I&k%^dexH$9lL&!s`ZPj2<9j_8Mc z_m(d;UlZ|GJ7`&dfyb^73YXV}%KbXAFQ=Q?O2lQlL1iNUolj@JG=FjLEbMl8WfN|9 zH*(>noTXVyjy!6Za#XYWqt#@w#6JI?3vIikA8F+q=f!>AzW8ME>)l0fjpRH!eoLty zJeN_qlrear^IESq=4E_093H7(>5D8o_^W%-*)X{ZHF@rg_;11PyPAhuQ)h80Gq1FL{;Op5tq=FE z8eNuTwE1*&K}tcxG^uUzKRp^}=I1}tD6Z*KW$ENC6#pjpFyz`s4UzijRWhvU={)8e zc?B0O%=BF$R-In-QnhK#r1fh%tggI`e7Rt6#&_0EdyZr4tiR0c*}X}qK>XRHy!Olo z%CcYV+4}!Y`~OYp9?P=5rq>^>k1ffM+0?0Xxbow_+4lsGOo_05mp^auhc{cKq^5rL O;D8m$;HnkMfw2MPALKFs diff --git a/test_fixtures/masp_proofs/B88A2DB72E3A0A624B9076C5A707ECEFBCDCC2ABB01BC7956857DFF45C81123C.bin b/test_fixtures/masp_proofs/B88A2DB72E3A0A624B9076C5A707ECEFBCDCC2ABB01BC7956857DFF45C81123C.bin deleted file mode 100644 index 155287509e7d8dd4a037217e44a19304f7d446ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6177 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 n+|Of7B2YIMfi7g5DuEZ(RZIHq&tOzNxX zKhwn!Yu?4GVy&oI11-T#Vk_&1xI#M&<96a}J5ty^Jw_xnjvY%^haZKW)w9?bqym2^ zuNeiqrT4ROTc$s2`#nQP{+=uWl!Pu?CDcBHR5-uG3;r|RhMT6T_GkAuAPhLkeU?70 zM%0}dNUqX}Mr^EZ??oY^gk7y9zF&XbJC_N7CUXcD`e0L?)*}7tVVMfvjp6~l4wma0 zV7GnbQt{L^q0(@G{SFS|)emYIeyspz!{z_~(^qd|*{=6Lh7 z41MnD~??tE~c`>~i^O9YO!a3;RAi?}$v zP#-~+l_^*Jbe)}tNnzBtZPah2|x z9^#1nZ<|QVSaooH9)G7eRtunNZ4<;EV$#mt#zLW!I47U=8xrqxcJ}cX^n|V)p!->V z(xvCkB!8jEO#h@D?{Rvobrw}r(V}s${T}s6#LXEP}6zfenK z#3G5GZTtzR8h`W>5}DO54-yXCWIeYajriyPprk?pq9LI$kr$l^+^YS6E5fi~f)RVk z!a%T1{~1o%lriax{1I7$J)IfU5|$PDAB7EiiJ&aI<9H13meqTRCHnc*u(db-sF?ER zyJpW*44_ADz0p`ES7vJq9Uy=OyqB$>x7HkWeSg@~Tb@?zEwr8gdZemUzR}SG zja=|qj*g5f%0(Ps`dtVo?mQUFpQ*NK=JE~0|AYv5e-b4*w*{4XGp{9R0PHwo0!NXye}j6K87)+T|h*wP_&2 z1nf_+P~P<(;!&uCWk8JbO;Uo~vpFGI003Pw>y`Crw}9U)dIc2NoRU0$wOUTg;A_qb zrGHWA+~0vo0<98*y;yIo($DM+Yg!fn3CHa5ZYj{1XE$nHy;W7GwhEfhtJ6ey?F>QS zDf)(A9Bge-?1^gZi8!PL83>hSdM}!h^tUh%>lLe>>%5a%LjU>IIuQ2nk<9#Gw!?EqiD`=gnx%*lA;mb n$3Xz^L+l6P+x5V=$~m(@i+T(t`wD3EL`w$U~zRC&Lu9Juoq`Bx2-2^K+N z_oI!_LXcr~ zLa+Zwm)*KeDVMGg0uadM?U5eFJvYzK1#ib4ELKAU!j4&4l8?kbuT|`vo3pDHqym3Z zbh@lfRFvF<4$_rQRnhhdxo&#L3=+9hJN!D8_XDvbLoS!Tk376 zWim?_0g(_WlP?PhljIygf0jCXAE*IH=QWpGaA&84OqrJP{J*lT{Yn+^@{lgJBfEYN zrKRBe#u7b+>NyTbbAaMEvZwD&$bTvIuhW-@l#f~||4JBymb5g7$QX^%Zif?Kj2mQj z+){P2QnmzR1_Nt{MHL}yUID4eDU#rPsFlVF3KT_?j-Z2kiu|+5e{f_+z}0jYEG4A! zpiq%|;l`=BKd&JgRV9{g%_0*^Zd*FpA5LH_(x-iD(7~ZpmyDi*at|0LsiKGlZHOfT zDuk$$y}30mdoR4T9F+MmOd*qcPu5h639~uRI;HCBrRmZ+;~DdIl=D~|e-}F@mlgC% zvRgu_ip@BeM^78CepmrMC--n2c|$nF86B;aWsr%j{I^T?2?AsE8|ObGbcdk7*Y|a0 zb7XDviU2noLrra%0y<1_Lb5s!{2J+2_72gaqiN$Q*UXIr22YqBMdvVrR;QP@D}e4jw+Jo z4%QbUe*Svje*_nbx?DO}c5A=_m?ZLw7etOQ6ER@W;sr(U*IjkiZ?MJkT@L+kJ&68I z9%FFBP6L6dX5XXW6B!uDtz6Ft=NzV(#3K*4&RBIF8>Wdy;%ravJE;cd#Q`wvFONIq z{RL7@y}f2+pLH&?hgui(FKgTt?F9a+;)_dnd zFK}Jxcw8w3L^aNmH2?Fy-~$nmv08>DI#Qv(sZ-^qt)?!qPn#9W4JV9(I3IrJeGWW|gf1vo^$tFiEY_4~)t#*O^Zq>J zi!Hz8^cWn3F%3!y{YLN+)xlh}?}a5?k(`p4f6YE;)E+x8xJG5JGfpnH0jlzGRz0z4 zG#r*mr`eP^bK~F|R^JFJ2;kP493QJ!5=a>(x;=GDrvN7sxD#Ck4eBN{2{RqpR=dCj z%hwlc^2TF1wNN!?rfUof{GFF?x;?Kth-0)bXtIlko3zYIPi_+B>6&7(0TZK~*a85 c6f+kOkcHvpn*#!*Og_9bAA$O}0+VDRJZ46}ZvX%Q delta 1474 zcmV;z1wHzpL!d*j=@lTcwLImA^AFQf0CB`e)Q>_}!4{lL{cud11J_AI3<4aJ2^K+N z9IUd4@1GRgd4My@T-bQ1wc>S+|FVfiyX`TQ23OuNM{fTM*U#3I`rwTPX_-1ZnnwHa zv2dyE1L_YphYnUA0=u4@j|SRU>Nt9>+p!Wc8rBAlHJ;rKBd5Bn%B$Mzy|b$pqym2s zaHIW-M+3Pr%@A}XaHf?zm%_t{(csJMr{C#iXQV0Oj15{cswaz3ppD&0e^zex9c8qt zYd0Hw#)GKq6)w!qP2i?1M=qfs3%WwfZ&-9JG;Zo3Gd|_lIW$7N%$3qP`^pMS^6_ad zrlwhqF$W+P-UU~ zPA01u{p{u61tH&#Bi-_JTA9$Q@nH+8Hsv6a>{5BN6bu3*SgT>W$;A}S8vSh;!byD( zvEB_d0g(_WlP?PhljIyge}tXjQ;*k!=xXQ69xvh^lMY%jBT`6D%7`bv7#6nX$n|bB z01x`%d9nbY<lCrmF?RE%V9uF-+yHs2%h`F{WOI4n*oXnSj~;` z-#Qx{ora-1m=d5i!Wc2cL2P(8Hef926XEp%ce=MB%5xsc0(gTie_rR`Uz4&ZAYHpx zQ%P@0;u4TF*qXxxo$i_?hI`}8Fnc;1#UJ1WF`5t`Z*7eyKt9ANYb)0$%#uJO4_!+c z@$DT5Yrm$-{85V0pz6yp?CtT|hW@T~QU|YJ2zY!Dbt4UnkX@HAnuY?2zmqVQ7-vM? z#EN)u@$Nw*u#a@pf5-}oJug%Xk5Zg_QX$~Lh5`$S0>DLx)9;VS27s|>a;9%~*T?}V zYvIYNQT~+$$!!>wWAAA(xyQywCj7_Pt<@Ihk+Ht}x9Za5say39D3lTAgiR7>8EABD z=Yhp3Zp{q}%N>-8petBtGP1z*L=8I!zXVn zuMb9~qs#h=;zf!xtww$6I>)1@ybJE`x!DDsVooq4VBvZ1z%tXgUEq^~rn#1`jzb*k z?8yxxR0tMzf3T1BY>^NI+ZHIWerNCj=|R@las?H&>`V2Rthj^JVx>X_Y6DxnsRE#| zUcM$t&6P2#!M{|5#fd+0kFRq1!iP(WEqpTg<8N{5h=`tw<7!>dq>eKBlg*D?w-b8~ zw6tZW&5M^L+{{Xg0+~n*xEpUf^sd{0jHyC#a?l%&eZaw;&PA6qz`$0>&8~kf zT6JKUr^%IBI4uq}?YuMtWT)xbyy0Q9Ge@Abi>(3Ptd2r}y4snJ3qw_nl0CO&%0YC$ zC`K=$e>+nxyb5QJC$Ug@HIRLTMQ%YN&Y}R3Sstg`yA+R6AX=dLOi+NqNM?ufLpxH0t}CV9^9iT~2LK&FCNrXen$w_a6# z_+8*PhgfPY;cfvA5mV3b@}cBF$|Yw^9VRoY1GILp_U+A0?Y=P+KNg8nSO= zNS{%NbBo2Q`X8~KiPszd9kl_yTGdTBf@kA?Ig`2h3|Gp^{V@r9R7z~N@zKEmt?U~o cCXauhytZ{p5nQbTMemfxN=LBK2a{wWJn$ymbN~PV diff --git a/test_fixtures/masp_proofs/C614F20521BADE7CE91F2399B81E2DCE33145F68A217FD50B065966646F59116.bin b/test_fixtures/masp_proofs/C614F20521BADE7CE91F2399B81E2DCE33145F68A217FD50B065966646F59116.bin index 51f68528d4cd92b03a2d83e5b2e058d41db47209..e93c32f27b205b6a70b6bb18e558904a5260c1ef 100644 GIT binary patch delta 601 zcmey%|Ce9q^?wLpWME)u@m_5IvPxj{YJ;VhJim!bmQE{O6iT3oZ920dk z6$q*+^(3ffNDZBOp!+1EEd z=r}0H)G4syPtl&znDs)X`&}mN`tD;fM|qp%qz?~68-Aw-a~wJ!P#<(iZSG&bjc47z zy+6>(GuK@9bG++2QL}BYw_T}z#l@vrQWo%?TZ8>$M3Rb~q=0@x{U+^QGcVl!`-$KF z;1jOpn{HU2d2?*RgA`#8qvIKW(*@j>QZoK54e(D0I_Va9n)C9VP}9Y)4S)5WZVch@ Z%@3TK>~9)>d*g9oUawkN=E)D)WdQ41D-i$y delta 601 zcmey%|Ce9q^?wLpWME(@mUFC*4!V1eXK&5c^w#7}YAt&%%`fKnU7yUf%zGi5;zS)y z1%hfyJqfDWc(0C$prXk&%nA;zbDkvUIv_#?=YJvysEmlS%NkD@Rw;x z58waO*d%)D)V%5|k9|U9oEIGq6=mOSz@oq;ASUjzHf{4+(?q{rW{W48|CyY?7FbWn zx6r_YQ)@-{zb;BV9Tt)P-h9agl}j^Ey}I)4(;U{@vRV@EiPa9r75hTHyq4dYqorW^ z_U+Nbt-?NPgf|9_a- z{IWr~EpiKIIscNzqX$LzPxGwZbLo`J-YwrpXW4WdI7!CG!9P diff --git a/test_fixtures/masp_proofs/C83BAD95A33CB66390611EF8155852DCD946FCC03040DF7A58FDA0B6CC4919AA.bin b/test_fixtures/masp_proofs/C83BAD95A33CB66390611EF8155852DCD946FCC03040DF7A58FDA0B6CC4919AA.bin deleted file mode 100644 index 31a1bd0816ae04084e9e57a728a7e29b29866c97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7875 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 m@-(Y%C&>_T{f&BL7vW#0WE!3hKjIyi*jZXq}c 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 diff --git a/test_fixtures/masp_proofs/CCDB111327E4189EC4C6FE2D429AFB3B6AE2AA3ADCACF75E6520A66B2F7D184C.bin b/test_fixtures/masp_proofs/CCDB111327E4189EC4C6FE2D429AFB3B6AE2AA3ADCACF75E6520A66B2F7D184C.bin index db2f1b978d468b75668732275e511b1170173b3e..b19f3ecf20b6c7b36fb6a8d7e717dfa48242a3d7 100644 GIT binary patch delta 1378 zcmV-o1)ciCJ;Ob)6cZpON!tPgceaYI-Mi|hyV**C6h!dsa# z?LP?t!<*Joc44|}0tt2RlfKMV3DB^cWY$?{gUmrm7F@FUDN5b~51Ub(Nwd}y^a3EO z8sqjFK3E|Q7H)Z+%Z&0bFe)_zCcV7 z1EE9>k-t>zc`n~+&ypOSD=g5x$nysq&ACFItMtUvGuk$ZwiZ3+{rdzsde4p@Tj(O( zH;MyZmK6`FwaYobAOVpOD3P5AlMfm|f1nBC&6e%EA^V8Yxv>x%Ca61a=sC{$@6qvt z@wh#3XGs92DTxkO)bxE`}}8YhPa`&;*I{4R338JskQ2d~kU%e>WMd ztwwVWWDCO(zh@Rdw8gh{knAt$DudlmrUzzCY93;{J0KD3$szh4u2-A|vNwXDEmEl(7Xya`Ul4lh{uYt&&oP zVn`8h|BXQ&Ti00+V%jnS)mm7!f2a$PT}=tkz11X>Sj%u5% zma{64zRaIRgj5wHFT4d8ARa12m4R~*3>AQpCWxOOQO!N?+myMEnGjxte}n35o1GL* zDqN41b#+@591Z1}pzd-y*k#R2?`j9qcy;;nJ&Vlmnnmx5zC)BVYexo}`Uwcp{BJo0 z=hIlD;A<*Ki6beffBRzBWNYwQNatn@K=t5{M$ed>y*1*6* zcM!#Q|MO0M+$%@ErJ*Qqhg>kL73{*JU!gZ;1<`1?3WT-0O=%sp!kDS|Wnnmg%%t0K zHzsK5g+G>fSV67oZjyi~Lg zj5lGzzoVb2D%Omx$ILvONi%GP>Uo{ZhJ60nzJ85c^f8Bhe?|+F?4Jy4SekC*?%MC1 z1zDP%d&zpg$+ohHf2+2EKCy9v5B^z3Z5(R64C97(8*Jf}EG#uz?kpcnW_(7uet@|k z6FM+Wv4SV{;^aauCWg+q433&t_vBiH0_^2j4g0FFM2(f?&9tUYN*0CPF?xY!$O%bv zTaL+(OqIry%||Jg9y(2IF#^o)%?6zD=hFbUOx9H#XOFONf1@I#Ndbp3*$_%GGbnr4 zdv?)ry�ZuDgzrKaZ{pL@G86HcN5$0ee$ZQ-O!nb+KCNbPX@*n58H;HNbhqi%)^O z{a`9#J#tz;q73l57=8Xg!@v7~l9+-fSc)1F=hqIETZ5=e5E=q1q*8B2_X0+6B5@Ud z+<-@{kXMIdND`HOh*pF^QJkhM2PfAC#%;*7*FqP^T*G#SE@^#A|> delta 1378 zcmV-o1)ciCJ;Ob)6cZqy&a{2XYFe%Jv2A<8D7PLi`RS__eYD&MuZFUx^jwUSG!sE# z)Jk@H!c=7b{dyd%Ll`1iF*|HIC46%Uc-8oy#OY^;ng1Xe7ArcU57KY5Z@IKyO#k+OyUZ^a3C} zpiu8%ar9kUu{omjBNH&BCtrH}vBHK3E|Q3=dKqK{P}U^5RRlmmrC z`RP)-IQ}Qm4Q!a9jl!$r(+1G0ftP@0WBPr&b^6?6?6(}_C{%)Ks9Y&c7V0Zuv6GLB z0tjspH4v6e6#8ze(gBeWD3P5AlMfm|f0JuC9*6#yHkDQ)iR_&zX7-6( z22&-NycoEYn)!~M8+6K=YAfEEVa;&?#B&B{U zQhhfEcWLHNrUZuf*o|vnU4_w~Sz>+Xnf;WMdahuPj%6Nr(?Sm=)OfMo-<@Ar*c%L{ ztFkMsqOsT&HzQ+6*E{wZeq3||-l-SN{xH%I*z4lpeF65LaqXqf4@?>@f5bafS@^JR7<}7g zZT3i1a`DOsaI^CeTgyHGwPqY{nKgZUj97g*e2|JwF9{l8)OHad;ghmfw;h|H|B^tk z+&86ov9BMya=m>--)--wh6$??2bWOUe^15!tScq2Bo=ws(!k6d zq&Y#W_l=m=e4*)dr>Dus;+^m}oBUw63`>LE0(kfE=i>RsuM##o5;@>n00S$b;hnrD zWo3zqE!Z+Ahxz~u_&Jc+a*d%A8K3J_w kq#`+<*kNk`5bHFP5SUT6h8#mVcn&uahf+>b2a}H;G_|g(O#lD@ diff --git a/test_fixtures/masp_proofs/D1DF6FEDD8C02C1506E1DCA61CA81A7DF315190329C7C2F708876D51F60D2D60.bin b/test_fixtures/masp_proofs/D1DF6FEDD8C02C1506E1DCA61CA81A7DF315190329C7C2F708876D51F60D2D60.bin index 1a4531f734866a3b3129105b299a1bc6860905d2..b15399485612fa5ac9e264f4eda3343154d362c2 100644 GIT binary patch delta 1358 zcmbQQHeb!)^?wLp00KrJu6IaoT6=%WWbJ}-$;th)Tuo;=b(C5(B%Lx}lsvrI=`qnj z)+6Ta!{%E~+t(jEeV64K-;%GJ173K}x$JFJYIks5>y{0&ATxrM)M?&^^JgaL8uzW> zw{#NRV{mFhTkqDqY2^{+=_cJin-qB~7bH(!z^SA#H)Z#&+dtn~th#E)5Rnq0 zk5hgu;!0UQO>J|+;^57XIKMDCcrNu`_kHr3Lhm0%%J2TD$*%pqH}**MtSkFHWNuvk z+?BjRJ>!}3EzMea-D5K}1wYSR8xn#xT4;5nb)XlDiw|^jGoYK20;r!X_UW$dDo?Xw(NAhA`H;#oR zDO^o6ImWtrvRCID#gb!F?nK;pTF?JC=u&jw-8V13FP-jgB|MpDo(xC+TxSV;g(8<5 zcDvlB82^+v(Os&QSFzE5Q%3bR#+>SR3$HFqUinY0_ZI(ymeqBR9<7o^H=X! zd&2G5!0Y#-g7kVm1Paf06q@zC&P5|bxV|(0YSel&zB(@R<%Pio~EA?|p8>I8U9v=cga z4>3%cqF?O(jCI|zwE54j{A|!DU-UIJ-S^j<@Xs}mb%jqAByzN@G5j6y(6@WfQitH5 z3szL63Msub=GyrDM~>Jhahpl*g`MX!cJHaqoKf#1ZnE%#)#IOuZ?>^)Ij6lxug@xz zMJVty=l9KLt^8GfcL_c`vf~wx$CJAjYqI7}Xz@A16fbl(!Nvbc!z{~}l?&9o8~i`^ zPMpXj5W}$g>dW1eVkSzP@A+u6z+rkpHLuM5gCDeCOC`ivW&Xq~*Qa^(AJyK&`TFDLmQs;f%hvn+cX>X4x|kRDJ(-jcMG}`G0;c zm?XuX`Si`(E(J5I|G!c!#Q4p4th*N5))!p%*d}8#=9k_7zVncW^aH=2JWDp0_KNN{WPU%< zK-NRoE&K#O|IXajD?tmi6<02M? zSk)4?dM1LZfNpo#?c};yUZ&#irkl+^9|8M#5NmNmDtYo9bb)%U=atEIz zaJ2guGM&#aT4r%BGS^z;Y|x$P;&n4@TE9$Qz^SBAv)-w%-!MASO-*@r!Jgl@BlmxM zUs+#m8vgx7R#VL1E1Ms2eqnOBQ?1ptV1}-X?R|bWw%Yg8`X94u+<8#Gg)w&h^FFDG zHaA$_9TZy9_|@z;|3O8mshYOGaPCqTK z2L1fa8}U@+zFgkRg@P^ITlbr1{N9|!tH4w*?Q^@MRpg}FWI@Uk|M^io?X zz|!9D;2&+=JT z`&BQ~`HV+)*DX@M!T!O>$ymO(QsK#4M*PuK&-|X@;a65r8iD~rX=IY@BG0y6y>nNn zDt)nTQr~y;QdijY-38^s)&0!}(2Ss{3aVMW^`!XTlV+m6uV!2 zC$AoQ>;7HTF^K=ZY{CDW$JtlwUj%Kx63%?>Usq`x|I^PmmNXSyW@$7{cE2?5+Mf#^ zaZ6@%?sMhYuDPd^w|w8rrPEpR0&Ap0Yl;up&40DVpi|m>+qNB>BVJq0`bM6{2a)=B9;a_S=gocS*^})bgD)N6%Zl%Lm+g1FJAO;O z-6!53Dgiu?c%yBaDz@r83Rj!4#Li-?S&`hY6xLkF^L%GG8y5u^~qEZ0yVEbMb%V+cqbLmI)~?|2N@^ZsYW3 zm1FI#izlp(@ykoPnXz1dLtVDm{u?KzO}??t{o@LbNps9A`eXj{&zPR&wNpA*{mb$` z3C?`xeNuNO)!V<`F!@w>#pCyk%#%MbDH(C5`j*rkT=;Y8Ld)ZyeUJC3TJU==UpIY) zXXJC2f42*ES)EI}Qgzzm$rE$mkyxj`d-bn=y4DM|37P5Nn z^XJiyIWFzo-cE4VLGQ zbexR1kpFLKXy3GDOj&!c%y>L6$!>Z~mF|t^y7fowcHjF~)lnysAg;#q!M3Vz_qEHM z?^XV>v`vUSYs`F-x9?L_$bsMuz5f}^)C4s-c6n^qN9Qvw&5paegeSy%=Df5w=x diff --git a/test_fixtures/masp_proofs/D5A372904527694939249FA0AAFBE1500FF70DC4F2365C83D9BB9015D3C28CE1.bin b/test_fixtures/masp_proofs/D5A372904527694939249FA0AAFBE1500FF70DC4F2365C83D9BB9015D3C28CE1.bin deleted file mode 100644 index 9ba262b0f395cf26c1f7114e31617f887bdce89c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2045 zcmaF;9|9N|7#MCZls76{9xWcpe2K?QbbsG6o#p1H|03(S{vG1Yo3!f$!^5wvKxGWE zSGS6)DLgZo&2n1G&E9%*AG?PSNSxs{&@7@1lIQvbwHHi*HG>F{W`>s!CW=eFoLxCJ z^Q6S9Y?K40hTCVQ>j)tTyjQ)(EGiE$a8XF52S?ZUUG zt7Xf&r+x!Dd=!k>5MToOoJ)PV+OpFBFF}C-O4f|TrcNCBi7`B9!R5{^h99!Y^QhD**$dU)M{m04P5G`h@t^VKCxorDQMg`6PE)cwLpb6>Wfpf{i`S_qQH(4sAwk_XH?~&qm>vKA ztMSqe_d?no3Wbh1ZI-uN%>MkSR@Jp4wlxKck2ZW;Hr>-LO=;%tZ%h5dlEi$p7*{GM zF4<)M+HB{d4An`cH;O_VRu)b2ihUEU=5kEGQ%15d&SJHerPz&cIo@-22ias81uJCn z);;L>=*QD=NA^IgESsBw$=R8^Usm0ATfVk(dOmOG+UY^>mmi$l|6DG3{RdH(`Tut( zxZ4I@ne`+pqVVae5_1pjkO}Xvy41!xYc$s+F-UBvb<^WBZw?bEkr&DSs#0I%$D*0y zGl$J+QsF#Pk7MqaCNO3`JhY=|x!az_=NPuDv|ODsVe9Kk>)gmQSCL zPEL3-ah6Zrfs}$H9zHztkBe(=G3m;@Z$5t~KRauL@^;(38|p(8@|PR^&wg0^Vb1UH z$pIceB~?a{LixPKIe;os>;~gR@?q4@67vP^m@IMQ{CHuUFSP?tL!~r zE1l)F=)B?K$JT2Mw<<)s{Cb;bw*JZsx6{&*cW$eFKcKh%$Xu2Khm8$u=gd=I91-#H zo{ZrwVU~|J{#&lz=C11PuG_+OWM^t${A-V2h9|BxbKGa$^kB+9mj(qtxz(#Wq95|z zTfWqMO~hO6pk@699=kp$TwW6@_v^&IoNi_-5tr!(m5Ka!KArip>A}hBRcZ|l&)=_d zozJf%yEJRbkw*3D+BdvVnytvQX7oRMCy}RhGk(@`zZzv%gA!BOmcKz*rFAGvrZ{Jp5c0cf1hhw*uMz>HJcRY zpPM|b^OTIo?U;zu1uxbmAIw?Lzw=9$H2dSq1$%e;n}={kt^K_In&oZo_-m`=E&wtCZ$SF`^Ip@Lu`Lov*)G`Rlf6CHUNJ`(ux28 diff --git a/test_fixtures/masp_proofs/DBE07FDEDBF79BBC814D3EB70E5A0AD04432D0D4BB8B2488EA5E836837B00394.bin b/test_fixtures/masp_proofs/DBE07FDEDBF79BBC814D3EB70E5A0AD04432D0D4BB8B2488EA5E836837B00394.bin deleted file mode 100644 index d39344547dbc331604dab3d6c2a89d96ee44b084..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2045 zcmaF;9|9N|7#P++Jg{)Q+%Tg=Z$SSx!s2*;{Y!WB2d@i8H(gnnjdBIj1_H_JS#}W)K0=%<%HTL~*H?vn!{D zoMkZKaKH9|S19!9x4a3HpBdj*5;&1lw3T7wydS(~bIVr~>*9ld%QF`K&DvGiy4-7L z|1qI+Q5`QbethHU0KO8I{#y|8d)v^-Vx>0gqM!KoR{lPr|pyTs3Sx#%=|epJkn zJ*QXvxq6&ukx}^1I8oD-=TYxjrfhMuHmDFhp(wF7d}_S?QTMzl-?b+GGrs)f&?Whr zJKyK8J}0#Fxz>vtlC?7m*9*yMN_J-mM_j1P;?8UFI`t%qk%c8BsN3eo*6JOzm%tra z2OS^%cpC1=9%z+ib2BhGJ9GETs@rbM*H%u?=j~iOJ?Q=NgLC_z%LT9hAnG#z|Lz2L z+n_76o1VFD%cBH3S6>WlnXG*f)$ zuo+D%oM-BB%>B{?#>|I@b`&jl+q3u_!*-RHt5YUyoge(~SDww)dztem{&?H+>GRRa z2~Q@@@~JzJQgFn>hiCqAam_6zU77dI=kMfaXN^$aZo79weTYK-a-;v*4~sv{`5itv zASFJayEgS=Qa>d=XGp8GGAm+aKkfc^`~kuXl2)dmFIpe8+B;z2|GC zv%D6aH$42$g-DlQZ}ZI7UwPqnS~~L1ZME+Q^wuAl%W~kbv0?3;dFqQJB0k=e zF}x+r^3leB%hlW5RlVJHTeyzwOzn$*?eWX-#Fb`_`>dNDOxfqspx`IBdR0gCL%w^< zmzuAMc&i<>tiQlx*9V2mYeMCIo!FPt&1@y>opuk^j!8Ghd!>`IE3)-E8jRT?(_D=CyQV2E_!Pu=h5+7O7-Bm zjLM~q!3&+&dbKexPh6{kSOeaL$3+s9CSKy@)t?an80W`D@wN=zqMY_nW(W~@B0fMzj>(M{eSJg>XYr&dXG%Lb6>5D5>+X+ z%B}D6ytiVfc))|wm#T}zrX|NJovBZs;j_Hx!Vw$i(sCbe&S%qS7#upp^)~wR(l_iJ Oup${;wL&>8P#OTZ?AfLO diff --git a/test_fixtures/masp_proofs/E1D883F9C9E7FD5C51D39AE1809BC3BBACE79DF98801EB8154EA1904597854A1.bin b/test_fixtures/masp_proofs/E1D883F9C9E7FD5C51D39AE1809BC3BBACE79DF98801EB8154EA1904597854A1.bin index 8cac916954e11697d45eb755016e7092e6fb521d..bd7d8bd196d23ceb71bf2bcfb665d7261be5c920 100644 GIT binary patch delta 1228 zcmX@Ea$Lpm^?wLpfC5IFCC5(+NBmwOH1*rY#pw)gzl2xHcD?;R-=a7qYih?E$%%#s z6{mFgb)xyqwa~{bA6~i(;QtP+-qRYuYV>2fD<{7vDiJbg{ zLrFnW_vg}=+ua+kd}W?wn9C=TnlE0r_9@qy*{Xk5SOo1owAqUD3zI{KW=Z|sb7vL? zD62*O>Aw79<@O2bLY#9O7s?BB_%YWie4ey#cW$QMz29HW-po!v-E3-aUlNkLccr^W z<>YNTH7=9$cuW++O?Ex&+AqISWmfOwXBR{#@^{-^iQV1h{G?uiXXlqIJ2oHUQDCaS z@U|%A_S?JnCl;@J%bS~XMmyCyby*FQ!BxvQGDXx) zxp2aBafiXVpS?Ww;`YI;3k;cBmY8jy;~Z|9#+7ciJnyBTs&7%^{cQ|)JN1~mo?QA~ z{YX81^>4F;bqO)4tA)0Eel+N7Nm25@W&hA1b1@n!z`yAE7v^KmUu3k#FY7L`jhCe=%BwTXV;khbM#+ZENr~-(lVd?CBHaW z=SSo!eA#0rCNIC*)8eqrhP=~GGC%^i+$tk2VG gZ+>1;Jx_1RmKFOi9Q*UicX7nhxidH>D+{Rr0E_xrz5oCK delta 1228 zcmajc{W}u~0KjouOhYm+3ERvPIaecMtt^z6Jua_}(#wU;Y%6cOHF4V-ze?t&b|=76jE2%2@ZUlwub=8LV66D?nbL!Vqe)(zgte}5i2#?sL>IBu)KssB%* zLD@jxde7vSx}+7j{;MJKrMR1+XZNnoeOildZt>)!SF5{$`g2(wHNP}Sc%VEkF zqsEzrHE9I+wpn?OhxmsD?($|NLN}>N5myGBT@gMN%npCO=Z!ilc+ekYi~N(g*i=ms ziZS5NK;KJw`K6KKMAf{TZ4I@c{B)-AUAUz%XuVN} zJZ~?1F#r5Sm{->#p9G?rL%GQ&o`|Zr1ZZa(ZcF|*`E>x`` zaKs7|1dz!`oh9gv?u`0+5v{HeJ?e)o@ptL~uZ;-dFUQ_Le&+_~-C)UzfwgpwZzMM@_F|qZEzX^0mgZSC@SWXZF;j z2A&heIQ`1OT&g8s442bG7>sr(&alp5iv5ig1}U6-PPCixwi0keh4RaIkpA`vfuH{O zOWIu@xYYJNRYv8sWY{6RrT>Ht8^b(3CX;Txa)*~0>Nh#b$YJl_`%w&n6s7-0W?Wx+ zt+TxK!tB*(y~vGueN)?du!pAGB7Uy9uWYT{Y(GEqP$c8HXXitood#+^4F=Y{U^lSf zT83jeyJFZL3Q^+c4oP}SYH4O7k@rR(mm$8-y7nM`-h9SB%eKkA{%10^f@y8(qbKdH zlwylw2dr#b1F7fDO4M5h8rKG8v0yCY%b0Rovjg{j2xyt)EYJdN*0hKmHY9UnU1^gd zFLR7>WgAF+90osQX_~me@mTP%>Mbe`2=B*U5N}8p@s+thA}#}BeT@YN(+>AWK4ZYD zZ_uG9=UCJvLQ*z-iRs*)7KLx($1Ph-GaSN-d97D&jz7$G_wr)&oO_vKj6$Yr7UBuf zHWq0`f3)oma*^=V;B234_1nM+{nlOEX~ANPcGHqKm|f%a2-T_+zD0$$1Zr1tN@KMr zM`2IeNG*szIC+96stWIEqRN%Gcjwv)uV!Q@osHZ?eaDzTHFZ>@Hht(i;$;->p&;TNA?KY>IB*hjG#MrG>CKkaI>XV(nGCk?g{Kvq zM@G1&?2LEmi$hkWB4fptk~v%z);q}>HkgtC1wYwmaI$Ed!Z?H&00Ma%`c6HX(r!>* z422#j2_jnkF0a^}rW#1wS8LK7!J966jJ8X6^m4jYnK#qn-vJp@$)?MuVrIdTmQ57X f{iL2Aes33)6hq>e5rKwsm diff --git a/test_fixtures/masp_proofs/EA7A88B1429EFFF0AE7167F6FBEF52D368B771AD525817E722EA3E12B0A96971.bin b/test_fixtures/masp_proofs/EA7A88B1429EFFF0AE7167F6FBEF52D368B771AD525817E722EA3E12B0A96971.bin index b1fcfa75c24ea8255db0cfe4fffc9291eeb62663..99465fb26055f553013ee2b0a13c5147fecae99b 100644 GIT binary patch delta 1355 zcmV-R1+@C&JK{UAixD6R3y5gsd}nTbZ_S430zz#Kh4=uw2q}(k;?R}_bK%94s}VpT z2r1v2Zm`hdNDiXqaXoBdGQwF);UQgZDPzN>nLQw1lM50-LFm92qfZT%_1{`wOJIVR z0n(?2i9{}=Vb4Cqz^t-tFajVecp12$A|I48g~4JB{ z81Ac~<_xgrx}hf9(|?wA;uiFO_pgt|2-O1@Coa5&Ko9fB!V8ZEVuo5>TnWa0cFk#l zs9Jmu>qN~e7`OE;RHAk#^T`Q`teWSc9Oz}Y;<)2e5|BIt`8cFb$qESK3Un9p>_GCJ z&CD01O#FS-mb>nm1BGo|k3|ba-Avt=Jy#%~tHt`kdq;NY6o0B5nbr@ZYvX1d!Wftb z*O>qzba(io3u!HRp`>~_G?`!>3o4b-MEW;a_?ufMq<;_$e~M!KG0Lw#>MHDB=iJ`D>l6l=QFpE|M`b3`{Yo?>i*e(cXVpc# z6D5-#fMeN)5W@QhX7|rs{scbVDucqF3PZ``mUwSzGUbU`L3gemlLtbe;(G+FcR?xi z#=(Hl@AgJ16$xqTI4$gbLr@|vPiZUu~4duGBgaQvKyv-Gw? z(<~kDnbr41!PMYtC1T5)c716_}Q4lHb=L zU!N8II)C%8i?bF~(5r?LAng+JoCwiXe^|w;DD3;u&3ZwXD# zB_v%-M^s)CNx@^DQT!Ra?{UGd=fGkOoEcXmTz_7QmLBv^Zt&})RqDDmEuBb(iqL3F z3yms_NYGk2 z3-Jlt_A>mfzUL5&v-5)_%dBTiSYyF_!B^4!|Nr%vw}=A1Yzpq+LD&^$P{QdCbgG!E ztbY<^`al>R7L`^RDX53O;AjZi1}^pR4DKB^3$Fp7r!>dpVgg^hQQMKm{PnUv++7aQ z>vnzdfwK~KPaMBIC(to(l|w}Cacbl*&TqJ1n9MSP_CruC{RG@8Zp^mh>d44CH5O8C zfDUR5--t{6U}Q*f57IT0o9z z+Md>g0lsHmeJFbIOCcJNJ!?F^e`Cv^8LfJm7IO!_zYH4e`R^Q{dK+qaZ#ALwTX?m) z@GdbHd5YJWI1BFK5D3~)trMIe>NcqS2qB=>C89@^OMfi)_3|-;_@x13(-=?XPY74j N!%QF3n2M9N9WBF)nDzhw delta 1355 zcmV-R1+@C&JK{UAixD7CJTWjU!`7tdj~N=3hMY*^q`W;ubeBWsg^TR#PrC+mmEdp}rJh$=c`;%6DbNBD=#lYwnp7iBPD)OUSYRXQo*Qv9O z67&KfNy6#+6YFd?*(|M;gC4yw=OzQ&mEiJrLfHTJ62kkbv!NB01Am2``<>u!#4`Vr zd3C?G<>UXsksgFNAk2`T{&9`uo~S;_1wG8NVem&wi|%@Gz6z&diEy3aXeU%`B(2<+ z@JLJ4J=IuicItNm<0Cj#dpFau;8hK`KgofAoCf;KJ9rsPeHh89YRY%oW9^|&_F}4d zbB&^%UhU40{3yF|1;Yrm74635_br7QxE0JE?qrD^e90=kMIWx!#{;3B!2yFUEMI68S(Ahtsx z)ha&T=JPwJ%75U6ArB@@EkCb0|MG6Fw=MMC!X_nR@k4#O`8HDnGhZF55MRInH3acn zKbsQxS^^1;9h~qM;qR|rTYeEI zz11lBHv8Yw`K+i^a0Tj;#!kzCpx{=+$EWRWLk1(V+S@qSxVo1G2dP6R}C2T!4-`8C#c_jVO*B&GV2pk5ml9FhIdznvxnzZH(B2*rdhr^FN=|A31+z?c$^}r z_An&A$F;F&x%1a2cS)_5%2H_B8R1<<%dsS-&z}9+$2J$Nab(hED+AEMx68@4_VC+< z<`O#+dLKD+U*JqX6FQi>EJTYQ?GNaU(SM1?qNwS!74BIv%}`J}TeIfAKT&<{MLLj! zF(dmHxXn4c7_vVu#CU$yl0td9NtV9N#vA{fvKH>9@Q}d4H>?Ldx=Er(=fp1iC6)<} z1|*f`qed}5v&Z>>3PlCXruQB&h1$ikKJ61S9WX4P62RD=YK6pFCHO?Fx#_e^rU)U) N-ZI{7dRUXS9W7kDqksSa diff --git a/test_fixtures/masp_proofs/EF7D15FBFB9CC557CC8F9D4D18F7858007C4DA521F8E3BF250A46E9342178EEB.bin b/test_fixtures/masp_proofs/EF7D15FBFB9CC557CC8F9D4D18F7858007C4DA521F8E3BF250A46E9342178EEB.bin index ab64d432336b662a53010693926fe9fa92455083..e4c74d543d00eb21d287b880c50454a6ed12b9fc 100644 GIT binary patch delta 1964 zcma)7X*3&%7LG)1K?F_I5)s;>7>d|xsY+98ZFxg1ZxltUOwgg#HsUp%p_CD#gA%n< zu_TDCtrRVygi%dveN?Mx=!hw8cT4v5X_uUK>G2bd>&$}F0ZMZ(jgjr1Xi3wIx7~H=PyL;%jt-{9#m4;H&(@xjV0v=qb4PVhC7e83 zA?(T_rMIeiX)FCO9W-C|JmX92%u+FoI8qst@{@AaL!yF-VgzNeIs2m}Ll=XaR@hzJ z_9`76JV%v~I7`~E8tC(%%KaJk6HWyBYnVUc`pCf%wN7+cz|$XQ%*&|cbU5AdR_HXq zxwZe&@KyoH{**X#QeqE?EG%mN?UVBI$=rT3g#BWLlK)tEf^AlEyMGGk$HV5?aH_)r z6iLR6mjqmf1V1*IH*^(-YcH$iuH7)+Excr+D$buY_eIi66-gP+z}6VhN6hMxck4Y} zN$RI-Ui7eRb9%6Z2PmWnI?JbdGYX?`$6kwo&$+y-o5l9dMCR+!@XF?y?Z=QBVQ*gs zRsWKT>GLJD9SEuQ(6ir(F`BQOD;u+m8eSO=L@I<8UGxhtBcye07n>~IPQiI+aK^E6e@Vupf;+wnD>kZNY%RH~-`(p0?A zZQm^F^+4}%(04N*d`~(rY9qh?3v{l_%7GO5 z{J#hOYs2=t!~L#_HEPdF*z9KUr)@3tIfW#sXq8NrZM!c+Bgjmf=cQW9 zksO)wi48B(_=iY~qs$@7LgWG@Sf+!6BE5`i0d7iC+4aXyodr}yzsEX7&2Pk#e4*^R z(446tlyz{t+>9&bLUC-x!1<7i6S@RQ)HP5fL)K8P94y$H_r)bO@{ZBIO$tPbx=PeO z;X31j@@hHTYC&hL=lb4BP#f+dPG_TA9qa_qjFOZpVX$P-Cl#}hLMO-4-guXM*ln*J z$!qTA;%&U}1>{8_3W>1GA0~mXC}(+~+Z^?wKcyf;|7|{0BH7(cEe>qwCwW`XW8iZ-RmpciJ2n~t%xRa@Edxn^uRMq z2g;7vFoEGzwKNC`)VFA%DL#k)9+UNL`&}=i+dn!` zVE&J1=9(7b`bM(>CrR?gsqj~odvawaOV?qkOZ6zT%0(tLh3x-`RoKqwNNxL;3f{Rb*J zMA;~@g|L}Yj(>4E%FS)#+?I_+PlEZ|R~sJbCzPyeHgxLT#7R#_kFyd=e!p|aTYAl7 zI_Z$yv%2~zFOLSH_p1X|fgMAeK9X5Ub``-=JfbyC^-;Yi#`j?DQt7=UZOJgZTfNll zN4+ynp2Ky}z!R5XZj;K@yfzy#I=mbQh!chk4Z-^$_a24^Jb6u9lGX~&Ek=|SxTf+b z+@HH#OzAtuN+fUmo2`~mZgYVkv!>H$wZ$`0M8Fx`KwNQ&&M-=L)aP9z#*+~tYdm6n zJG7&S?cP|TwyICB$~!!s#!saMj|qs4+T9<)BlKwQuaV9CH?NJjeh{!VU}_d-Ak*cC jAb-YPeV-5dX2NPVaO0uMVSH${c^~-etNe-_nEHPJln=9o delta 1994 zcma)7c{CIX7dOT_62{OFZ|1WOku7QLV;izB@n-C0X*dZHrh1cQtRY)Nh8HDSr_7Lb zIzl|A@C@0vH`xnWLNZ^y<&W>5=lh*=@BQbV`#Zn8oJ&?As}NS%e}UsW0N)KWXj&Lv z3Q`w^)qn-tun8Z{zYq!7^5v?=KHf? zz&GfdQJlxn@Kk!*sLVK<97igSdfsBkwHxzfk3jL)M!{S^1<_ZJXdTQU@Rtk@N?Uc&jn|YK<$x zYbzF6SoFeBe6m!GS^_ZVg1gzs4JwJUE^$_7$cLIrc;~lNj3N%4zC0h=<+^1S`hb50orOzHy+M^(T5wUnIXK}t1^u( z;M;>R-7TXiix*YrrIus8XTnttP*8Z5yq5<(kssTv60uTTl;6O6$CQ|1#Dl)p3U1i4 zU|xd^kAV*O@bR}QWaq&tccaE|vNeaDa(*NoZ9P(Lko zdlBxPq)B}pnIJ>(Zpi}V0(>O+H>Jh3%>uQJXGEH_t@$r@s5+JW3iPhC&a8SJ6aHT8aQ#OtKW%$#=l(9vv;o_WM1z@Q8@acm;VzWxP~#QIm2BVk4- z(~us{F#|qF`;9AH;Hu=GJT(-Qj3*dmBgcrm)gpWC@mvKp078%W% zG_TRgq5F0f)|ESyG&c0DW~Xq`^BIe7*-#bPV-^sDVgqEmn0)H*5R?bCP^Y*m55YGoA>iGxiQ-M^@)}BXZ&%Vo*wQO2WmY*R>N$GWGT<3 zr`4-@dJ40I-A60*PukMmgSi{kxLy+iO)=eN>_Z^bRbH1d=FlvYze?f{(lT&3Xk$ZnCj+aG1&L_%k z0$)vBK+=FqMGNPc_Z62e6#K|U^Vyxm<1J(*Oa!Ps?}S~2@h&)j%k6NV;Lnv1IeL{5 zg(-5f02SFjt~)#+N$#WB-SpsVYN1AETYx*j-OFUURR#AYkuoN!m(|uKhSM3u4w(E* z584-;KqpJ~+#OM;1$!!J5EOZr@7%j`rYy_)wdjyvK!5V3Q&OL!x_H(JS&xdD!a7xY ze;^=$yDw1rPI~ss=Q7tLFk11!qA?F!_T;o5VeU@XvcQtPjzItd)f=+vp5fB!eKbbPsO+TozXsd z>&aY-FUkFF$`0QQ29}7hIl+t@YU8}RV9&#-Lx=51l|srbMBm2{Je9jMw$s%3Ug#LyBw^nc$Fd8um|y42o_ z;I1fBHq81sp9j?^9PatrOzvN%JISR8QMI;o9?&9o32~s-8qv`3go^v5oxa>~<@!X! zl(zJj2(_bY1oQbs)IrBrC3yKwc;wBVOfV&1J-!WQ>&KDf6)-;8zNKjen-#)f@y`Xj z`fg`W6@Bw~Sw6^~b93;2{OPkkwe@$GLw2ibZAYr{AKW$s#=`YBbGM1?#Y|{kv5O>N z0qR-fzp<+tcCug4?2Bf@l;ZfzzVcFr18xPPDA5U;h}UY@BXv=ZH0Bt4-j<(WFV{?= z)I2`WIfk-`I|R$a#je1`Oja+gj9}93N1mXZLMp4>tAu^}53w2f4PS_B;?>h)JU<@k J4`ho={TG(E-pi4^0&PF-d~QEFC4eQ#?1kRlMY$H}}BTp`Bc_yaOcz ze}F&)Di0{7^NdqIB0Qa+$u5X`kOE112(&0Aiu*97prYo03RayF$3EJ$B^!d zy%1;UYpVt zuyBo)aGNdpvvO#@tz+-8xxERh!6z4Ef1KN7q?qOdafYrle-qhca;$)t-U8mfpwe5x zs|lc<>=1%UuyuMG#taRv1Y?})O0x&^3Wx8HRdtf=f#mgA6q8OY^jdh%h+&StmE}S! z1<>Xc2#|>ovQ4XWDQpzq`R6G=KlQi!WUojN>e+3ycpHdYaOIi$45eZJoQ+W(0wfEQ G;RhTv_m?98 delta 308 zcmV-40n7gV5B(3YoC6>RvVrYnztuGu#A@Zw9AV+LUMz&a>i8%5fF?U3i2$#&yaOcz ze~;6`ByB|TQsg=i=AjnFAB}vU9#5v#NDgN<%&C#qN8Vw66vm!}c6>(=tgy2Vyo3#ufSPBcvRV_xp|5rx0>}xI G;RhT#yqvNC diff --git a/test_fixtures/masp_proofs/F7D91D1E43AA598631284A69E9861C7F98EA4325D94989648024831E350D8F98.bin b/test_fixtures/masp_proofs/F7D91D1E43AA598631284A69E9861C7F98EA4325D94989648024831E350D8F98.bin index c3214e3d3438679029e06d252ff94293badd8008..38ecef6e7bb35b24fd680fa427af6c0e3c32e422 100644 GIT binary patch delta 307 zcmV-30nGmW5B(3YoC6?c(L4#`-92hOWiD7CCnbt0ktjZo5O1ILe|#i}vKr8{yaOf! zf3*l0QAJ~+gde@hG8D8`L2~4sjNZbi{a?UHlv}tC zewDF=5$o}Wo_f8FF{rf?uliV4_#e}+>WGQ~%-m7J6z|<}*S2!yM$Cgn0(wnrQw{eL z&S~U1TTZ8xSrb)K(J^AH5Ek7AGfjM6e>SL!MEvX{M7G=AJ`|!6Z zLdEX~fmuBic3bJ<#|B7y=$BTgjoZ22TXZNxkn%ADxy`BIGL^O7I|2%lIQPeEthaxu zWW(3oH--+HS5z)#0Q?vs*jl0;o}HkSCuO2g+hde+6W0lg0l+IqtVV|Ez(9*)0SlAi F2OOD;kkbGF delta 307 zcmV-30nGmW5B(3YoC6^H2`|CFMp%vhr*@WdZ-E1H&DumgQLiHVLl-_oyMrRLyaOf! zfBa8T{qj=89#yH)=|=vSw#0{H_Qn&GRL_vPXB{p$QkB+=m##hGXBp-c7jY$&plR{Z zkV2dAF&S*#&u|r5Sa&Esx-Edw{py4MJR<_uqqR>V^;XoN9jtqNNnQ_51w@3aHF&rA zKgc)$mj7XI7jFN1o5h9|Zsk$o;IEGrf6BV3^4RwBI>4>*ljCI3tA;BHUGxr{CdRfc zZG45|!ZPQ5OCcPjf_^hChixAFb87Drti$f^&z$EinlML2)8sUD)_IGPc6uD-fLmz* zPOT_kV~q>Y9yMHMbX1m+>0amX)OMo1d!#e;iQy^=Gj(&UEVm_AScikNBEgu00S1%d F2ONq)nJ54N From 4456603b21c8c07b05e708376d4776af15dfd295 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Wed, 31 Jan 2024 16:55:36 +0100 Subject: [PATCH 08/16] Improves tests of fee unshielding --- crates/tests/src/e2e/ledger_tests.rs | 32 +++++++ crates/tests/src/integration/masp.rs | 129 +++++++++++++++++++++++++-- 2 files changed, 156 insertions(+), 5 deletions(-) diff --git a/crates/tests/src/e2e/ledger_tests.rs b/crates/tests/src/e2e/ledger_tests.rs index 48daa1bc71..2f9e7d4da5 100644 --- a/crates/tests/src/e2e/ledger_tests.rs +++ b/crates/tests/src/e2e/ledger_tests.rs @@ -694,6 +694,8 @@ fn ledger_txs_and_queries() -> Result<()> { /// operation is successful /// 2. Test that a tx requesting a disposable signer /// providing an insufficient unshielding fails +/// 3. Submit another transaction with valid fee unshielding and an inner +/// shielded transfer with the same source #[test] fn wrapper_disposable_signer() -> Result<()> { // Download the shielded pool parameters before starting node @@ -759,6 +761,8 @@ fn wrapper_disposable_signer() -> Result<()> { NAM, "--amount", "1", + "--gas-limit", + "20000", "--gas-spending-key", A_SPENDING_KEY, "--disposable-gas-payer", @@ -783,6 +787,8 @@ fn wrapper_disposable_signer() -> Result<()> { NAM, "--amount", "1", + "--gas-limit", + "20000", "--gas-price", "90000000", "--gas-spending-key", @@ -798,6 +804,32 @@ fn wrapper_disposable_signer() -> Result<()> { let mut client = run!(test, Bin::Client, tx_args, Some(720))?; client.exp_string("Error while processing transaction's fees")?; + // Try another valid fee unshielding and masp transaction in the same tx, + // with the same source. This tests that the client can properly fetch data + // and construct these kind of transactions + let _ep1 = epoch_sleep(&test, &validator_one_rpc, 720)?; + let tx_args = vec![ + "transfer", + "--source", + A_SPENDING_KEY, + "--target", + AB_PAYMENT_ADDRESS, + "--token", + NAM, + "--amount", + "1", + "--gas-limit", + "20000", + "--gas-spending-key", + A_SPENDING_KEY, + "--disposable-gas-payer", + "--ledger-address", + &validator_one_rpc, + ]; + let mut client = run!(test, Bin::Client, tx_args, Some(720))?; + + client.exp_string(TX_ACCEPTED)?; + client.exp_string(TX_APPLIED_SUCCESS)?; Ok(()) } diff --git a/crates/tests/src/integration/masp.rs b/crates/tests/src/integration/masp.rs index 527dab7e08..a07fb0f9dc 100644 --- a/crates/tests/src/integration/masp.rs +++ b/crates/tests/src/integration/masp.rs @@ -1450,6 +1450,8 @@ fn masp_txs_and_queries() -> Result<()> { /// success /// 3. Submit a new wrapper with an invalid unshielding tx and assert the /// failure +/// 4. Submit another transaction with valid fee unshielding and an inner +/// shielded transfer with the same source #[test] fn wrapper_fee_unshielding() -> Result<()> { // This address doesn't matter for tests. But an argument is required. @@ -1466,15 +1468,15 @@ fn wrapper_fee_unshielding() -> Result<()> { vec![ "transfer", "--source", - ALBERT, + ALBERT_KEY, "--target", AA_PAYMENT_ADDRESS, "--token", NAM, "--amount", - "500000", + "1979999", // Reduce the balance of the fee payer artificially "--gas-price", - "30", // Reduce the balance of the fee payer artificially + "1", "--gas-limit", "20000", "--ledger-address", @@ -1482,6 +1484,40 @@ fn wrapper_fee_unshielding() -> Result<()> { ], )?; node.assert_success(); + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + ALBERT_KEY, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + assert!(captured.contains("nam: 1")); + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + AA_VIEWING_KEY, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + assert!(captured.contains("nam: 1979999")); _ = node.next_epoch(); // sync shielded context @@ -1506,13 +1542,15 @@ fn wrapper_fee_unshielding() -> Result<()> { vec![ "transfer", "--source", - ALBERT, + ALBERT_KEY, "--target", BERTHA, "--token", NAM, "--amount", "1", + "--gas-price", + "1", "--gas-limit", "20000", "--gas-spending-key", @@ -1522,6 +1560,40 @@ fn wrapper_fee_unshielding() -> Result<()> { ], )?; node.assert_success(); + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + ALBERT_KEY, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + assert!(captured.contains("nam: 0")); + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + AA_VIEWING_KEY, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + assert!(captured.contains("nam: 1959999")); // sync shielded context run( @@ -1535,7 +1607,7 @@ fn wrapper_fee_unshielding() -> Result<()> { let tx_args = vec![ "transfer", "--source", - ALBERT, + ALBERT_KEY, "--target", BERTHA, "--token", @@ -1562,6 +1634,53 @@ fn wrapper_fee_unshielding() -> Result<()> { tx_args ); + // 4. Try another valid fee unshielding and masp transaction in the same tx, + // with the same source. This tests that the client can properly fetch data + // and construct these kind of transactions + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + A_SPENDING_KEY, + "--target", + AB_PAYMENT_ADDRESS, + "--token", + NAM, + "--amount", + "1", + "--gas-price", + "1", + "--gas-limit", + "20000", + "--gas-payer", + ALBERT_KEY, + "--gas-spending-key", + A_SPENDING_KEY, + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + let captured = CapturedOutput::of(|| { + run( + &node, + Bin::Client, + vec![ + "balance", + "--owner", + AA_VIEWING_KEY, + "--token", + NAM, + "--node", + validator_one_rpc, + ], + ) + }); + assert!(captured.result.is_ok()); + assert!(captured.contains("nam: 1939998")); + Ok(()) } From 7265cc5617138acc24ffa497e765436e07508f4d Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Wed, 31 Jan 2024 16:56:19 +0100 Subject: [PATCH 09/16] Returns error if the provided gas-spending-key is not needed --- crates/sdk/src/signing.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index 1519b1ae49..2324444d20 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -623,11 +623,11 @@ pub async fn wrap_tx( } _ => { if args.fee_unshield.is_some() { - display_line!( - context.io(), - "Enough transparent balance to pay fees: the fee \ - unshielding spending key will be ignored" - ); + return Err(Error::Other( + "Enough transparent balance to pay fees: please remove \ + the --gas-spending-key or select a different --gas-payer" + .to_string(), + )); } None } From c5b0e00df7755e90613fc5b0939255d38f62c532 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Sun, 4 Feb 2024 00:36:06 +0100 Subject: [PATCH 10/16] Masp commitment tree anchor update in tx --- .../lib/node/ledger/shell/finalize_block.rs | 20 +---------- crates/namada/src/ledger/native_vp/masp.rs | 36 +++++++++++++++++-- crates/shielded_token/src/storage_key.rs | 20 +++++++++-- crates/shielded_token/src/utils.rs | 5 ++- 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/crates/apps/src/lib/node/ledger/shell/finalize_block.rs b/crates/apps/src/lib/node/ledger/shell/finalize_block.rs index a65c2af8e7..d963e8f92c 100644 --- a/crates/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/crates/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -1,8 +1,6 @@ //! Implementation of the `FinalizeBlock` ABCI++ method for the Shell use data_encoding::HEXUPPER; -use masp_primitives::merkle_tree::CommitmentTree; -use masp_primitives::sapling::Node; use namada::governance::pgf::inflation as pgf_inflation; use namada::ledger::events::EventType; use namada::ledger::gas::{GasMetering, TxGasMeter}; @@ -13,10 +11,7 @@ use namada::proof_of_stake::storage::{ write_last_block_proposer_address, }; use namada::state::wl_storage::WriteLogAndStorage; -use namada::state::write_log::StorageModification; -use namada::state::{ - ResultExt, StorageRead, StorageWrite, EPOCH_SWITCH_BLOCKS_DELAY, -}; +use namada::state::{StorageRead, EPOCH_SWITCH_BLOCKS_DELAY}; use namada::token::conversion::update_allowed_conversions; use namada::tx::data::protocol::ProtocolTxType; use namada::types::key::tm_raw_hash_to_string; @@ -599,19 +594,6 @@ where tracing::info!("{}", stats); tracing::info!("{}", stats.format_tx_executed()); - // Update the MASP commitment tree anchor if the tree was updated - let tree_key = token::storage_key::masp_commitment_tree_key(); - if let Some(StorageModification::Write { value }) = - self.wl_storage.write_log.read(&tree_key).0 - { - let updated_tree = CommitmentTree::::try_from_slice(value) - .into_storage_result()?; - let anchor_key = token::storage_key::masp_commitment_anchor_key( - updated_tree.root(), - ); - self.wl_storage.write(&anchor_key, ())?; - } - if update_for_tendermint { self.update_epoch(&mut response); // send the latest oracle configs. These may have changed due to diff --git a/crates/namada/src/ledger/native_vp/masp.rs b/crates/namada/src/ledger/native_vp/masp.rs index 7c3f3dee5c..52e614f485 100644 --- a/crates/namada/src/ledger/native_vp/masp.rs +++ b/crates/namada/src/ledger/native_vp/masp.rs @@ -25,8 +25,8 @@ use sha2::Digest as Sha2Digest; use thiserror::Error; use token::storage_key::{ balance_key, is_any_shielded_action_balance_key, is_masp_allowed_key, - is_masp_key, is_masp_nullifier_key, is_masp_tx_pin_key, - masp_commitment_anchor_key, masp_commitment_tree_key, + is_masp_commitment_anchor_key, is_masp_key, is_masp_nullifier_key, + is_masp_tx_pin_key, masp_commitment_anchor_key, masp_commitment_tree_key, masp_convert_anchor_key, masp_nullifier_key, }; use token::Amount; @@ -135,6 +135,7 @@ where // the tree and anchor in storage fn valid_note_commitment_update( &self, + keys_changed: &BTreeSet, transaction: &Transaction, ) -> Result { // Check that the merkle tree in storage has been correctly updated with @@ -171,6 +172,35 @@ where return Ok(false); } + let expected_anchor_key = + token::storage_key::masp_commitment_anchor_key(post_tree.root()); + let changed_anchor_keys: Vec<_> = keys_changed + .iter() + .filter(|key| is_masp_commitment_anchor_key(key)) + .collect(); + // Check that at most one anchor was modified, the anchor is indeed + // committed (no temp write and no delete), it is the expected + // one and carries no associated data (the latter not + // strictly necessary for validation, but we don't expect any + // value for this key anyway) + match changed_anchor_keys.len() { + 0 => (), + 1 => { + if changed_anchor_keys.first().unwrap() != &&expected_anchor_key + { + tracing::debug!( + "The masp transaction wrote an unexpected anchor key" + ); + return Ok(false); + } + } + _ => return Ok(false), + } + match self.ctx.read_bytes_post(&expected_anchor_key)? { + Some(value) if value.is_empty() => (), + _ => return Ok(false), + } + Ok(true) } @@ -588,7 +618,7 @@ where // The transaction must correctly update the note commitment tree // in storage with the new output descriptions - if !self.valid_note_commitment_update(&shielded_tx)? { + if !self.valid_note_commitment_update(keys_changed, &shielded_tx)? { return Ok(false); } diff --git a/crates/shielded_token/src/storage_key.rs b/crates/shielded_token/src/storage_key.rs index e58ffe93a0..51917bae5f 100644 --- a/crates/shielded_token/src/storage_key.rs +++ b/crates/shielded_token/src/storage_key.rs @@ -85,8 +85,13 @@ pub fn is_masp_allowed_key(key: &storage::Key) -> bool { [ DbKeySeg::AddressSeg(addr), DbKeySeg::StringSeg(key), - DbKeySeg::StringSeg(_nullifier), - ] if *addr == address::MASP && key == MASP_NULLIFIERS_KEY => true, + DbKeySeg::StringSeg(_value), + ] if *addr == address::MASP + && (key == MASP_NULLIFIERS_KEY + || key == MASP_NOTE_COMMITMENT_ANCHOR_PREFIX) => + { + true + } _ => false, } } @@ -104,10 +109,19 @@ pub fn is_masp_nullifier_key(key: &storage::Key) -> bool { matches!(&key.segments[..], [DbKeySeg::AddressSeg(addr), DbKeySeg::StringSeg(prefix), - .. + DbKeySeg::StringSeg(_nullifier) ] if *addr == address::MASP && prefix == MASP_NULLIFIERS_KEY) } +/// Check if the given storage key is a masp commtimentr tree anchor key +pub fn is_masp_commitment_anchor_key(key: &storage::Key) -> bool { + matches!(&key.segments[..], + [DbKeySeg::AddressSeg(addr), + DbKeySeg::StringSeg(prefix), + DbKeySeg::StringSeg(_anchor) + ] if *addr == address::MASP && prefix == MASP_NOTE_COMMITMENT_ANCHOR_PREFIX) +} + /// Get a key for a masp pin pub fn masp_pin_tx_key(key: &str) -> storage::Key { storage::Key::from(address::MASP.to_db_key()) diff --git a/crates/shielded_token/src/utils.rs b/crates/shielded_token/src/utils.rs index 4dfbaa9e89..dc2d0816be 100644 --- a/crates/shielded_token/src/utils.rs +++ b/crates/shielded_token/src/utils.rs @@ -7,7 +7,8 @@ use namada_core::types::storage::IndexedTx; use namada_storage::{Error, Result, StorageRead, StorageWrite}; use crate::storage_key::{ - masp_commitment_tree_key, masp_nullifier_key, masp_pin_tx_key, + masp_commitment_anchor_key, masp_commitment_tree_key, masp_nullifier_key, + masp_pin_tx_key, }; // Writes the nullifiers of the provided masp transaction to storage @@ -50,7 +51,9 @@ pub fn update_note_commitment_tree( })?; } + let anchor_key = masp_commitment_anchor_key(commitment_tree.root()); ctx.write(&tree_key, commitment_tree)?; + ctx.write(&anchor_key, ())?; } } From 9c43e18d7fc3ce6463fdf335466b15ae524d879e Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Sun, 4 Feb 2024 19:25:45 +0100 Subject: [PATCH 11/16] Wip: pre-cache masp transactions when generating them --- crates/apps/src/lib/bench_utils.rs | 77 ++++ crates/apps/src/lib/cli/client.rs | 15 +- crates/apps/src/lib/client/tx.rs | 22 +- crates/sdk/src/eth_bridge/bridge_pool.rs | 11 +- crates/sdk/src/masp.rs | 425 ++++++++++++++++-- crates/sdk/src/signing.rs | 82 ++-- crates/sdk/src/tx.rs | 233 ++++++++-- crates/tests/src/integration/masp.rs | 134 +++--- ...582DAD9FBD3ACA2E0F8314642810FC958594E7.bin | Bin 10105 -> 10105 bytes ...D4D70154B89179E7DA6F14C700AAE1EC531E80.bin | Bin 2045 -> 2045 bytes ...FD0A13DAD049EAA1ECA95234C8AB02601FC0F0.bin | Bin 2045 -> 2045 bytes ...11DFBCF2AAA7876CE5FACD48AD18CB552E7349.bin | Bin 2045 -> 2045 bytes ...DB8CE4F984EEA5DE6991947DC46912C5EEEC72.bin | Bin 8392 -> 8392 bytes ...F2741B2A24802E41AF7F56081564BF2A160464.bin | Bin 2045 -> 0 bytes ...753FB3BE606A5729D43A6EA8F79007D34F6C60.bin | Bin 2045 -> 2045 bytes ...0F3AD4FA4AB61D0B965BB9ED02971491A2B7FC.bin | Bin 2045 -> 2045 bytes ...16BE737B7C747CD18D3B832DEC3C9DDCF3DBF8.bin | Bin 4895 -> 4895 bytes ...80F84F6B712C682DD639AF812F29AF23E4AB7F.bin | Bin 6393 -> 0 bytes ...DBE3DA9201B7C90E74A7B6C2B9B7320F006872.bin | Bin 6393 -> 6393 bytes ...346C4D5419EB8C2C4174F5DC1317D493122486.bin | Bin 6910 -> 0 bytes ...0DF6893C1C09CF3101C402BFE1465005639F14.bin | Bin 14387 -> 14387 bytes ...83E61BED82F25C4452CA41B769C3BABEB62D2B.bin | Bin 2045 -> 2045 bytes ...06FB77DB730FFFE562F2565B0431F7A901CC9A.bin | Bin 2045 -> 2045 bytes ...DC5356710DE7B6F6FA2B23C19412005669DC2B.bin | Bin 10105 -> 10105 bytes ...9384EF0421F46F7732EE62196DEB73ECB4C225.bin | Bin 8608 -> 8608 bytes ...1E2DCE33145F68A217FD50B065966646F59116.bin | Bin 2045 -> 2045 bytes ...9AFB3B6AE2AA3ADCACF75E6520A66B2F7D184C.bin | Bin 7875 -> 7875 bytes ...A81A7DF315190329C7C2F708876D51F60D2D60.bin | Bin 4895 -> 4895 bytes ...22056C14747EAC3FB1625F0A86957E00ED109.bin} | Bin 5412 -> 5412 bytes ...9BC3BBACE79DF98801EB8154EA1904597854A1.bin | Bin 4679 -> 4679 bytes ...EF52D368B771AD525817E722EA3E12B0A96971.bin | Bin 7650 -> 7650 bytes ...F7858007C4DA521F8E3BF250A46E9342178EEB.bin | Bin 5660 -> 5660 bytes ...3356453E412F862D949ABE9671C24A3903909E.bin | Bin 2045 -> 2045 bytes ...861C7F98EA4325D94989648024831E350D8F98.bin | Bin 2045 -> 2045 bytes 34 files changed, 814 insertions(+), 185 deletions(-) delete mode 100644 test_fixtures/masp_proofs/55CC69CC552A02161C1C9EED1AF2741B2A24802E41AF7F56081564BF2A160464.bin delete mode 100644 test_fixtures/masp_proofs/84320514AEC06D9AADC35DEF5C80F84F6B712C682DD639AF812F29AF23E4AB7F.bin delete mode 100644 test_fixtures/masp_proofs/891CCBE84265DFA7F35C8E5F08346C4D5419EB8C2C4174F5DC1317D493122486.bin rename test_fixtures/masp_proofs/{D38C391DF4F1F69AB04682F0C1B78DD77AA5620AC08519F73AB740B5A44AFA65.bin => D1F174D8596E8C1DA892DDC23D322056C14747EAC3FB1625F0A86957E00ED109.bin} (57%) diff --git a/crates/apps/src/lib/bench_utils.rs b/crates/apps/src/lib/bench_utils.rs index 9391e4aabc..5211e8774d 100644 --- a/crates/apps/src/lib/bench_utils.rs +++ b/crates/apps/src/lib/bench_utils.rs @@ -117,6 +117,8 @@ const BERTHA_SPENDING_KEY: &str = "bertha_spending"; const FILE_NAME: &str = "shielded.dat"; const TMP_FILE_NAME: &str = "shielded.tmp"; +const SPECULATIVE_FILE_NAME: &str = "speculative_shielded.dat"; +const SPECULATIVE_TMP_FILE_NAME: &str = "speculative_shielded.tmp"; /// For `tracing_subscriber`, which fails if called more than once in the same /// process @@ -669,6 +671,31 @@ impl ShieldedUtils for BenchShieldedUtils { Ok(()) } + /// Try to load the last saved speculative shielded context from the given + /// context directory. If this fails, then leave the current context + /// unchanged. + async fn load_speculative( + &self, + ctx: &mut ShieldedContext, + ) -> std::io::Result<()> { + // Try to load shielded context from file + let mut ctx_file = File::open( + self.context_dir + .0 + .path() + .to_path_buf() + .join(SPECULATIVE_FILE_NAME), + )?; + let mut bytes = Vec::new(); + ctx_file.read_to_end(&mut bytes)?; + // Fill the supplied context with the deserialized object + *ctx = ShieldedContext { + utils: ctx.utils.clone(), + ..ShieldedContext::::deserialize(&mut &bytes[..])? + }; + Ok(()) + } + /// Save this shielded context into its associated context directory async fn save( &self, @@ -698,6 +725,56 @@ impl ShieldedUtils for BenchShieldedUtils { tmp_path, self.context_dir.0.path().to_path_buf().join(FILE_NAME), )?; + + // Remove the speculative file if present since it's state is + // overwritten by the confirmed one we just saved + let _ = std::fs::remove_file(SPECULATIVE_FILE_NAME); + Ok(()) + } + + /// Save this speculative shielded context into its associated context + /// directory + async fn save_speculative( + &self, + ctx: &ShieldedContext, + ) -> std::io::Result<()> { + // TODO: use mktemp crate? + let tmp_path = self + .context_dir + .0 + .path() + .to_path_buf() + .join(SPECULATIVE_TMP_FILE_NAME); + { + // First serialize the shielded context into a temporary file. + // Inability to create this file implies a simultaneuous write + // is in progress. In this case, immediately + // fail. This is unproblematic because the data + // intended to be stored can always be re-fetched + // from the blockchain. + let mut ctx_file = OpenOptions::new() + .write(true) + .create_new(true) + .open(tmp_path.clone())?; + let mut bytes = Vec::new(); + ctx.serialize(&mut bytes) + .expect("cannot serialize shielded context"); + ctx_file.write_all(&bytes[..])?; + } + // Atomically update the old shielded context file with new data. + // Atomicity is required to prevent other client instances from + // reading corrupt data. + std::fs::rename( + tmp_path.clone(), + self.context_dir + .0 + .path() + .to_path_buf() + .join(SPECULATIVE_FILE_NAME), + )?; + // // Finally, remove our temporary file to allow future saving of + // // shielded contexts. + // std::fs::remove_file(tmp_path)?; //FIXME: probably not needed Ok(()) } } diff --git a/crates/apps/src/lib/cli/client.rs b/crates/apps/src/lib/cli/client.rs index d40b529b22..c99811db01 100644 --- a/crates/apps/src/lib/cli/client.rs +++ b/crates/apps/src/lib/cli/client.rs @@ -1,6 +1,7 @@ use color_eyre::eyre::Result; use masp_primitives::zip32::ExtendedFullViewingKey; use namada::types::io::Io; +use namada_sdk::masp::ContextSyncStatus; use namada_sdk::{Namada, NamadaImpl}; use crate::cli; @@ -317,6 +318,7 @@ impl CliApi { .await?; } Sub::ShieldedSync(ShieldedSync(args)) => { + eprintln!("IN SHIELDED SYNC"); //FIXME :remove let client = client.unwrap_or_else(|| { C::from_tendermint_address(&args.ledger_address) }); @@ -338,7 +340,18 @@ impl CliApi { .into_iter() .map(|sk| sk.into()) .collect::>(); - let _ = chain_ctx.shielded.load().await; + // //FIXME: make sure this laod the confirmed one, never the speculative, it does + //FIXME: if I enable this I get a stack overflow!!! + //FIXME: atually I don't get the overflow anymore + // let _ = chain_ctx.shielded.load_confirmed().await; //FIXME: probably unneeeded since we reload it later anyway + //FIXME: remove block + if let ContextSyncStatus::Confirmed = + chain_ctx.shielded.sync_status + { + eprintln!("FOUND OCNFIRMED STATUS"); + } else { + eprintln!("FOUND SPECULATIVE STATUS"); + } crate::client::masp::syncing( chain_ctx.shielded, &client, diff --git a/crates/apps/src/lib/client/tx.rs b/crates/apps/src/lib/client/tx.rs index 911e1b475a..ffa20f42f9 100644 --- a/crates/apps/src/lib/client/tx.rs +++ b/crates/apps/src/lib/client/tx.rs @@ -23,6 +23,7 @@ use namada::types::dec::Dec; use namada::types::io::Io; use namada::types::key::{self, *}; use namada_sdk::rpc::{InnerTxResult, TxBroadcastData, TxResponse}; +use namada_sdk::signing::validate_fee_and_gen_unshield; use namada_sdk::wallet::alias::validator_consensus_key; use namada_sdk::wallet::{Wallet, WalletIo}; use namada_sdk::{display_line, edisplay_line, error, signing, tx, Namada}; @@ -414,13 +415,20 @@ pub async fn submit_change_consensus_key( let signing_data = init_validator_signing_data(namada, &tx_args, vec![new_key]).await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + namada, + &tx_args, + &signing_data.fee_payer, + ) + .await?; tx::prepare_tx( namada, &tx_args, &mut tx, + unshield, + fee_amount, signing_data.fee_payer.clone(), - None, ) .await?; @@ -742,13 +750,20 @@ pub async fn submit_become_validator( let signing_data = init_validator_signing_data(namada, &tx_args, all_pks).await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + namada, + &tx_args, + &signing_data.fee_payer, + ) + .await?; tx::prepare_tx( namada, &tx_args, &mut tx, + unshield, + fee_amount, signing_data.fee_payer.clone(), - None, ) .await?; @@ -931,7 +946,9 @@ pub async fn submit_transfer( } else { sign(namada, &mut tx, &args.tx, signing_data).await?; + eprintln!("BEFORE SUBMIT"); //FIXME: remove let result = namada.submit(tx, &args.tx).await?; + eprintln!("AFTER SUBMIT"); //FIXME: remove match result { ProcessTxResponse::Applied(resp) if @@ -943,6 +960,7 @@ pub async fn submit_transfer( let submission_epoch = rpc::query_and_print_epoch(namada).await; // And its submission epoch doesn't match construction epoch if tx_epoch.unwrap() != submission_epoch { + //FIXME: here if in sepculative context fetch the updated conversion anchor // Then we probably straddled an epoch boundary. Let's retry... edisplay_line!(namada.io(), "MASP transaction rejected and this may be due to the \ diff --git a/crates/sdk/src/eth_bridge/bridge_pool.rs b/crates/sdk/src/eth_bridge/bridge_pool.rs index 6712e463c8..baa8ea05a9 100644 --- a/crates/sdk/src/eth_bridge/bridge_pool.rs +++ b/crates/sdk/src/eth_bridge/bridge_pool.rs @@ -40,7 +40,7 @@ use crate::queries::{ TransferToEthereumStatus, RPC, }; use crate::rpc::{query_storage_value, query_wasm_code_hash, validate_amount}; -use crate::signing::aux_signing_data; +use crate::signing::{aux_signing_data, validate_fee_and_gen_unshield}; use crate::tx::prepare_tx; use crate::{ args, display, display_line, edisplay_line, MaybeSync, Namada, @@ -87,6 +87,12 @@ pub async fn build_bridge_pool_tx( Some(sender_), ), )?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; let chain_id = tx_args .chain_id @@ -107,8 +113,9 @@ pub async fn build_bridge_pool_tx( context, &tx_args, &mut tx, + unshield, + fee_amount, signing_data.fee_payer.clone(), - None, ) .await?; diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 4406a514cd..23a400ed6b 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -68,7 +68,7 @@ use rand_core::{CryptoRng, OsRng, RngCore}; use ripemd::Digest as RipemdDigest; use sha2::Digest; use thiserror::Error; -use token::storage_key::is_any_shielded_action_balance_key; +use token::storage_key::{balance_key, is_any_shielded_action_balance_key}; use token::Amount; #[cfg(feature = "testing")] @@ -461,17 +461,29 @@ pub trait ShieldedUtils: /// Get a MASP transaction prover fn local_tx_prover(&self) -> LocalTxProver; - /// Load up the currently saved ShieldedContext + /// Load up the currently confirmed saved ShieldedContext async fn load( &self, ctx: &mut ShieldedContext, ) -> std::io::Result<()>; - /// Save the given ShieldedContext for future loads + /// Load up the currently saved speculative ShieldedContext + async fn load_speculative( + &self, + ctx: &mut ShieldedContext, + ) -> std::io::Result<()>; + + /// Save the given confirmed ShieldedContext for future loads async fn save( &self, ctx: &ShieldedContext, ) -> std::io::Result<()>; + + /// Save the given speculative ShieldedContext for future loads + async fn save_speculative( + &self, + ctx: &ShieldedContext, + ) -> std::io::Result<()>; } /// Make a ViewingKey that can view notes encrypted by given ExtendedSpendingKey @@ -575,6 +587,16 @@ impl IntoIterator for Unscanned { } } +#[derive(BorshSerialize, BorshDeserialize, Debug)] +/// The possible sync states of the shielded context +pub enum ContextSyncStatus { + /// The context contains only data that has been confirmed by the protocol + Confirmed, + /// The context contains that that has not yet been confirmed by the + /// protocol and could end up being invalid + Speculative, +} + /// Represents the current state of the shielded pool from the perspective of /// the chosen viewing keys. #[derive(BorshSerialize, BorshDeserialize, Debug)] @@ -612,6 +634,8 @@ pub struct ShieldedContext { pub tx_note_map: BTreeMap, /// A cache of fetched indexed txs. pub unscanned: Unscanned, + /// The sync state of the context + pub sync_status: ContextSyncStatus, } /// Default implementation to ease construction of TxContexts. Derive cannot be @@ -634,6 +658,7 @@ impl Default for ShieldedContext { asset_types: HashMap::default(), vk_map: HashMap::default(), unscanned: Default::default(), + sync_status: ContextSyncStatus::Confirmed, } } } @@ -642,12 +667,51 @@ impl ShieldedContext { /// Try to load the last saved shielded context from the given context /// directory. If this fails, then leave the current context unchanged. pub async fn load(&mut self) -> std::io::Result<()> { - self.utils.clone().load(self).await + match self.sync_status { + ContextSyncStatus::Confirmed => { + eprintln!("LOADIGN CONFIRMED CONTEXT"); //FIXME: remove + self.utils.clone().load(self).await + } + ContextSyncStatus::Speculative => { + eprintln!("LOADING SPECULATIVE CONTEXT"); //FIXME: remove + self.utils.clone().load_speculative(self).await + } + } + } + + /// Try to load the last saved confirmed shielded context from the given + /// context directory. If this fails, then leave the current context + /// unchanged. + pub async fn load_confirmed(&mut self) -> std::io::Result<()> { + self.utils.clone().load(self).await?; + // self.sync_status = ContextSyncStatus::Confirmed; //FIXME: change this directly inside the function we call here above + + Ok(()) } - /// Save this shielded context into its associated context directory + // FIXME: what' the first state that we load when we start this thing? The + // confirmed or the speculative FIXME: copy this logic in the docstring + // of the ContextSync enum FIXME: the logic should be the following: + // - save are fine, I just save whatever state I am in and if it is + // confirmed than I also delete the speculative one if available + // - load, I should try to load the speculative state all the times and + // fallback to the confirmed one? + // - Only in fetching I should always load the confirmed state + // - At startup if I have a speculative file I load that one, otherwise I + // fallback to the confirmed one + + //FIXME: probably I query the conversions everytime so the speculative context works anyway + + /// Save this shielded context into its associated context directory. If the + /// state to be saved is confirmed than also delete the speculative one (if + /// available) pub async fn save(&self) -> std::io::Result<()> { - self.utils.save(self).await + match self.sync_status { + ContextSyncStatus::Confirmed => self.utils.save(self).await, + ContextSyncStatus::Speculative => { + self.utils.save_speculative(self).await + } + } } /// Update the merkle tree of witnesses the first time we @@ -672,9 +736,27 @@ impl ShieldedContext { Error::Other("note commitment tree is full".to_string()) })?; } + //FIXME: probably need to review validation and update the merkle root for every masp transaction + //FIXME: No wait, I still belive this should work even with the current protocol logic of updating the anchor only once per block + //FIXME: I probably just need to construct the wrapper before the inner, at the moment I'm switching them but than the wrapper is executed first and it carries invalida data (wrong commitment anchor) + //FIXME: also because an unshielding does not update the commitment tree + // if let ContextSyncStatus::Confirmed = self.sync_status { + //FIXME: so in here we effectively update the merkle tree with ALL the notes, not just the ones I can decrypt + + //FIXME: BIG PROBLEM, if I use the speculative context I produce some new output descriptions that I cache for usage. The problem is that I don't have the merkle tree for these new notes and therefore I don't have the anchor and a valid markle path, because to have those I would need to fetch all the notes (even the ones from the other transactions) and reconstruct the merkle tree locally to produce a valid merkle path. SO I would still need to fetch data from the blockchain in the end + //FIXME: what I can do is to just invalidate the spend descriptions I've used so that if I have more than one I can use the others, so in some cases I will still be able to construct a valid transaction, but not always unfortunatly + + //FIXME: regarding the choice to not update the commitment tree anchor with every transaction: + // - for fee unshielding the one above is the only solution, because the inner is executed in the next block, so unless the previous block had only my transaction, I would still need to fetch data (which is impossible), actually is this the case? NO it would actually work, I would just need to refer to the merkle tree of my fee unshielding!! + // - for sequential masp transaction in a same block (no fee unshielding) it's the same thing, if I use the speculative notes than I don't have a valid anchor and merkle path + + //FIXME: to conclude, if I want to use the speculative notes I need to update che ledger to update the anchor with every transaction, because otherwise the notes that I used are still unkown to the ledger in the case of sequential txs and have an invalid anchor in case of fee unshielding. I also need to revert the construciton of the wrapper and the inner, must construct the inner first and wrapper after + + //FIXME: for the conversion tree, at the epoch boundary that changes and if I need to use conversions in my txs those would be invalid, but I could query just the new anchor without querying everything else and still preserve my specyulative context. I could do that if I see that the transactio nfails because of epoch self.tree.append(node).map_err(|()| { Error::Other("note commitment tree is full".to_string()) })?; + // } // Finally, make it easier to construct merkle paths to this new // note let witness = IncrementalWitness::::from_tree(&self.tree); @@ -696,6 +778,26 @@ impl ShieldedContext { fvks: &[ViewingKey], ) -> Result<(), Error> { // add new viewing keys + //FIXME: reload alwyas cause I could have parallel clients! + // if let ContextSyncStatus::Speculative = self.sync_status { + // Reload the state from file to get the last confirmed state and + // discard any speculative data, we cannot fetch on top of a + // speculative state + // eprintln!("IN FETCH, RELOADING CONFIRMED FROM SPECULATIVE"); //FIXME: remove + // Always reload the confirmed context or initialize a new one if not found + if self.load_confirmed().await.is_err() { + // Initialize a default context if we couldn't load a valid one + // from storage + *self = Self { + utils: std::mem::take(&mut self.utils), + ..Default::default() + }; + } + // } else { + // //FIXME :remove else branch + // eprintln!("IN FETCH, FOUND CONFIRMED STATE"); //FIXME: remove + // } + for esk in sks { let vk = to_viewing_key(esk).vk; self.vk_heights.entry(vk).or_default(); @@ -703,10 +805,7 @@ impl ShieldedContext { for vk in fvks { self.vk_heights.entry(*vk).or_default(); } - self.utils - .save(self) - .await - .map_err(|e| Error::Other(e.to_string()))?; + let _ = self.save().await; let native_token = query_native_token(client).await?; // the latest block height which has been added to the witness Merkle // tree @@ -729,10 +828,7 @@ impl ShieldedContext { .await?, ); // persist the cache in case of interruptions. - self.utils - .save(self) - .await - .map_err(|e| Error::Other(e.to_string()))?; + let _ = self.save().await; let txs = logger.scan(self.unscanned.clone()); for (indexed_tx, (epoch, tx, stx)) in txs { @@ -753,15 +849,12 @@ impl ShieldedContext { vk, native_token.clone(), )?; - *h = Some(indexed_tx); + *h = Some(indexed_tx); //FIXME: probably this is the part I'm missing in prefetch } // possibly remove unneeded elements from the cache. self.unscanned.scanned(&indexed_tx); std::mem::swap(&mut vk_heights, &mut self.vk_heights); - self.utils - .save(self) - .await - .map_err(|e| Error::Other(e.to_string()))?; + let _ = self.save().await; } Ok(()) @@ -1594,7 +1687,12 @@ impl ShieldedContext { let mut val_acc = I128Sum::zero(); let mut normed_val_acc = I128Sum::zero(); let mut notes = Vec::new(); - // Retrieve the notes that can be spent by this key + eprintln!( + "BEFORE LOOP IN COLLECT UNSPENT. POS MASP: {:#?}", + self.pos_map + ); //FIXME: remove + //FIXME: error here, I never enter the Some branch, am I passing the wrong viewing key? No the pos map is actually empty!!! + // Retrieve the notes that can be spent by this key if let Some(avail_notes) = self.pos_map.get(vk).cloned() { for note_idx in &avail_notes { // No more transaction inputs are required once we have met @@ -1606,6 +1704,7 @@ impl ShieldedContext { if self.spents.contains(note_idx) { continue; } + //FIXME: the masp vp must verify the merkle path somewhere oterwise it's useless, verifying only the merkle root is only half of the check // Get note, merkle path, diversifier associated with this ID let note = *self.note_map.get(note_idx).ok_or_else(|| { Error::Other(format!("Unable to get note {note_idx}")) @@ -1642,6 +1741,7 @@ impl ShieldedContext { normed_val_acc += normed_contr; // Commit the conversions that were used to exchange conversions = proposed_convs; + //FIXME: problem here, I take the merkle path from the witness map but this is invalid if we are in a speculative context let merkle_path = self .witness_map .get(note_idx) @@ -1664,6 +1764,7 @@ impl ShieldedContext { )) })?; // Commit this note to our transaction + eprintln!("FOUND UNSPENT NOTE: {:#?}", note); //FIXME: remove notes.push((*diversifier, note, merkle_path)); } } @@ -1926,7 +2027,10 @@ impl ShieldedContext { { // Load the current shielded context given the spending key we // possess + //FIXME: it's more complicated than this. I could have multiple parallels clients loading and storing contexts in differents status (speculative or confirmed). So what should I do? let mut shielded = context.shielded_mut().await; + eprintln!("BEFORE CONTEXT LOAD IN GEN SHIELDD"); //FIXME: remove + //FIXME: really need to reload here??? let _ = shielded.load().await; } // Determine epoch in which to submit potential shielded transaction @@ -2024,6 +2128,8 @@ impl ShieldedContext { amount }; + //FIXME: does the speculative context work across epochs? IN this case the protocol updates the conversion tree root and therefore I'm not sure the speculative context can still produce valid transactions, verify it + //FIXME: maybe we can just query the updated conversion tree without fetching everything else? // If there are shielded inputs if let Some(sk) = spending_key { // Locate unspent notes that can help us meet the transaction amount @@ -2144,7 +2250,7 @@ impl ShieldedContext { // We want to take at most the remaining quota for the // current denomination to the receiver let contr = std::cmp::min(*rem_amount as u128, val) as u64; - // Make transaction output tied to thee currentt token, + // Make transaction output tied to the current token, // denomination, and epoch. if let Some(pa) = payment_address { // If there is a shielded output @@ -2245,28 +2351,27 @@ impl ShieldedContext { // To speed up integration tests, we can save and load proofs #[cfg(feature = "testing")] - let load_or_save = if let Ok(masp_proofs) = - env::var(ENV_VAR_MASP_TEST_PROOFS) - { - let parsed = match masp_proofs.to_ascii_lowercase().as_str() { - "load" => LoadOrSaveProofs::Load, - "save" => LoadOrSaveProofs::Save, - env_var => Err(Error::Other(format!( + let load_or_save = + if let Ok(masp_proofs) = env::var(ENV_VAR_MASP_TEST_PROOFS) { + let parsed = match masp_proofs.to_ascii_lowercase().as_str() { + "load" => LoadOrSaveProofs::Load, + "save" => LoadOrSaveProofs::Save, + env_var => Err(Error::Other(format!( "Unexpected value for {ENV_VAR_MASP_TEST_PROOFS} env var. \ Expecting \"save\" or \"load\", but got \"{env_var}\"." )))?, - }; - if env::var(ENV_VAR_MASP_TEST_SEED).is_err() { - Err(Error::Other(format!( + }; + if env::var(ENV_VAR_MASP_TEST_SEED).is_err() { + Err(Error::Other(format!( "Ensure to set a seed with {ENV_VAR_MASP_TEST_SEED} env \ var when using {ENV_VAR_MASP_TEST_PROOFS} for \ deterministic proofs." )))?; - } - parsed - } else { - LoadOrSaveProofs::Neither - }; + } + parsed + } else { + LoadOrSaveProofs::Neither + }; let builder_clone = builder.clone().map_builder(WalletMap); #[cfg(feature = "testing")] @@ -2325,6 +2430,22 @@ impl ShieldedContext { BorshDeserialize::try_from_slice(&loaded_bytes) .map_err(|_e| Error::Other(exp_str))?; + // Cache the generated transfer + let native_token = query_native_token(context.client()).await?; + let mut shielded_ctx = context.shielded_mut().await; + shielded_ctx + .pre_cache_transaction( + spending_key, + payment_address, + &loaded.masp_tx, + source, + target, + token, + epoch, + native_token, + ) + .await?; + Ok(Some(loaded)) } else { // Build and return the constructed transaction @@ -2339,6 +2460,23 @@ impl ShieldedContext { .await .map_err(|e| Error::Other(e.to_string()))?; } + + // Cache the generated transfer + let native_token = query_native_token(context.client()).await?; + let mut shielded_ctx = context.shielded_mut().await; + shielded_ctx + .pre_cache_transaction( + spending_key, + payment_address, + &built.masp_tx, + source, + target, + token, + epoch, + native_token, + ) + .await?; + Ok(Some(built)) } } @@ -2349,10 +2487,124 @@ impl ShieldedContext { let built = build_transfer( context.shielded().await.utils.local_tx_prover(), )?; + + let native_token = query_native_token(context.client()).await?; + let mut shielded_ctx = context.shielded_mut().await; + shielded_ctx + .pre_cache_transaction( + spending_key, + payment_address, + &built.masp_tx, + source, + target, + token, + epoch, + native_token, + ) + .await?; + Ok(Some(built)) } } + // Updates the internal state with the data of the newly generated + // transaction + async fn pre_cache_transaction( + &mut self, + esk: Option, + payment_address: Option, + masp_tx: &Transaction, + source: &TransferSource, + target: &TransferTarget, + token: &Address, + epoch: Epoch, + native_token: Address, + ) -> Result<(), Error> { + //FIXME: somehting wrong in here, I'm not saving the data correctly because whe ntrying to construct from a speculative context it doesn't work + eprintln!("IN PRECACHE TRANSACTIONS"); //FIXME: remove + // Need to mock the changed balance keys + let mut changed_balance_keys = BTreeSet::default(); + match (source.effective_address(), target.effective_address()) { + // Shielded transactions don't write balance keys + (MASP, MASP) => (), + (source, target) => { + changed_balance_keys.insert(balance_key(token, &source)); + changed_balance_keys.insert(balance_key(token, &target)); + } + } + eprintln!("PRE CACHE CHANGED KEYS: {:#?}", changed_balance_keys); //FIXME: remove + + let mut vks = Vec::with_capacity(2); + if let Some(esk) = esk { + vks.push(to_viewing_key(&esk).vk); + } + //FIXME: don't do it like that, get the viewing key from the wallet which is inside the Namada contexts in gen_shielded_transfer! + // FIXME: clane up this, use find on iterators + if let Some(pa) = payment_address { + // Try to look for the viewing key associated to this payent address + // in the shielded context + 'outer: for (vk, positions) in &self.pos_map { + for pos in positions { + if let Some(div) = self.div_map.get(pos) { + if let Some(ref p) = vk.to_payment_address(*div) { + if p == &masp_primitives::sapling::PaymentAddress::from(pa) { + vks.push(*vk); + break 'outer; + } + } + } + } + } + } + + //FIXME: I never enter this loop!!! + eprintln!("ABOUT OT ITERATE ON VKS"); //FIXME: remove + for vk in vks { + eprintln!("IN ITERATE VKS: {:#?}", vk); //FIXME: RMEOVE + //FIXME: can share this code with fetch? + self.vk_heights.entry(vk).or_default(); + // This data will be discarded at the next fetch so we don't need to + // populate it accurately + let indexed_tx = self.vk_heights.get(&vk).unwrap().map_or_else( + || IndexedTx { + height: BlockHeight::first(), + index: TxIndex(0), + }, + // FIXME: I should try to mock the correct block height? yes + |indexed| IndexedTx { + height: indexed.height, + index: indexed.index + 1, /* FIXME: this seems to never + * be updated, is it ok? + * Probably because I'm not + * saving the speculative + * context */ + }, + ); + eprintln!("NED INDEXED TX: {:#?}", indexed_tx); //FIXME: remove + + self.update_witness_map(indexed_tx, masp_tx)?; + + self.scan_tx( + indexed_tx, + epoch, + &changed_balance_keys, + masp_tx, + &vk, + native_token.clone(), + )?; + + *self.vk_heights.get_mut(&vk).unwrap() = Some(indexed_tx); + } + //FIXME: I'm probably forgetting to update vk height! + self.sync_status = ContextSyncStatus::Speculative; + // Save the speculative state for future usage + eprintln!("BEFORE SAVE SPECULATIVE"); //FIXME: remove + self.save().await.map_err(|e| Error::Other(e.to_string()))?; //FIXME: error here + eprintln!("AFTER SAVE SPECULATIVE"); //FIXME: remove + + Ok(()) + } + /// Obtain the known effects of all accepted shielded and transparent /// transactions. If an owner is specified, then restrict the set to only /// transactions crediting/debiting the given owner. If token is specified, @@ -3558,6 +3810,8 @@ pub mod fs { /// Shielded context file name const FILE_NAME: &str = "shielded.dat"; const TMP_FILE_NAME: &str = "shielded.tmp"; + const SPECULATIVE_FILE_NAME: &str = "speculative_shielded.dat"; + const SPECULATIVE_TMP_FILE_NAME: &str = "speculative_shielded.tmp"; #[derive(Debug, BorshSerialize, BorshDeserialize, Clone)] /// An implementation of ShieldedUtils for standard filesystems @@ -3588,9 +3842,23 @@ pub mod fs { ); } // Finally initialize a shielded context with the supplied directory + + let sync_status = + if std::fs::read(context_dir.join(SPECULATIVE_FILE_NAME)) + .is_ok() + { + eprintln!("FOUND SPECULATIVE FILE"); //FIXME: remove + // Load speculative state + ContextSyncStatus::Speculative + } else { + eprintln!("LOADING CONFIRMED FILE"); //FIXME: remove + ContextSyncStatus::Confirmed + }; + let utils = Self { context_dir }; ShieldedContext { utils, + sync_status, ..Default::default() } } @@ -3606,6 +3874,8 @@ pub mod fs { #[cfg_attr(feature = "async-send", async_trait::async_trait)] #[cfg_attr(not(feature = "async-send"), async_trait::async_trait(?Send))] + // FIXME: I can probably refactor everything to have the associated + // contextsSycn state on this trait impl ShieldedUtils for FsShieldedUtils { fn local_tx_prover(&self) -> LocalTxProver { if let Ok(params_dir) = env::var(ENV_VAR_MASP_PARAMS_DIR) { @@ -3623,6 +3893,7 @@ pub mod fs { /// Try to load the last saved shielded context from the given context /// directory. If this fails, then leave the current context unchanged. async fn load( + //FIXME: review the use of this! &self, ctx: &mut ShieldedContext, ) -> std::io::Result<()> { @@ -3638,12 +3909,34 @@ pub mod fs { Ok(()) } - /// Save this shielded context into its associated context directory + /// Try to load the last saved speculative shielded context from the + /// given context directory. If this fails, then leave the + /// current context unchanged. + async fn load_speculative( + &self, + ctx: &mut ShieldedContext, + ) -> std::io::Result<()> { + // Try to load shielded context from file + let mut ctx_file = + File::open(self.context_dir.join(SPECULATIVE_FILE_NAME))?; + let mut bytes = Vec::new(); + ctx_file.read_to_end(&mut bytes)?; + // Fill the supplied context with the deserialized object + *ctx = ShieldedContext { + utils: ctx.utils.clone(), + ..ShieldedContext::::deserialize(&mut &bytes[..])? + }; + Ok(()) + } + + /// Save this confirmed shielded context into its associated context + /// directory. At the same time, delete the speculative file if present async fn save( &self, ctx: &ShieldedContext, ) -> std::io::Result<()> { // TODO: use mktemp crate? + eprintln!("IN INNER SAVE CONFIMRED!"); //FIXME: remove let tmp_path = self.context_dir.join(TMP_FILE_NAME); { // First serialize the shielded context into a temporary file. @@ -3664,7 +3957,63 @@ pub mod fs { // Atomically update the old shielded context file with new data. // Atomicity is required to prevent other client instances from // reading corrupt data. - std::fs::rename(tmp_path, self.context_dir.join(FILE_NAME)) + std::fs::rename(tmp_path, self.context_dir.join(FILE_NAME))?; + + // Remove the speculative file if present since it's state is + // overruled by the confirmed one we just saved + // let _ = std::fs::remove_file(SPECULATIVE_FILE_NAME); //FIXME: uncomment + //FIXME: remove block + if let Err(e) = std::fs::remove_file( + self.context_dir.join(SPECULATIVE_FILE_NAME), + ) { + eprintln!("COULD NOT REMOTE SPECULATVE FILE!: {}", e); + } else { + eprintln!("SUCCEFULY REMOVED SPECULATIVE FILE"); + } + + Ok(()) + } + + // FIXME: refactor, the functions are exactly the same, just pass the + // enum and modify the filename based on that + /// Save this speculative shielded context into its associated context + /// directory + async fn save_speculative( + &self, + ctx: &ShieldedContext, + ) -> std::io::Result<()> { + // TODO: use mktemp crate? + eprintln!("IN INNER SAVE SPECULATIVE!"); //FIXME: remove + let tmp_path = self.context_dir.join(SPECULATIVE_TMP_FILE_NAME); + { + // First serialize the shielded context into a temporary file. + // Inability to create this file implies a simultaneuous write + // is in progress. In this case, immediately + // fail. This is unproblematic because the data + // intended to be stored can always be re-fetched + // from the blockchain. + let mut ctx_file = OpenOptions::new() + .write(true) + .create_new(true) + .open(tmp_path.clone())?; + let mut bytes = Vec::new(); + ctx.serialize(&mut bytes) + .expect("cannot serialize shielded context"); + ctx_file.write_all(&bytes[..])?; + } + // FIXME: there's an error here somewhere + // Atomically update the old shielded context file with new data. + // Atomicity is required to prevent other client instances from + // reading corrupt data. + eprintln!("BEFORE RENAME"); //FIXME: remove + std::fs::rename( + tmp_path, + self.context_dir.join(SPECULATIVE_FILE_NAME), + )?; + // std::fs::remove_file(tmp_path)?; //FIXME: breaks here, why? I + // renamed the file, why do I even delete it? FIXME: but + // it works for the confirmed file + Ok(()) } } } diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index 2324444d20..a0993f6615 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -10,6 +10,7 @@ use masp_primitives::asset_type::AssetType; use masp_primitives::transaction::components::sapling::fees::{ InputView, OutputView, }; +use masp_primitives::transaction::Transaction; use namada_account::{AccountPublicKeysMap, InitAccount, UpdateAccount}; use namada_core::types::address::{ Address, ImplicitAddress, InternalAddress, MASP, @@ -403,8 +404,8 @@ pub async fn init_validator_signing_data( }) } -/// Information about the post-tx balance of the tx's source. Used to correctly -/// handle fee validation in the wrapper tx +/// Information about the post-fee balance of the tx's source. Used to correctly +/// handle balance validation in the inner tx pub struct TxSourcePostBalance { /// The balance of the tx source after the tx has been applied pub post_balance: Amount, @@ -414,19 +415,14 @@ pub struct TxSourcePostBalance { pub token: Address, } -/// Create a wrapper tx from a normal tx. Get the hash of the -/// wrapper and its payload which is needed for monitoring its -/// progress on chain. -#[allow(clippy::too_many_arguments)] -pub async fn wrap_tx( +/// Validate the fee of the transaction and generate the fee unshielding transaction if needed +pub async fn validate_fee_and_gen_unshield( context: &N, - tx: &mut Tx, args: &args::Tx, - tx_source_balance: Option, - epoch: Epoch, - fee_payer: common::PublicKey, -) -> Result<(), Error> { - let fee_payer_address = Address::from(&fee_payer); + fee_payer: &common::PublicKey, +) -> Result<(DenominatedAmount, TxSourcePostBalance, Option), Error> +{ + let fee_payer_address = Address::from(fee_payer); // Validate fee amount and token let gas_cost_key = parameter_storage::get_gas_cost_key(); let minimum_fee = match rpc::query_storage_value::< @@ -482,27 +478,22 @@ pub async fn wrap_tx( None => validated_minimum_fee, }; - let mut updated_balance = match tx_source_balance { - Some(TxSourcePostBalance { - post_balance: balance, - source, - token, - }) if token == args.fee_token && source == fee_payer_address => balance, - _ => { - let balance_key = balance_key(&args.fee_token, &fee_payer_address); - - rpc::query_storage_value::<_, token::Amount>( - context.client(), - &balance_key, - ) - .await - .unwrap_or_default() - } - }; + let balance_key = balance_key(&args.fee_token, &fee_payer_address); + let balance = rpc::query_storage_value::<_, token::Amount>( + context.client(), + &balance_key, + ) + .await + .unwrap_or_default(); let total_fee = fee_amount.amount() * u64::from(args.gas_limit); + let mut updated_balance = TxSourcePostBalance { + post_balance: balance, + source: fee_payer_address.clone(), + token: args.fee_token.clone(), + }; - let unshield = match total_fee.checked_sub(updated_balance) { + let unshield = match total_fee.checked_sub(balance) { Some(diff) if !diff.is_zero() => { if let Some(spending_key) = args.fee_unshield.clone() { // Unshield funds for fee payment @@ -574,8 +565,7 @@ pub async fn wrap_tx( )); } - updated_balance += total_fee; - Some(transaction) + Some(transaction) } Ok(None) => { if !args.force { @@ -587,6 +577,7 @@ pub async fn wrap_tx( )); } + //FIXME: should update the balance to 0 here? None } Err(e) => { @@ -595,7 +586,7 @@ pub async fn wrap_tx( TxSubmitError::FeeUnshieldingError(e.to_string()), )); } - + //FIXME: should update the balance to 0 here? None } } @@ -605,9 +596,8 @@ pub async fn wrap_tx( let fee_amount = context.format_amount(&token_addr, total_fee).await; - let balance = context - .format_amount(&token_addr, updated_balance) - .await; + let balance = + context.format_amount(&token_addr, balance).await; return Err(Error::from( TxSubmitError::BalanceTooLowForFees( fee_payer_address, @@ -618,6 +608,7 @@ pub async fn wrap_tx( )); } + //FIXME: should update the balance to 0 here? None } } @@ -629,10 +620,27 @@ pub async fn wrap_tx( .to_string(), )); } + updated_balance.post_balance -= total_fee; None } }; + Ok((fee_amount, updated_balance, unshield)) +} + +/// Create a wrapper tx from a normal tx. Get the hash of the +/// wrapper and its payload which is needed for monitoring its +/// progress on chain. +#[allow(clippy::too_many_arguments)] +pub async fn wrap_tx( + context: &N, + tx: &mut Tx, + args: &args::Tx, + epoch: Epoch, + unshield: Option, + fee_amount: DenominatedAmount, + fee_payer: common::PublicKey, +) -> Result<(), Error> { let unshield_section_hash = unshield.map(|masp_tx| { let section = Section::MaspTx(masp_tx); let mut hasher = sha2::Sha256::new(); diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index a5ff9da0da..0f28c00a4a 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -47,6 +47,7 @@ use namada_ibc::storage::channel_key; use namada_proof_of_stake::parameters::PosParams; use namada_proof_of_stake::types::{CommissionPair, ValidatorState}; use namada_token::storage_key::balance_key; +use namada_token::DenominatedAmount; use namada_tx::data::pgf::UpdateStewardCommission; use namada_tx::data::{pos, ResultCode, TxResult}; pub use namada_tx::{Signature, *}; @@ -62,7 +63,9 @@ use crate::rpc::{ self, query_wasm_code_hash, validate_amount, InnerTxResult, TxBroadcastData, TxResponse, }; -use crate::signing::{self, SigningTxData, TxSourcePostBalance}; +use crate::signing::{ + self, validate_fee_and_gen_unshield, SigningTxData, TxSourcePostBalance, +}; use crate::tendermint_rpc::endpoint::broadcast::tx_sync::Response; use crate::tendermint_rpc::error::Error as RpcError; use crate::wallet::WalletIo; @@ -185,14 +188,17 @@ pub async fn prepare_tx( context: &impl Namada, args: &args::Tx, tx: &mut Tx, + unshield: Option, + fee_amount: DenominatedAmount, fee_payer: common::PublicKey, - tx_source_balance: Option, ) -> Result<()> { if !args.dry_run { let epoch = rpc::query_epoch(context.client()).await?; - signing::wrap_tx(context, tx, args, tx_source_balance, epoch, fee_payer) - .await + signing::wrap_tx( + context, tx, args, epoch, unshield, fee_amount, fee_payer, + ) + .await } else { Ok(()) } @@ -286,6 +292,9 @@ pub async fn build_reveal_pk( let signing_data = signing::aux_signing_data(context, args, None, Some(public_key.into())) .await?; + let (fee_amount, _, unshield) = + validate_fee_and_gen_unshield(context, &args, &signing_data.fee_payer) + .await?; build( context, @@ -293,8 +302,9 @@ pub async fn build_reveal_pk( args.tx_reveal_code_path.clone(), public_key, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -348,6 +358,7 @@ pub async fn broadcast_tx( } Ok(response) } else { + eprintln!("TX NOT ADDED TO MEMPOOL"); //FIXME: remove Err(Error::from(TxSubmitError::TxBroadcast(RpcError::server( serde_json::to_string(&response).map_err(|err| { Error::from(EncodingError::Serde(err.to_string())) @@ -575,6 +586,12 @@ pub async fn build_validator_commission_change( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; let epoch = rpc::query_epoch(context.client()).await?; @@ -664,8 +681,9 @@ pub async fn build_validator_commission_change( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -694,6 +712,12 @@ pub async fn build_validator_metadata_change( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; let epoch = rpc::query_epoch(context.client()).await?; @@ -797,8 +821,9 @@ pub async fn build_validator_metadata_change( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -822,6 +847,12 @@ pub async fn build_update_steward_commission( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; if !rpc::is_steward(context.client(), steward).await && !tx_args.force { edisplay_line!( @@ -858,8 +889,9 @@ pub async fn build_update_steward_commission( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -882,6 +914,12 @@ pub async fn build_resign_steward( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; if !rpc::is_steward(context.client(), steward).await && !tx_args.force { edisplay_line!( @@ -900,8 +938,9 @@ pub async fn build_resign_steward( tx_code_path.clone(), steward.clone(), do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -924,6 +963,12 @@ pub async fn build_unjail_validator( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; if !rpc::is_validator(context.client(), validator).await? { edisplay_line!( @@ -1002,8 +1047,9 @@ pub async fn build_unjail_validator( tx_code_path.clone(), validator.clone(), do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -1026,6 +1072,12 @@ pub async fn build_deactivate_validator( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; // Check if the validator address is actually a validator if !rpc::is_validator(context.client(), validator).await? { @@ -1073,8 +1125,9 @@ pub async fn build_deactivate_validator( tx_code_path.clone(), validator.clone(), do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -1097,6 +1150,12 @@ pub async fn build_reactivate_validator( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; // Check if the validator address is actually a validator if !rpc::is_validator(context.client(), validator).await? { @@ -1143,8 +1202,9 @@ pub async fn build_reactivate_validator( tx_code_path.clone(), validator.clone(), do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -1313,6 +1373,12 @@ pub async fn build_redelegation( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; let data = pos::Redelegation { src_validator, @@ -1327,8 +1393,9 @@ pub async fn build_redelegation( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -1353,6 +1420,12 @@ pub async fn build_withdraw( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; let epoch = rpc::query_epoch(context.client()).await?; @@ -1410,8 +1483,9 @@ pub async fn build_withdraw( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -1436,6 +1510,12 @@ pub async fn build_claim_rewards( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; // Check that the validator address is actually a validator let validator = @@ -1458,8 +1538,9 @@ pub async fn build_claim_rewards( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -1510,6 +1591,12 @@ pub async fn build_unbond( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; // Check the source's current bond amount let bond_source = source.clone().unwrap_or_else(|| validator.clone()); @@ -1560,8 +1647,9 @@ pub async fn build_unbond( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await?; Ok((tx, signing_data, latest_withdrawal_pre)) @@ -1710,6 +1798,13 @@ pub async fn build_bond( default_signer, ) .await?; + let (fee_amount, updated_balance, unshield) = + validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; // Check bond's source (source for delegation or validator for self-bonds) // balance @@ -1718,6 +1813,7 @@ pub async fn build_bond( let balance_key = balance_key(&native_token, bond_source); // TODO Should we state the same error message for the native token? + //FIXME: use the updated balance here if it's the same source and token let post_balance = check_balance_too_low_err( &native_token, bond_source, @@ -1745,8 +1841,9 @@ pub async fn build_bond( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - tx_source_balance, ) .await .map(|tx| (tx, signing_data)) @@ -1773,6 +1870,9 @@ pub async fn build_default_proposal( default_signer, ) .await?; + let (fee_amount, updated_balance, unshield) = + validate_fee_and_gen_unshield(context, &tx, &signing_data.fee_payer) + .await?; let init_proposal_data = InitProposalData::try_from(proposal.clone()) .map_err(|e| TxSubmitError::InvalidProposal(e.to_string()))?; @@ -1791,14 +1891,16 @@ pub async fn build_default_proposal( }; Ok(()) }; + // TODO: need to pay the fee to submit a proposal, check enough balance build( context, tx, tx_code_path.clone(), init_proposal_data, push_data, + unshield, + fee_amount, &signing_data.fee_payer, - None, // TODO: need to pay the fee to submit a proposal ) .await .map(|tx| (tx, signing_data)) @@ -1826,6 +1928,9 @@ pub async fn build_vote_proposal( default_signer.clone(), ) .await?; + let (fee_amount, _, unshield) = + validate_fee_and_gen_unshield(context, &tx, &signing_data.fee_payer) + .await?; let proposal_vote = ProposalVote::try_from(vote.clone()) .map_err(|_| TxSubmitError::InvalidProposalVote)?; @@ -1884,8 +1989,9 @@ pub async fn build_vote_proposal( tx_code_path.clone(), data, do_nothing, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -1912,7 +2018,11 @@ pub async fn build_pgf_funding_proposal( default_signer, ) .await?; + let (fee_amount, updated_balance, unshield) = + validate_fee_and_gen_unshield(context, &tx, &signing_data.fee_payer) + .await?; + // TODO: need to pay the fee to submit a proposal, check enough balance let init_proposal_data = InitProposalData::try_from(proposal.clone()) .map_err(|e| TxSubmitError::InvalidProposal(e.to_string()))?; @@ -1928,8 +2038,9 @@ pub async fn build_pgf_funding_proposal( tx_code_path.clone(), init_proposal_data, add_section, + unshield, + fee_amount, &signing_data.fee_payer, - None, // TODO: need to pay the fee to submit a proposal ) .await .map(|tx| (tx, signing_data)) @@ -1956,7 +2067,11 @@ pub async fn build_pgf_stewards_proposal( default_signer, ) .await?; + let (fee_amount, updated_balance, unshield) = + validate_fee_and_gen_unshield(context, &tx, &signing_data.fee_payer) + .await?; + // TODO: need to pay the fee to submit a proposal, check enough balance let init_proposal_data = InitProposalData::try_from(proposal.clone()) .map_err(|e| TxSubmitError::InvalidProposal(e.to_string()))?; @@ -1973,8 +2088,9 @@ pub async fn build_pgf_stewards_proposal( tx_code_path.clone(), init_proposal_data, add_section, + unshield, + fee_amount, &signing_data.fee_payer, - None, // TODO: need to pay the fee to submit a proposal ) .await .map(|tx| (tx, signing_data)) @@ -1993,6 +2109,14 @@ pub async fn build_ibc_transfer( Some(source.clone()), ) .await?; + let (fee_amount, updated_balance, unshield) = + validate_fee_and_gen_unshield( + context, + &args.tx, + &signing_data.fee_payer, + ) + .await?; + // Check that the source address exists on chain let source = source_exists_or_err(source.clone(), args.tx.force, context).await?; @@ -2013,6 +2137,7 @@ pub async fn build_ibc_transfer( // Check source balance let balance_key = balance_key(&args.token, &source); + //FIXME: use updated balance if fee payer is also source let post_balance = check_balance_too_low_err( &args.token, &source, @@ -2152,8 +2277,9 @@ pub async fn build_ibc_transfer( context, &args.tx, &mut tx, + unshield, + fee_amount, signing_data.fee_payer.clone(), - tx_source_balance, ) .await?; @@ -2168,21 +2294,16 @@ pub async fn build( path: PathBuf, data: D, on_tx: F, + unshield: Option, + fee_amount: DenominatedAmount, gas_payer: &common::PublicKey, - tx_source_balance: Option, ) -> Result where F: FnOnce(&mut Tx, &mut D) -> Result<()>, D: BorshSerialize, { build_pow_flag( - context, - tx_args, - path, - data, - on_tx, - gas_payer, - tx_source_balance, + context, tx_args, path, data, on_tx, unshield, fee_amount, gas_payer, ) .await } @@ -2194,8 +2315,9 @@ async fn build_pow_flag( path: PathBuf, mut data: D, on_tx: F, + unshield: Option, + fee_amount: DenominatedAmount, gas_payer: &common::PublicKey, - tx_source_balance: Option, ) -> Result where F: FnOnce(&mut Tx, &mut D) -> Result<()>, @@ -2225,8 +2347,9 @@ where context, tx_args, &mut tx_builder, + unshield, + fee_amount, gas_payer.clone(), - tx_source_balance, ) .await?; Ok(tx_builder) @@ -2301,6 +2424,14 @@ pub async fn build_transfer( ) .await?; + let (fee_amount, updated_balance, unshield) = + validate_fee_and_gen_unshield( + context, + &args.tx, + &signing_data.fee_payer, + ) + .await?; + let source = args.source.effective_address(); let target = args.target.effective_address(); @@ -2317,6 +2448,8 @@ pub async fn build_transfer( .await?; args.amount = InputAmount::Validated(validated_amount); + //FIXME: here use the updated balance if the source matches the fee payer + //FIXME: don't need to return the post_balane naymore let post_balance = check_balance_too_low_err( &args.token, &source, @@ -2326,11 +2459,6 @@ pub async fn build_transfer( context, ) .await?; - let tx_source_balance = Some(TxSourcePostBalance { - post_balance, - source: source.clone(), - token: args.token.clone(), - }); let masp_addr = MASP; @@ -2407,8 +2535,9 @@ pub async fn build_transfer( args.tx_code_path.clone(), transfer, add_shielded, + unshield, + fee_amount, &signing_data.fee_payer, - tx_source_balance, ) .await?; Ok((tx, signing_data, shielded_tx_epoch)) @@ -2438,6 +2567,7 @@ async fn construct_shielded_parts( Ok(Some(stx)) => stx, Ok(None) => return Ok(None), Err(Build(builder::Error::InsufficientFunds(_))) => { + //FIXME: I'm failing here return Err(TxSubmitError::NegativeBalanceAfterTransfer( Box::new(source.effective_address()), amount.amount().to_string_native(), @@ -2472,6 +2602,12 @@ pub async fn build_init_account( ) -> Result<(Tx, SigningTxData)> { let signing_data = signing::aux_signing_data(context, tx_args, None, None).await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; let vp_code_hash = query_wasm_code_hash_buf(context, vp_code_path).await?; @@ -2509,8 +2645,9 @@ pub async fn build_init_account( tx_code_path.clone(), data, add_code_hash, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -2536,6 +2673,12 @@ pub async fn build_update_account( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; let addr = if let Some(account) = rpc::get_account_info(context.client(), addr).await? @@ -2596,8 +2739,9 @@ pub async fn build_update_account( tx_code_path.clone(), data, add_code_hash, + unshield, + fee_amount, &signing_data.fee_payer, - None, ) .await .map(|tx| (tx, signing_data)) @@ -2622,6 +2766,12 @@ pub async fn build_custom( default_signer, ) .await?; + let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( + context, + &tx_args, + &signing_data.fee_payer, + ) + .await?; let mut tx = if let Some(serialized_tx) = serialized_tx { Tx::deserialize(serialized_tx.as_ref()).map_err(|_| { @@ -2649,8 +2799,9 @@ pub async fn build_custom( context, tx_args, &mut tx, + unshield, + fee_amount, signing_data.fee_payer.clone(), - None, ) .await?; diff --git a/crates/tests/src/integration/masp.rs b/crates/tests/src/integration/masp.rs index a07fb0f9dc..313a183ff4 100644 --- a/crates/tests/src/integration/masp.rs +++ b/crates/tests/src/integration/masp.rs @@ -1357,12 +1357,6 @@ fn masp_txs_and_queries() -> Result<()> { ]; for (tx_args, tx_result) in &txs_args { - // sync shielded context - run( - &node, - Bin::Client, - vec!["shielded-sync", "--node", validator_one_rpc], - )?; node.assert_success(); // there is no need to dry run balance queries let dry_run_args = if tx_args[0] == "transfer" { @@ -1373,6 +1367,12 @@ fn masp_txs_and_queries() -> Result<()> { vec![false] }; for &dry_run in &dry_run_args { + // sync shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; let tx_args = if dry_run && tx_args[0] == "transfer" { vec![tx_args.clone(), vec!["--dry-run"]].concat() } else { @@ -1448,10 +1448,11 @@ fn masp_txs_and_queries() -> Result<()> { /// 1. Shield some tokens to reduce the unshielded balance /// 2. Submit a new wrapper with a valid unshielding tx and assert /// success -/// 3. Submit a new wrapper with an invalid unshielding tx and assert the -/// failure -/// 4. Submit another transaction with valid fee unshielding and an inner +/// 3. Submit another transaction with valid fee unshielding and an inner /// shielded transfer with the same source +/// 4. Submit a new wrapper with an invalid unshielding tx and assert the +/// failure +//FIXME: do a separate test without the syncs #[test] fn wrapper_fee_unshielding() -> Result<()> { // This address doesn't matter for tests. But an argument is required. @@ -1470,6 +1471,7 @@ fn wrapper_fee_unshielding() -> Result<()> { "--source", ALBERT_KEY, "--target", + //FIXME: I believe this is not known to the context yet so it doesn't get fetched. But it could be knwn if I take it from somewhere else? Meybe from wallet? AA_PAYMENT_ADDRESS, "--token", NAM, @@ -1484,6 +1486,20 @@ fn wrapper_fee_unshielding() -> Result<()> { ], )?; node.assert_success(); + // sync shielded context + run( + &node, + Bin::Client, + vec![ + "shielded-sync", + "--viewing-keys", + AA_VIEWING_KEY, + // AB_VIEWING_KEY, //FIXME: remove if not needed + "--node", + validator_one_rpc, + ], + )?; + node.assert_success(); let captured = CapturedOutput::of(|| { run( &node, @@ -1519,22 +1535,9 @@ fn wrapper_fee_unshielding() -> Result<()> { assert!(captured.result.is_ok()); assert!(captured.contains("nam: 1979999")); + //FIXME: seems like the speculative context is not working, if I don't fetch this doesn't pass + //FIXME: ah it's because the viewing key is unknown _ = node.next_epoch(); - // sync shielded context - run( - &node, - Bin::Client, - vec![ - "shielded-sync", - "--viewing-keys", - AA_VIEWING_KEY, - AB_VIEWING_KEY, - "--node", - validator_one_rpc, - ], - )?; - node.assert_success(); - // 2. Valid unshielding run( &node, @@ -1560,6 +1563,13 @@ fn wrapper_fee_unshielding() -> Result<()> { ], )?; node.assert_success(); + // sync shielded context + run( + &node, + Bin::Client, + vec!["shielded-sync", "--node", validator_one_rpc], + )?; + node.assert_success(); let captured = CapturedOutput::of(|| { run( &node, @@ -1595,48 +1605,10 @@ fn wrapper_fee_unshielding() -> Result<()> { assert!(captured.result.is_ok()); assert!(captured.contains("nam: 1959999")); - // sync shielded context - run( - &node, - Bin::Client, - vec!["shielded-sync", "--node", validator_one_rpc], - )?; - node.assert_success(); - - // 3. Invalid unshielding - let tx_args = vec![ - "transfer", - "--source", - ALBERT_KEY, - "--target", - BERTHA, - "--token", - NAM, - "--amount", - "1", - "--gas-price", - "1000", - "--gas-spending-key", - B_SPENDING_KEY, - "--ledger-address", - validator_one_rpc, - // NOTE: Forcing the transaction will make the client produce a - // transfer without a masp object attached to it, so don't expect a - // failure from the masp vp here but from the check_fees function - "--force", - ]; - - let captured = - CapturedOutput::of(|| run(&node, Bin::Client, tx_args.clone())); - assert!( - captured.result.is_err(), - "{:?} unexpectedly succeeded", - tx_args - ); - - // 4. Try another valid fee unshielding and masp transaction in the same tx, + // 3. Try another valid fee unshielding and masp transaction in the same tx, // with the same source. This tests that the client can properly fetch data // and construct these kind of transactions + //FIXME: I break here, it succesfuly executes the wrapper but I've got a broadcast error before the inner gets executed run( &node, Bin::Client, @@ -1681,9 +1653,43 @@ fn wrapper_fee_unshielding() -> Result<()> { assert!(captured.result.is_ok()); assert!(captured.contains("nam: 1939998")); + // 4. Invalid unshielding + eprintln!("BEFORE THE LAST ONE"); //FIXME: remove + let tx_args = vec![ + "transfer", + "--source", + ALBERT_KEY, + "--target", + BERTHA, + "--token", + NAM, + "--amount", + "1", + "--gas-price", + "1000", + "--gas-spending-key", + B_SPENDING_KEY, + "--ledger-address", + validator_one_rpc, + // NOTE: Forcing the transaction will make the client produce a + // transfer without a masp object attached to it, so don't expect a + // failure from the masp vp here but from the check_fees function + "--force", + ]; + + let captured = + CapturedOutput::of(|| run(&node, Bin::Client, tx_args.clone())); + assert!( + captured.result.is_err(), + "{:?} unexpectedly succeeded", + tx_args + ); + Ok(()) } +//FIXME: add a test that checks that two transactions generated from sequential notes can be applied in the same block + // Test that a masp unshield transaction can be succesfully executed even across // an epoch boundary. #[test] diff --git a/test_fixtures/masp_proofs/11BBC6FA2A8493A11DD5E488B2582DAD9FBD3ACA2E0F8314642810FC958594E7.bin b/test_fixtures/masp_proofs/11BBC6FA2A8493A11DD5E488B2582DAD9FBD3ACA2E0F8314642810FC958594E7.bin index 809124ae22df903ecf004622ad952eae4623c7d9..9d6f8e4f8a770c0044b692f0baf6de89300ae37e 100644 GIT binary patch delta 1795 zcmV+e2mJW?PWeu-78oF!DvGU+i6>(gt6z+tt?+DpR#aX$;TQH=#V3OmRs#u>HW)%+ zkdE^Q)!1T$OSryx{1f$rXY5hk&nIxG(8k{M^t`YtU_zjWXo_SXt^`5SPa}~qU1UU) z8Rj=j-9l~Ee??9MM=)ztk8v0CubOan_x8K8hi{*U)=y5oad-fBW&nc`v)CA<0)IpR z%C;(wyJ;D0G5%<$u5UMG*!~si6J0N0PKvKakyng8Q>5 zTG^bD8BwJZ5A_xR%$BnN1uAkHufSd7WFAwBB}OujiR`_~h~om4yGfFac9>Gk-x9hn zHYwK)!zr&Lp(C=oFpnV4b3`kQBD4D&l>&c9O#`3xofG6X>&L@fNdL|Dh4;NLvQGR? zNkCeO9U`kXos(b1J>FubFx9I+71D{AcNhQi;BX$430Fe02PNe2(*s@z#QZJW>tOY6T}L@0;vTwZREjEp?Y8N(Cnp;@`(2uj9Q&n3+9Uv~4i< zXpYAL#5m4ZijlJFepjWh`+!>eFZWqQ*-%4wHL1L3IvWSxGZr7(mtZXrPeUJd0%Sans&og{U+gbkLXk-4 z;{@6TGM&mlrn8*T-ILoXX}P0voO1k;tU_0+7j@>N@c(Rte-i?ME=$KdbqnxLy1`Y^ zl`JQ$ho}xJVr%LAwlYG?@tR#4P(}k4Yx3)i7sukw0L{3FFmA*0!as6-$-K|tm@K?V zWlt{0dB+w}X(J}?$^Og`>NZ?2r=e|jf38n8*x;`S%%J#MtRXB&xq|~6{h^+jSD6*<#@8Izniyh>r`3qmHLOAe@7)lD5hM@DLyLVSxRyOJb zpJw;{8}7sefKY$TF|Hw#sR@g_!MhbVHDxy$_b z1169|f5ve=M(LtG(GS?SC48eFV6_`BAO?_PxXd?!RIs#$bBd5nnzj|gjwuzNi)mSn zdl9RUMO~zSY=%n`Q(3tGI&CmO# z5M?1H(-xtsTeR6{xW)X5QbIG%NbWZLHCm4Ydf0WIx@}WX9?NDsX^ZY@M4t4v_3xoX zmQ)uE$wi2Dpc6^U<17Vwwzs1~fYy5&ePW&EURoWW(B= z4!pz6Zvoq(Cc+Do?J|8x+h8f;hX2x3pv#;8_D^-OPbgKMi}vX?Cv2xJ43URA-LApa zC!Th84_}R_$xx9ul`+(y_GK-)G4g+te>0@x$@KWYxUQm1fm*}^U z3F9j)c7Io8{GTW^KK*!|*{tv|K(To?<6uc4sh9$%tl<(Ea*H|C8Xg3nt4#5K!e4L= zdGHFbI~~L_C@=?0BeDSP{lkrxGKK6hrUz^auNKk(S?(!jKUp&hDG(4Fq!1!3f0uaJ zN0;PW6f`1S7yPjl{Z)-Q*oWoX=lYN0#wFZPOQh2(xcUe_axQK~QRf9mKGOJk5uCU< z!o$^L)#ekKG$l>Hsv1wOV421?kX5mAxo9Wc+r4=bKuioemsfhbc0_$-DNa$c#=|@; lozU$K+nj%nEO+80s_|Niu2mV+2?ILK8q2{m3k{PrCq;^jcU1rY delta 1795 zcmV+e2mJW?PWeu-78oG&?ajh~2TK6V_{fiJT4y=)GiO`xo}X3g5=iaTN&6C$HW)%+ zX5~3o&+hBr$=98`e4VO#-m1nJ@plccx@4Xe2+fPzkpc&$Z>Dc2`XFvHAa(04dJ=5j zO5+5b7DgeFZw?>>O@p9SQn9bR#csv|S+GSqgRL7E@+kx0>bOz+586kXv)CA<0)O!8 zi;p}^QhzNePq2_B+f*rC$!qfnO(@l6m%uwiyd|QrVq9cjK0Z1yY_w7r=&6Li80qE; zHjgOf8rO;AKk2D^gJR~_E?P+tS=J}f{|z}_q7K+ORbq-bup{DWYuwpqIH7`pke8X1 zU)wjeH{Y)#p(C=oFpnV4b3`kQBD4D&l>&eNZu6g&$Z=*&mphRT>850{G2 z2{QY8ZkLdwODq-g*S<_+b420TzC(m;1=1s}{pl-K0FeAjUL71N%EokAGXfMwdm2BT~ZqzDrHD-XR$8 z*{r<+w#EVAkW)qevwrDac;N$4RY=8lW%ObQ^A3WjwG%K_w!1k&crnx(GHoW0WCoCB zF&Qa4=mY@aMr@Y>e`f%~xLhO3*hY>pa5W`{aZ9xCM1OwEsJsfkiiUIpao%H@osKcp zpc8cTj+C5pvw58Mve7>C67A|-yvvd&khksX+cWxCF*x z)#pfS@sz?kLi&^wP42c1fH@cIu=6A@`J)83cpVs$2F5u-e^&sD^~fIB3KI%dlvCU_ z5wn;lTzhGI4$QzJ>>Qxfx+0r>^ZLZ!BXs66$>51V!19inRzf7y2~j$=uz4~MXH+*4 z(5hZrZ>J<(JX|Ns1E@l}`(W1t#2!nsj00M8Pb`%MyMpRQ%g3fTXZ-hWQK!o30&g8f z!$LDOVzs2ke^@TUpD1>wrfGtA+pWvs__Bk}fx6!TAJgNZin}i6N|3#i1!9er~;mCAeL)%Ah-rv%?bERJwwKnP?*sfj8m|Ol{Ay>-qcl^zTf47Br;OYD*>#D z(}Bpt>dtt^@>$tUgDgQE{tnY(P`+1r7ut+cT;B=XAF!{BAsq2SaY zhk2B^q#)GCWf#UZ(3W!J7{78Z{KSvFk5xP;!8L<8Xpfekr16A||V`M_k*l z{<#iuDRJTs(zWBbdtdS~x*p!JqzpU*lw0vrbZ$S!JhcO>sK&>O6c*?J;33hbkigT! z+1eN}l> z?f%Y>{Pd+IWyc0tfkpqM>ehTJ$ lVi~}VjC(suqee>^kl^b5d1ln&3B(F698L>-fa{YqCq=$oaCZOz diff --git a/test_fixtures/masp_proofs/2B6C3CEF478B4971AF997B08C8D4D70154B89179E7DA6F14C700AAE1EC531E80.bin b/test_fixtures/masp_proofs/2B6C3CEF478B4971AF997B08C8D4D70154B89179E7DA6F14C700AAE1EC531E80.bin index d8c8886e1bb151090fca578f75ba47ed6c30de99..65e1f5ddc8e8bf282a8f715e28371a528414925e 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6>;QpsejpT*Z=<#!kP90yxd{(+A9b8}Nn&FVtR%rr~0yaOcz zf4HKowS8d0=<8w=1?{EAH`wG zVL^*l1TlHJZZdG@<*hE|MNaRcWTI9^f0E^js~Q9%^89d)XtG7K30kj!W;w#PVkkF& z!%6O!1*fg~QB~4`-~Qw13yBROuzN!{UIc}vOeCm#=Ge@bzH2X0sqK)F~CSy_wp-QctJc8aytg!0+RYsKc)2UZ@|t&i_5!wtcUHl7!{KI0wD~O G;RhUw43l>N delta 308 zcmV-40n7gV5B(3YoC6?Z!~?K&0|MlC-g@m`-0evkfr>E7Oz$i;x3lv6>KLlokuxc<8D+4tjZ}XIajcE2 z7X!8`7mp)On+?&KTH%qAF|kxC+m9hAM{GZ%7jJ3jT8F@a=Tb5k8q1JbPZ^`8=05sp zckKy+a)MlEb+RBMX>8q870rVbUI1L{e=QT}rAiOtRJa=QD*~ ztGsN9@q!w|05fZZpGxSRKz>Ia+{0TuLAbpcMz|Y`5b+xN8&4zNq2jVoOsDc@fse-q zE$D|IN|BuqRFDKM!mbK8Bo~0tq5m}0w4SRwm$Sy`F$wO8?my0js4fX`bmhcuoHS!ob|2=dbv0Z#Qst!|B^jl)GIN?gq2sCC6hFrz__^m; zz#faZ$T{_S2Sub(OVt;!;>0_}QL$Siq7ve}mc`>oe2l4&uEr_GH`^FlaqnGVz|;7PB*fw+A6sLvAz*+?NVQ-ZDgn0AF~0=f;8 G;RhU0+?UP( delta 308 zcmV-40n7gV5B(3YoC6?yFvd*G@relAdT!CT+1%qbnDe_nsEcNYIZ4a_;sG3LQ|*#{ZdrET^ly zE3|U?XW3gC-i}j)lYI|EtFe19uR6o#?v)D<84Gn2u_P`L(3u40a4JXkf&?~CpX}9W diff --git a/test_fixtures/masp_proofs/3FDD781F73CEEE5426EF9EF03811DFBCF2AAA7876CE5FACD48AD18CB552E7349.bin b/test_fixtures/masp_proofs/3FDD781F73CEEE5426EF9EF03811DFBCF2AAA7876CE5FACD48AD18CB552E7349.bin index e8ab8308e6785f1e2176a757d430ffa33eae0cc9..1452014ada1d9bd81330bd33b55f9682c76f18c4 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6>wPmk5Wk9Vg9XmE^(nEx@89nDWOl{L=DWOhupOatz-yaOcz ze~=!BwCMoXa)b0m?I<2mo6vWq>%SVNn7(t(LU1!9Y>;FF?-yQD5rX@z2Eel@#j?(u z7vudCf}9D!DlnO(X$k%bTlurn(++q?aL2OKTPC60!dtaPu{LS*u}xVK0v1Dk7xCXv zDQmg9^aO6DU`p<*mbfsOy-pi}@e`6nf83m3+jn~WZ@4iw81Wv7@71x{-q>}>RlTKw ziyNJCw0a}-3LJz{L1NjAA}Y+LC^nIhQ%@Zkf;AaGbn3H#Q{GL^18DI|0kFJWM-~?p zWe)1=`{X7Rs5%u`AaH#PmB-&-SDmc%2}!J G;RhTgl9P!5 delta 308 zcmV-40n7gV5B(3YoC6@*-NJ-I_?r@rsPcWYh+490whEQB8DdBAF!FVOZ)G^MyaOcz ze~hQ~)?hd9&y>swYOTE2?XV+oh!Asd>l8nJI#qs%MqJjV^ zgs|54mE(f&sM;B9zh_hQs#)YiW=pYK8JCH5z0rcNSOn%H_)of9^fp@2fCNT8GvleR z4fh}c;A4z>_SeZYrdxes!a@f7ZkdsQf9i5~mD2DWN}GkY`S6SdL;;hez^*L0MtZ4G zR3rX<)?}YOW%UZ*cpjgixI_Y${WVlFAcP7GVNR3K`d>KQE%AfW)`qUuREa`OtS8

(S0rtzi?H5_-n*yat|F)jF=Y&YcHWSGHuOv@883mX` zxdK^KUDc6cC2o=KJMDKS)vQ_}{O@elSP;WCX_Y~VD~3)u)tvNYK6DXoW$mwe6g`3- z>NWuF99qDk>V@!aOjA@CUL^6{k?*r68I=N2F2{G`yM)T!Zq*S14&L*a+_u0N(<%=U zB4zL`-~K5(i&A<1+B8v$|Ivx6Bkl5@+ESXWd4Y z-D0RLt^gi*FMwL3Tq|}4ENc{zdbkyBQJTCRfmS9u5|avOSgKKVEl+Iwdn+KTN4 z@CEemZs%A5>Qv(%`$2jMmcCmbtLQS%Da28+JVPT~226!}$q*B1Q=6UM%c%49wa93R zmoQN>@(roce@_Ir5ou~__grDmN8joZODf)Ef$WEw{exbv40ZD$gEIVE2y(7$O-rTR zumuEO59M%-zOCu?vIEh?4S#dv70lor7vW~s>RAb!* zgUCWAA(1?~nJ5El#|M4Cc>`xoW@z%~+3~egSNq)dTg7R1hal293B8j)sbc`&v?ndP zCp0tBf-AzFS^s0D>>oBZrLTdlu(1$)u!;GW)?6i$?Eq~GuBPTx`mckEk3hY$=E$Y*mkIj9Kx@8H*D5|+(kC`f}jJLrt1*CrLr z1i#5t$x!{&)A6!LQ|9aOkgfc5z#bTzKN%Jke*#pmCn=+G46L(L?J|)QWnlgGR;v~_ zH+p(FiMVG;8L_)IZI!V=(LPnComH2;vFjfvAJnwJ(DiF}?DV<4IvD^I%>I7l$)jm? znG>6#`{3ZQV&FU8Af70*-IFvE+IgtHwp17?Idzw23L@ih-)*Kb`&FIaik6E%I7_;i ze^~nqtCqmu+(pbt;n>5cNxz3+?*A9I-bqD7Q4p9yim@bFtpSe{p3cC0sh+`XuPX5< zID1|&zTFKTq%av>0Bbv~_m@_-Ju}<|KSX?*RTlH>D9m4k#k_S^qBz?d(xcc>WIENy zis_f~2-QOL)vH?uqc^a*K}=|p&kjb2e@<@%{mMBmCi5v|RXnDzfC&XtIt6?MILRPt zu5wG?^Fdlx__ss}29_y#by%+X$(97gm6w&*z>R4ii}_@uN06hb#?8)+j?@g172w36 zeYA;bX~E|;ucXIZ$r?|_yYU YdRTd99cdkp9@!N`$pqB|1e1&)Jk?^*)&Kwi delta 1470 zcmV;v1ws1ALC8U{K@}h&7yv^{v<0aFc!VU0mo$v=?5#|w8h7hVHH7P zt~&S$fuEp%7s`WcW>BdM=Hpk*H8RTi_5jIUdFdpS=H){nEnNEO zm#Cx}p4?^R7&9^j0-wCRXYi8$YjW3N#mjtB6)!EWc}~G^DXXXI{o-1v+p_}}qym4H zqf%U4=<{6u?JOn5DG*dB53ZHJ18q!7#9v57k;V@!aOjA@CUL^6{k?*r68I=N2=K@nTpM(4|`*#Yn3jFbQYDwr%Kr3F@ zw6+i$Nl4|cXA%DFEY%eLE?%S+ejQi>O~oZzXs#nk)mbqFqx4a-WH)JF1USGv~ zoz(Rg0FegeSe_GrSwBCIs;R03Nno+(q0cgOZT9FVA}bz zWiQ>Ss1hXnRBs!>Q7!WnNYgcIj0S2kD0H=|p$zfZa(G0Af2dnKx$@6Y;s&&qI$Pb+ z3bUAoOC-^kiMLgTOTRa-y$@E-%?`VniSrv~+i+Wq)xUM*9wFlfR1`ViZOxP*QA^#SiRveZdB7{xNId#a}Y z;%6WSue5ZrWsNxa8L@g@td$1N8@pe5cE1}w0C@MNbO26o7Lr`bev4H5l8nhk!&4gs&I}OOC;tYn=0bsISBo`G~|Zu;u@Ph$cA`VM{knF>8R#7fg#2Y#b7(wP`_;K z6J*fLo@UadiEs-lT4&(rIz}Fi@nkIg<}FVKe;OA3kbb1=__!`!upV&(h+3Gt?K{EE z8Aj$BJ%t2wwt;2(+@M82qJW_ht3gn2gf3nmE9J4>T~7_3dlo0`BEN!%_aV^X@gZ4@ z)F?kd0_`|zh}a6EPM}~RWUo5r-B+y6c})&*rZKe!KwV~Xwm}*?Od!j24@aQn+`zj< zf7g4&WhT9|3GS0xb#T%3BJ#I>JAaOoKqs>|%OdZc@>}+4+VrF-^D&Y3)NzAzhvoY1 zS*_WM&2N`J(}0te5fTRVTEzH+?I9(In4h z_fB*_om})`d1Zv%7_!c?JQTW+g>c?1=99u?odpE-XXA3>Ho3rb{wye9+Z-~x>;tX) zd)GLrPXUr=w+Yyimyc(IYzz{xA`)Qo3~7tztSNd1+|nEk%p33Xj~_b(NlYavNG6k5 zEc}BQitzbseNSxz0L77a>fTqVFrfRK(mN4sABEZZm7i|3alAKfHX6_d@xa5>gDXp zsUc?>OgP-HJ>V4zeflkL!sKVh_mu=r

dX*f{S8ui4!4)x^5^;NS9$g@3bl6}B$- z+Sz|h=v)+s+S(;P=Rf-V^8RqvIhv3?O!fIXXE)hv?XJ#L@0(J?cub7T@I2GOxoj7{ zJzXtZ);;wb$l;@4#D)M9(C1w0%hi^Z{(lJy1W>AGBsO*8$WM$bJ%siOz5nssUEOBc znl%ikmcKR-o9Mtgol9G8uA^bWi57idDbWAk#@QL=ALx)O?tc@n+ zwR+U+$R1App`0Jy<6+2VuA`LyXVMD`S4PWIMW6m9`52sAg$*Y?q5pvzu)l zH|#mRLZ>7}e^;sg^C2s|YHzaFk6s{MN)0FJa5RSM|nZ=#g;&tjt6e9~uNKm)Ujjh!?X2-w( zYP@vAy^wZ?LZKs0o8|2mvp+woRdub1ZB2pVqYdAdP4{$5Q<}N^+fx6qBrzW?#+Ay6 zOE#ImHru%Q=jiS(ol|_@hV&6ooxg68)l#wiqvskTVDR$#qj`y71K{gpi!3tTt zbq_i|`tdZ}kv-5V%jRZaa(3qKmsPjjmanaxp3mF4c6!kJ->*EItM@YJPyF$=<$Y$m*_qlG|Jvi1;fX8F9QRo_J(#l3r9r_@ZuP2;=!bmw zmM=A56Y*9%Xjy-O$F2_wm)C^K{W`HPr<>VI#AUicWg`EbPiMZ|Ir%u-KS-jY)_r!{jR5REnen2xls^x@FPs)00cnq*RR! zFCE)1v~bm~nKt*HckR&432%uywEDBtqTZu>CvkA}EUTINI6HZD`%v@=Gcl)0^+uI!K{+z$nAND%kcwNCxF^BfmyBqSk?F3f@ zXLP#Oa~yPCQEqVQ+s}tGuV#ER$?4B*Ey2JUNnG}kxckBic;qqcQu zcc=vO(@9^l7iC4$et%E|8;{|55e8JN0q}!jdWgEQHCJ1z~jaG4WtG+HWYM+P#Gp^v zG^ZuPIUJ?FWxCD3};6yIL$+?zvM4<>$?9F-8bdxlq!$q<*p4e4|z z+0j`wUC52dq5eSL9p->f_nc|ReweAQf4(T#nl=Mb}4 zYO;c~3DBC0gED_I-{PX-_{z>3;fe9Aia1|MI95BI5LE_$y73|+Iim&i#yljEU0i24 z1Npm{QDIcUwSQCX0zMG5OrOfz=Ts8?-DJ0Ta^+4>zYdTw8p0-*qt G;RhTPZkSsD delta 308 zcmV-40n7gV5B(3YoC6>_a5&xShcZAG7{?G@rze<8@=ylf-y?}a;-qOIqiDLbyaOcz zf1oxWU69spiy3a}$PCljZIt6#x#fn)euKqF#`6d%GE`e`?)De7#vXgfDbaR{@VTa* z#Iq(^#323ZN?N?1k^1Fy*l`IK=J9v}2%6&=PLnraBy8QTJy`)^;mW-?;}C(Xor|>A z$MOdmJSUy(H9rXDkm?y!!*htylLhj$f7si`c2N9xErqQhbN}oFhtr_x$oS3E(=v#_ z2M~9%K53M#tzZIg?mqyNG$ABn4AumkzxOeJdYv^{HiVBgzKqcasN$2krhNP+7=RCv z_(Zn9d%s_-@FO%e4M{|F@&nwdBbYsePvqzX0qQ&$zfL3nd#RU1ODY;FC2wbZ0yzwm G;RhVMQkF0P diff --git a/test_fixtures/masp_proofs/7A240D86DB78C8E1478FB0857D16BE737B7C747CD18D3B832DEC3C9DDCF3DBF8.bin b/test_fixtures/masp_proofs/7A240D86DB78C8E1478FB0857D16BE737B7C747CD18D3B832DEC3C9DDCF3DBF8.bin index eee0b431bd420ac190dc7bc444ac766a53a17340..681b074d16b20282cfd7c46cdfd4ed9d05407bbf 100644 GIT binary patch delta 926 zcmV;P17ZB1CZ8s-UPbhLForR*-e?eZ9aG%RGkzaH~P#?+~B4l`1wp z0g(_Wk(~&W8xSCWvg)P|^v#TB6$I??$;AEiavu@y)kAYhn!&6{cdN~YR!|(|)AY=7 z(2mDKeiL5_t}_}o6xFU#$g(oc18#i}2Ei8Dmvmb)Cl?Mj80QXY9Z9V!?MIMAr+6B% zn}S@86YTwjivHP)s9RCGIOSr0KEA{lL(%d#Ypoij4gh?A1N-jZTp{j)4f)Z29Mw+P z`nPql50Rm?PeR=YbLow+F*pQ6qCh+u`KCMFo~2;cvRNjs)YZ#)9P9oefv6<)^cC0T zP`cGVcDsV3{~8jM|=a(ZuGAuiryrbNV(hTD-3Jr&08x`BU#A z`c?Qzzx=v?ZU?E)+%qMJx>A0bz%3`zlDTMkQIm$qaFl8}$t40C=XZXzP)|u&^`|<( zEr-><(6N≫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 SoQw&J1_20>^di5L%or``I564( delta 1152 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 A0{{R3 diff --git a/test_fixtures/masp_proofs/AF6B3A470013460A05E8A522EC0DF6893C1C09CF3101C402BFE1465005639F14.bin b/test_fixtures/masp_proofs/AF6B3A470013460A05E8A522EC0DF6893C1C09CF3101C402BFE1465005639F14.bin index 12a7af575f7c235afc7cb969b944424c5847ef04..6c9a57a93a2110f597d22a7b0e8fcab9cf665ba4 100644 GIT binary patch delta 2424 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 G;RhTSL7t2N diff --git a/test_fixtures/masp_proofs/B13164F18807523FAB9840F34106FB77DB730FFFE562F2565B0431F7A901CC9A.bin b/test_fixtures/masp_proofs/B13164F18807523FAB9840F34106FB77DB730FFFE562F2565B0431F7A901CC9A.bin index cd3c95a2647acf30e9011caf86a628b14ce33184..138e8d996a07283fffed194b5b0dcb7512f8a109 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6?DR@zybJ91ObN&+V?K@R#WHO#p2ML-*Q(`r+3T1aBEyaOcz zf35yQqOCSnK3$3urnqxF7S}odIm-1Zh~=`?uNt<8KgrnckM{Z2G3Hau;oRWSqp^b@ z)UYnko~2lq;>e%;gB=!qgC0oI+JJpKJCOu?ajReCFsE#}7(iH|1XkvG_6FDIC`Nqt z(=T*z)W>rC0Q%xtB34a80*i7InGS#|eF2Y8kY%!q_m*f3|vini>mCo>XwY`j2u$`yu7(ajTI0J>` zC4Y~dy3GmdbEcCNZy23JTo&w^RRB1t>G-GJRJ$7?t5`}nWUxaVO864%bl2F%0vZ65 G;RhT>%$Csr delta 308 zcmV-40n7gV5B(3YoC6?G(0l^CPUx^B3y4hi1#CNX^A!a8qNPnt1pDUb#4P8tyaOcz zf0FVHpK}=N>el;fqqv!REKAd3^Z##sW(AbK%}w?hi6HG&ReS
e8MPogxWikR)b zP1@OEN>7KK^|?SyhY%vT=T|!99ZDO$s0hM1ak+axjmE`$weM@X0)2xMu@Sr;D3uKQjOq!gbXridXdvdM-ej z_545^-A3LvC`ypbC||zh%%86C+Y=>(rz_Tip1V-&XseqhHB7PI>QcksdIsg30#OW; G;RhVGiI{o- diff --git a/test_fixtures/masp_proofs/BE09EB8FF98C0CAF7BA8278C4ADC5356710DE7B6F6FA2B23C19412005669DC2B.bin b/test_fixtures/masp_proofs/BE09EB8FF98C0CAF7BA8278C4ADC5356710DE7B6F6FA2B23C19412005669DC2B.bin index 68f0939fe65cd9aa9a56aa9e6da30d3ea4d16b21..4e2fd1fdb85c02983101721d3478f118928730eb 100644 GIT binary patch delta 1797 zcmV+g2m1K=PWeu-78oE@VpmmD#%EE4=WtoH#!k4mX?=GDUCjY{VLrhT%gjlWHW)!+ zd3fm48|O0);{Fi7&dzB&CV*~S2tsH^=BZ5t>*<3Xufy**@=FJ6>^i`a7{fO5cd4xX zDXM6wwDq28v@s@c1FT9Uji}Hvy{36pLatlA{)$jw?oUh_#LyjR7A~scDzn%aqym3$ z_zgXAzGqu(@n1i6fMUd1#JC_ro>K7z8;muZKSN*1%(A^S~;e+#4z zOk^XpVGxKlq0(@G{SFg%Ek(x{M7)Fk69_%BTr*nnmr9N5rWp1 zvGhD+h_etJPjzZ4hivzo(nkZq6Zr*lYG4&M%JCU^d_&H@spz!{z_~(^qd|*{=6Lh7 z49W5z%m zErsJf5&w8y3)bW1HJcD-G4Q}9v>wroR7s3zb!=hHCjW{pk zbEY7%z<@*rsDJ9uc%sK;IV5VgRog0R^|{;A+qTw;?w(GSvdOI1KyMHtd=JYMKjUoQ~o)by6IR)%_ z^_E(lBI!PwkR^{tRrR%#vU3P+>+3P<>6SBHgao7uJXUbs&KzlFZzwQ$L|s@q3a2*} zphH~FTRay{hAqYt;Jk(ov@cb8Ku~(G=SZP(a!fBx?QLBRHlGs-tRz;vt2plI{3ju^ zEg8*|DSt-K?$ec+AT?V9CYAN^H3=t718r{P+uoaVR1+!i%LTtel_UE*K`YOX1 z;+`f-;B)n)ABSezWpygY_5_}z2fq;V5W0v<;p_*0ih93)JL~Q*KxsrNP}y$-bs~nJ z2&bb9@(C7&wo(wE>|GG;AKvOfP0JymzKiVoCx3P+kHn0wlfG4FNUZcI#1vHvO8!^W zhAbJ=d}7=`WNgP4l`*p&SCFQ0pUDMpX$XCv+G66^>jW76=SjmK1w6&}u>T>@hCZ6k z$t19$LKkM*|KLXgUxjOCcq8*w14~3rJ+(`x!hHJ8GJ=6q+or7YlWcr?lqf2;l~Qw9 z%zu^N`5~?2ldw7KU+i4f;>enWXKdMq+-lvtW#S8nD4~78`;YN>vIBUxBvZS&7GdX% z=fwMgpNKa9&C_3rz9SbfuqYle3VpVY7o0DkSMqi-W{b`HRF&J}YzUa4y(-Eoh{7@R zZ(nkHbuttwXKjF-sjRVI7x{fi^p%;W0DrS1Qf|tfEF_~vs#R)SkH2mF%6Ar3Fnc(e zT&}E|^3l}yaM7PT@is8%r~7-Xf$h`syql1@#;%jlW0bhKBF}1b4x^K_?zc`@6s%8~ zksW&yw_HZXTM@rgj?fb@brw}&22wur1|b$IDMhgzg=G(z(~oH5rnOWL_-cE=&wr1! zwyq2VZr-qB7rkVgd09&yUJcH|^?B2#63>htnJ|OsQ6YB2?KmfAcyJ7fS>IcOPdB!r zEdTZKnyXF{wTI22q7cMMdpn?l8iGH|BnhII{9=SdKtlC_11lI~q5U@+&(N-oKBmKf nwD9^i?lxl7zVoQxJR@eG&QG$yBMMCybC!y_ea9&VlQkzqzuIxr delta 1797 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 c^%HW&woF&t`w$U~zRC&Lu9Juoq`Bx2-2^K+N z_oI!_LXcr~ zLa+Zwm)*KeDVMGg0uadM?U5eFJvYzK1#ib4ELKAU!j4&4l8?kbuT|`vo3pDHqym3Z zbh@lfRFvF<4$_rQRnhhdxo&#L3=+9hJN!D8_XDvbLoS!Tk376 zWim?_0g(_WlP?PhljIygf0jCXAE*IH=QWpGaA&84OqrJP{J*lT{Yn+^@{lgJBfEYN zrKRBe#u7b+>NyTbbAaMEvZwD&$bTvIuhW-@l#f~||4JBymb5g7$QX^%Zif?Kj2mQj z+){P2QnmzR1_Nt{MHL}yUID4eDU#rPsFlVF3KT_?j-Z2kiu|+5e{f_+z}0jYEG4A! zpiq%|;l`=BKd&JgRV9{g%_0*^Zd*FpA5LH_(x-iD(7~ZpmyDi*at|0LsiKGlZHOfT zDuk$$y}30mdoR4T9F+MmOd*qcPu5h639~uRI;HCBrRmZ+;~DdIl=D~|e-}F@mlgC% zvRgu_ip@BeM^78CepmrMC--n2c|$nF86B;aWsr%j{I^T?2?AsE8|ObGbcdk7*Y|a0 zb7XDviU2noLrra%0y<1_Lb5s!{2J+2_72gaqiN$Q*UXIr22YqBMdvVrR;QP@D}e4jw+Jo z4%QbUe*Svje*_nbx?DO}c5A=_m?ZLw7etOQ6ER@W;sr(U*IjkiZ?MJkT@L+kJ&68I z9%FFBP6L6dX5XXW6B!uDtz6Ft=NzV(#3K*4&RBIF8>Wdy;%ravJE;cd#Q`wvFONIq z{RL7@y}f2+pLH&?hgui(FKgTt?F9a+;)_dnd zFK}Jxcw8w3L^aNmH2?Fy-~$nmv08>DI#Qv(sZ-^qt)?!qPn#9W4JV9(I3IrJeGWW|gf1vo^$tFiEY_4~)t#*O^Zq>J zi!Hz8^cWn3F%3!y{YLN+)xlh}?}a5?k(`p4f6YE;)E+x8xJG5JGfpnH0jlzGRz0z4 zG#r*mr`eP^bK~F|R^JFJ2;kP493QJ!5=a>(x;=GDrvN7sxD#Ck4eBN{2{RqpR=dCj z%hwlc^2TF1wNN!?rfUof{GFF?x;?Kth-0)bXtIlko3zYIPi_+B>6&7(0TZK~*a85 c6f+kOkcHvpn*#!*Og_9bAA$O}0+VDRJZ46}ZvX%Q diff --git a/test_fixtures/masp_proofs/C614F20521BADE7CE91F2399B81E2DCE33145F68A217FD50B065966646F59116.bin b/test_fixtures/masp_proofs/C614F20521BADE7CE91F2399B81E2DCE33145F68A217FD50B065966646F59116.bin index e93c32f27b205b6a70b6bb18e558904a5260c1ef..d83c46f49a3012e806cd728ab439f1e89f51fff7 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6?bI`x1~c`{Q42s~%Zo1nQdT-{FKz5j%?xgUCE;PcS4yaOcz ze}I7pJt}*P>Xb>`>{nLQf7sbrDI|k0&PaiI#j=72SEPd-X^A6TzGd1M zTVLK7Z=KIJXe}c3QGYB+gJS=2}TJ=;5mk22SbJ!yunaRUe^kD8`7MfPZgT`?i9qq68ObE8R}@hIPkA9+^$hw zP^O8J$sQp&<#4#|+??UC`N}h>1+Eh}eKt|kK5IxhcAu8KZS$MgvEYco9s-FFsQhxg zbzH9!b-zTAy7x>toFldwlJMbGfcs@re+a_QP=8XwCY}8bvCT*J@4$r&oi`oxUq$W} zHn!`w)O+d*3Mq7UQ1=Tc2k}^9Bt97sFJOPNE4rD`+x_wnKf&Y*r?S{P% z$7ua$5Jw_pX#Ay6Phe8XMp?@V)7(`xqw6vHj>~~m2u*KMm19peU)!1w2GfWUMlJMbo(!PMl znNN8gZ2PJkpeeS$0(p}@!K3E|QNh2=s>$AGp*Z!2=SCYG z5sF$a>m%9-wF69)<9rCaO5(KY`hluv@RLX4ytAbH;0e=BzqNs_i%@uyWG4}9=A`{b+YaqekX!y zwB0S3F%%<|$MH_c9yq?82MsChCY0l2$w?nn3h5=As)!%1G~toN(qJ#GU$B#Le@_Ww z6-01vKp!r#mp!++EZKrd%E|1UJH>@x@A0KOI9E99;3(8;Ae%JYTM)Fh3tyGfey+QLe>@wLWvFw) z?@3dXyn;qY$W8Fl&;T#0{U*ef4lL_4N8#uSAr3q zZ9MG-s0Fq{EsEE(+Ch9bZO9&ZP;yR?I;Fd1m_|V5u@G$E^`~_t8!NRevtl`k2_dPz zTmVNR;&gk2LV}uKtKI{K-@6*N2pa$zW=$9oyz4%9mKptvz(oWoi`bhTqr6`D)H>;h zRSS4T&+dS$z9|&{e@kXJ;+-_QKE785lbUu8Jt29@g=93QpVwi{blir!m7+elQUAD@ z>vBS+v#X&z=)|yLG&RLgUJYX|xOWr;E<;jPo=bAE-WZ{h`gucxRDth~92$iK<-?Nw z;6@H(4@ak%1!6MOjB~FwKOND=-V4VyW}_5@kIbISR_Tv`e~pJ7k3<4Um2$s#v7;FK zv(0AS;XZ%Z&~h>18ihOQ`Y9zhaskjh0DG)UK8d#(O#`F{a>g8ONXgAEz1;}J8gD8c zq-<1K!Wf_y&y!u=&G=)HSxJd>rs0mQU1AjIoKN%~PrG?lt(rxUL%WQ6)+fA*{TWy~ zPFNpw`#Z=*NQ49wh_J)i(ZLhRbJ;^2K9MzgB*f-SC(5d8cqly8r{h@Bx^I5%Np**C6h!dsa# z?LP?t!<*Joc44|}0tt2RlfKMV3DB^cWY$?{gUmrm7F@FUDN5b~51Ub(Nwd}y^a3EO z8sqjFK3E|Q7H)Z+%Z&0bFe)_zCcV7 z1EE9>k-t>zc`n~+&ypOSD=g5x$nysq&ACFItMtUvGuk$ZwiZ3+{rdzsde4p@Tj(O( zH;MyZmK6`FwaYobAOVpOD3P5AlMfm|f1nBC&6e%EA^V8Yxv>x%Ca61a=sC{$@6qvt z@wh#3XGs92DTxkO)bxE`}}8YhPa`&;*I{4R338JskQ2d~kU%e>WMd ztwwVWWDCO(zh@Rdw8gh{knAt$DudlmrUzzCY93;{J0KD3$szh4u2-A|vNwXDEmEl(7Xya`Ul4lh{uYt&&oP zVn`8h|BXQ&Ti00+V%jnS)mm7!f2a$PT}=tkz11X>Sj%u5% zma{64zRaIRgj5wHFT4d8ARa12m4R~*3>AQpCWxOOQO!N?+myMEnGjxte}n35o1GL* zDqN41b#+@591Z1}pzd-y*k#R2?`j9qcy;;nJ&Vlmnnmx5zC)BVYexo}`Uwcp{BJo0 z=hIlD;A<*Ki6beffBRzBWNYwQNatn@K=t5{M$ed>y*1*6* zcM!#Q|MO0M+$%@ErJ*Qqhg>kL73{*JU!gZ;1<`1?3WT-0O=%sp!kDS|Wnnmg%%t0K zHzsK5g+G>fSV67oZjyi~Lg zj5lGzzoVb2D%Omx$ILvONi%GP>Uo{ZhJ60nzJ85c^f8Bhe?|+F?4Jy4SekC*?%MC1 z1zDP%d&zpg$+ohHf2+2EKCy9v5B^z3Z5(R64C97(8*Jf}EG#uz?kpcnW_(7uet@|k z6FM+Wv4SV{;^aauCWg+q433&t_vBiH0_^2j4g0FFM2(f?&9tUYN*0CPF?xY!$O%bv zTaL+(OqIry%||Jg9y(2IF#^o)%?6zD=hFbUOx9H#XOFONf1@I#Ndbp3*$_%GGbnr4 zdv?)ry�ZuDgzrKaZ{pL@G86HcN5$0ee$ZQ-O!nb+KCNbPX@*n58H;HNbhqi%)^O z{a`9#J#tz;q73l57=8Xg!@v7~l9+-fSc)1F=hqIETZ5=e5E=q1q*8B2_X0+6B5@Ud z+<-@{kXMIdND`HOh*pF^QJkhM2PfAC#%;*7*FqP^T*G#SE@^#A|> diff --git a/test_fixtures/masp_proofs/D1DF6FEDD8C02C1506E1DCA61CA81A7DF315190329C7C2F708876D51F60D2D60.bin b/test_fixtures/masp_proofs/D1DF6FEDD8C02C1506E1DCA61CA81A7DF315190329C7C2F708876D51F60D2D60.bin index b15399485612fa5ac9e264f4eda3343154d362c2..a791a47beefaa553566f0b6b48f721e0862166ca 100644 GIT binary patch delta 926 zcmV;P17ZB1CZ8s-U_0l0t2T{xKhyr6s-8Fc zX9END?Qqu0zp2`^t=mj~>dqLBoe!*X8d~aXcL*)+Sz@)PW2(G+{HJMb8cpb zd$U(gQA2B9GFpbiO4OYs@c&>^eeu|kmeM-mrBdip)foET znGae;WB#tM9N(_96J^oPXdY7ZSqDY61-U3yhGA4`=B#&gWW4encY5DIv`}z{>~pZ z6}9vCK#if!6JB(?mFYXokI^p^SNHkEp4k3HtWd{xC$>lz>N6R>L>+m8yD&XJQ@Q{n zh*4N$kHo_esUD|DfsP|D)-THY(!NR9@ekg_wZv9&S0F4(GYod~L9y(;0h9X@Br$Kw A<^TWy delta 926 zcmV;P17ZB1CZ8s-U`@OT!UCpOksh4ULVwswqf-jXJLodbwe_gu(SaA3d_eUS}}crLzZ%?=-Ms_j*< z0g(_Wk(~&W8xSCWf(A!gOTBF1zR*dAL`W~d-)-eJ%xAym5>+f%5Y%_gsd_9P~lCB zyrn=>`JkwJWfCIkGYYZi_-q#P7d(AR9#ksCL>@jReFmvDOx9N)q4E9)9yUN~>FyeBMe6O&M>m4&#XQZycL ziyZu4BW6gC#VfoC>+!RMbrhPWuT1|$=bx7rN(OH2=j23V}NH|8!SMdh{JAqj#W?0B4_mp@tWtia%8aoHCd~w6$*PJCW4-vY$Q`G zlR3sk1g|!-bioIujW-?A5j%z$P{3I`9bs{6u~=jgY%KYf zA-VXVdXQWNpUzr2LbWO>=(e|H<>#+EGQTB70AT~Px z`eZm34>k-tilaS$aMMh`dO|@Yuq!V$<+YPj-!BMXtrdFRIWcJLu~2(d3X}U1Bo-jI AbN~PV diff --git a/test_fixtures/masp_proofs/D38C391DF4F1F69AB04682F0C1B78DD77AA5620AC08519F73AB740B5A44AFA65.bin b/test_fixtures/masp_proofs/D1F174D8596E8C1DA892DDC23D322056C14747EAC3FB1625F0A86957E00ED109.bin similarity index 57% rename from test_fixtures/masp_proofs/D38C391DF4F1F69AB04682F0C1B78DD77AA5620AC08519F73AB740B5A44AFA65.bin rename to test_fixtures/masp_proofs/D1F174D8596E8C1DA892DDC23D322056C14747EAC3FB1625F0A86957E00ED109.bin index 8d9b720476074e63e2b18bb5dd3684488b8ebb83..f459f6dea66ef36a1bf2917fa2d836e6c349aaf5 100644 GIT binary patch delta 1276 zcmV;M1%|NsC000000000000r}6Mwp6IB`L*<<%T+i%gUrK~O_Dm{ z_(_N`BXfW{P?0g>1cmdk!?PCwLj*%L`O#P_%ZwB|e~wvb>NGVqV!MJQiN*g0s@w)^ zS#(VxGFs|MWCRmgthUi#rz8lS*CZ->VX@iUP?$bIEr|aeAOVxH1|Iq|-MGtf_=ui^DC^Eo2fXw}jpH zUzUzav8;Zn8M6-zqym55Z*RKXfFSmm*@OOODvY|fL`NpdgYZP`m|i|a6D7RRGoezZ z|I}lg?yVE0L0z~MJxbwWH|nfbR0ZKftq?oeNzEaMy{PBh9|lS2F z_*-QpbT>ym;UR(C3_-6%8|YlzT(@xJGk^mECn_ehf(9AM(XT6vG*~Tz8U~qBTICi- zC)P~8cdWU8TTi+G`Ol!XRH&@^we+ORRX9C^%)^yUk~-n|Nr*5bbAW$3P=m?RYG9nf z0Q`OA{h50RFqjpAC)ha+)^EgGfy7**NUESC#WFSzP;|=jCoSRQkE@BfU8PpY-bS=H z_H$ORO~ycK9F8hPYd9ivt(Ht~i&)G=M3})AwV9kivnnjjZW+Bu5;xhuKaJt~r1*29 zJcP8^$r$FOPHI47yUc$~f7Xo`%JkK~xv()f%oI0u29>GWz|#o1m#B_lz4!R@gl^oS zr+!R-u4#z7=G3mEkoZG3A76!M0k-1jGLsY)%!z|rCF9K>*5b-~QuVO@$3d@35b+60 zp8ONRmjxb;(rB|xM1J_}9U8J==?)p1MChE#gT-;<>0(v0Cdq#`?R*QfcJ(l~6&baM zsTT55B@yNo84P^4>45HAC%Bg$jco28^e?WDsv@nuJ3-A2w|t+MMvBzTfqZh_v#RS8pTGg#FVn(&ur5-Qv5;PiPBsDE$?$*OD+gTU8bsd>x$6b%@X_6p zhP}080a4SFF*%24e=*fW0hL0u76`{@>N09W%$4O>z*|sh25nR7A&2CUTXiwPkalGQ z2b&Jtj-F0F5?6cu^vBl6mav*02#Y`a$b$QGY4P?a9=BWqUEH(x0%?bgNtpyvC6crG;c6Oiu delta 1273 zcmV;M1%|NsC000000000000bVL+vNa`$il{AQ(bAIB4oT*4?)MB} z6u|PBh4F407m+dI1WgNB$g>v#Lj*%-a{tn?g{sEU4ZtN)+1{RTl(kfjo)f4u+Kt3_ zp#mTvsNjCfJ->t{bHiwMbA~$N%Yu9Jk#B{A1Nq{MZTW~Bi)V!GQ_^PC~HT6&p`%@;J>UE_Kz>}^wlIa`I|DCWW& zCwhXmCub>jaISK*W?=a&y=(cqVc(kTQ&}#-VI!{vg8yk8=2lJNM5l2mJN3qmrv05 zluF`K{~41*4=n`K&wC25G5}sGXREB!WYN-+(+)}IaPIdEU=+aen1%6fe;OB~d=HRH zD^c%i)gyRlrzGMEAT7GJbkYcSGu*YpTy_aWRG>LNWss&28MYNR#6{ zNqs*Or&%i%O8fGL1V7Hzf4{W249d;vW4@#Zzx{1*3C(tDk}8#0ze6#S06ZZgE+0%T z5Sk5&HkAVVXyF(!z#B$Ubzo^xf;O8ZuwG;83DXcu*Yz> zzBCGIZWZZ_OH=Gn-7&nlqPYD(HwyVO-Udt51wM)xD*!7^8+kyhb1V_?4f9r@J+aU4l zISwP$HF!3g3Eo7{5+)P}{Ge3C&~p%fCK|1O^CF1N?-*#LPsZX8A^7+bqeH7jCRR66 zwL?SUNFOjqi?@Uf(NHvz1za5E;`|{z-e|1j~O!o%wZq&kYm#3&u zja*^|tOHa?UW1fe){tQi=mAT#rBYA^a{jjn1rLl-jf&6j`SJ6}^EV`1=VgMwA-{Pq z$l#1U8Suso{$%+#5YmCz+yJYgiyyhSuxPg->U7KI5sGEB_$BrciqtD?ijicG6+uB5 zD3AT-e+Gn=NBxEaBt$2}DAD01sYaxoh7N$dhfVe#r50$XaS+`vGOU=Kpa})9h~;^& jT6T|?R+V#HO2Z%poj*CjvYS&X&0dmR+E$WYu+3K4*fGjQA1F0nd$6zv)Ntc0I~98x5FG*A@B=VH5$ye-kl&G2}i%N2yUq7*h3e>r9v>j~a{- zWvv9`Kv4-C$YvM0%=}#?G$X}27v3&?e!`q`_BP0Sa`Xqx#JYb#{ud0f>AI}EEU@QB znlPWHC4BeP+W^a~qLbXs(%mJz&H)FNk48%ZL?1TWcZyy-fe8bs+-7x^y+JyhS+zTp ze_IH&H(>EK!A|4?u4&u_Sh9Pw(nrfFpCh5jyrIms?zuE-#--)Q0qZEZ52k--U{}zB zbGY?>Q>3fi38)A|!h|pTFCxL``d}4Z+|Q}%fWNjsw33=QgW|B;Qu60Qe*r&sjKaK*m}cXYU)3e-BH?fz zhBEi)SvzU#E05Ds^edDH@`WsfXWWFCMw)(1|E@`Jhyt_k=l2`=CIpis5+vG?zZn1k delta 919 zcmV;I18DrmB*!GMxCkItk<(;^i}0EEjO@w}6_k!LuH<%QD9MYQWp5XLt>p^Ln%%M;tCRzN8 z)A*^kkY^GJoq?er69`TNeIT<=45R{4D`h)nrerYQUCus4ozCm>0$Ee8=lL=CXfkQf z-2hmxIVP;uEV=*ZGI>`!TJsT-XN#%pf{OU;%mwv0NwF}Y*$k8g^;D{_5!43_95IIa z0FebnQ%4H&(b+I7&S1 zP8Z(DwqhPCW0_$NkCH4uS)YC6be16x4;bsqW&sdx;fPo+%Fj{nPJktS^gMmo957D3 zK#=LQ@s5TbW+JzQ39_=sI6U6Gjz@^IgvBqp3}Sh^5vr%L0$6^O(8x)nh%nCijSLq* ze^UjZF#?37Hn*HZS2bn|XEvv9=@BJOa$(=L0Nsf$1B&F*_j}?eXRG@*V6I?XWvddm zN%1g_gk&O5+CSkiWXzA2c|zMj-kQVMc$UyuND2+k&=#O|`9BQKW#UZIt19jiO9jB~ zAi`5nm*W-g^SSML}0$YoC=@bpif5H?JAsNv6o(fF|I_oU-F=|4%sjT5E80Q^g z0%_)#Ipb^2q7iecZ)8O91xRQJrx_@Bh4iYbxyVA{Q`Y`Jk)4VzWWG?^8dedF>2J z!=XeNR4sBd5s(0mU)V7*KK|hd#LB%f$0UCGZ;glk6iU_5e#635C+Z?!L=D62;WN!~ z(dZw*-!YCJ{%7(Bgy0EO%c3R|Z%s`dLq t;1lRMN%Hb^X4$wwUIpi7ecAJ1qZx|{gB~UUEd*q787rjJ)v!NB01Amxo)qk1h@X^<) zEFGRqP=jkG1qllS=_{TH_(siW-P=ZdFx zp71t3XfBwX#(1(7U9j)a3_W>WBIH_OzfvVHIru$Fhf5DMyH8Wb(#lG@{1gM%pQ3az zwY;3hWZ%J8y}a)zSbvNuek4M<3ihrC>CuWm;I`t5!Qs=k;U!?PDoOcFOnYD+?eV%A z`aW`|8?pC`jM8_u^jp*ko(8NfWUjom4@l^_nMNP(t$2od4<~km?iOo~U-+X_&KDVG zh=&~xn$Jp zU9K*8P~ilPSiBV3f{kP0i$W`jN(>XNy^MN~s?{rzCOji^EG?Tf>|bAD38;r=Hlk(M zVy9s<0*CRAd4DK2S79c)=n`3lzcF!;$UK?b)YO%%Gn`2~PZDtT!z_+CLS0^uBKfjC z8HEQY=U&^VMnoqh`wx?XB=1?*A`U^occhJEy^gx#NT?L?mEA`<;s4x_|zt?FEM%E7noF4#m%abmAM5 z0BxMz=>F+UGV4(FTL`H+w1-(7a!Q-jhk$nk&py9um?DI0zh?N0`LIARr{+2krM8=u zg)F1@T!nbG?jp~&aC?fzrhx^tMxkGcf$Cx=up#5|3 zy?k);R)5IHH>Dzd6mxS%=$azk2$cUuSl3^#DGS$|-h8#S$QQA_vYkwMRlMB*k+6QO%1 z_n&~BO}!g>L{)sgrEvs%3Vo!pID-3EifWW3|0?VOaUARiEooa^h#gxF5%m-%kK;ll zRVd9+x$pfOp?E^UtFQ=@{Y9TGP_p)DxvIFNJc4f{f}e^jcW0ve)(^#fZS~*ZPKDFe z$$t=%-mU_-z>WKiv_S%zmY6duHuF6P@+DsZmgkJiEYi_nc}CwE);&2)bKdB(P^jh4 z?d&88`MDfbgl1NkgGCLjKd^By=q3G20}&aJ2Tch5?;__TSp_qo@%qAG7f_bB`<_-X znoY`LZ6VH_yY>!w-B^qU&BuS@0P>MlH|nUPs)p1^3u)n^6AA6> OWmpyg*uMdjwjC_RgPFMi delta 1356 zcmV-S1+)6%JK{UAixD6R3y5gsd}nTbZ_S430zz#Kh4=uw2q}(k;?R}_bK%94s}VpT z2r1v2Zm`hdNDiXqaXoBdGQwF);UQgZDPzN>nLQw1lM50-LFm92qfZT%_1{`wOJIVR z0n(?2i9{}=Vb4Cqz^t-tFajVecp12$A|I48g~4JB{ z81Ac~<_xgrx}hf9(|?wA;uiFO_pgt|2-O1@Coa5&Ko9fB!V8ZEVuo5>TnWa0cFk#l zs9Jmu>qN~e7`OE;RHAk#^T`Q`teWSc9Oz}Y;<)2e5|BIt`8cFb$qESK3Un9p>_GCJ z&CD01O#FS-mb>nm1BGo|k3|ba-Avt=Jy#%~tHt`kdq;NY6o0B5nbr@ZYvX1d!Wftb z*O>qzba(io3u!HRp`>~_G?`!>3o4b-MEW;a_?ufMq<;_$e~M!KG0Lw#>MHDB=iJ`D>l6l=QFpE|M`b3`{Yo?>i*e(cXVpc# z6D5-#fMeN)5W@QhX7|rs{scbVDucqF3PZ``mUwSzGUbU`L3gemlLtbe;(G+FcR?xi z#=(Hl@AgJ16$xqTI4$gbLr@|vPiZUu~4duGBgaQvKyv-Gw? z(<~kDnbr41!PMYtC1T5)c716_}Q4lHb=L zU!N8II)C%8i?bF~(5r?LAng+JoCwiXe^|w;DD3;u&3ZwXD# zB_v%-M^s)CNx@^DQT!Ra?{UGd=fGkOoEcXmTz_7QmLBv^Zt&})RqDDmEuBb(iqL3F z3yms_NYGk2 z3-Jlt_A>mfzUL5&v-5)_%dBTiSYyF_!B^4!|Nr%vw}=A1Yzpq+LD&^$P{QdCbgG!E ztbY<^`al>R7L`^RDX53O;AjZi1}^pR4DKB^3$Fp7r!>dpVgg^hQQMKm{PnUv++7aQ z>vnzdfwK~KPaMBIC(to(l|w}Cacbl*&TqJ1n9MSP_CruC{RG@8Zp^mh>d44CH5O8C zfDUR5--t{6U}Q*f57IT0o9z z+Md>g0lsHmeJFbIOCcJNJ!?F^e`Cv^8LfJm7IO!_zYH4e`R^Q{dK+qaZ#ALwTX?m) z@GdbHd5YJWI1BFK5D3~)trMIe>NcqS2qB=>C89@^OMfi)_3|-;_@x13(-=?XPYGAk O!%QF3n2HCJwjC^6F_``U diff --git a/test_fixtures/masp_proofs/EF7D15FBFB9CC557CC8F9D4D18F7858007C4DA521F8E3BF250A46E9342178EEB.bin b/test_fixtures/masp_proofs/EF7D15FBFB9CC557CC8F9D4D18F7858007C4DA521F8E3BF250A46E9342178EEB.bin index e4c74d543d00eb21d287b880c50454a6ed12b9fc..ee5646add2fef586edea8b836a6b5843838d51f1 100644 GIT binary patch delta 1061 zcmV+=1ls$YESxN`T?-)Aak08o`{Z+(e3>Sm&yv6tHhVzI0xZHU-Q>=3DoGqgs;f)Pw*h{F zkqsgVMYemZ-EL}|S+oBO^a3E%JvxDF-{QVHA#GuccWX;q5ZvkCyr35eimqvlw>O)! z6Axtrf3=)0n{QyS7k`6wW84|o04O#asyiTv zz>_3*e~s~yRpD0ZvqKy`rE+EGSkpTz5*(CLF5Q0znMJj=vW@x?sL%2qqCkA$eirFP z*$eBbHu%5?qKsL(5o*iV+hGTtcKLo;--jw>e-R*Qpv=>|dF$1s&a}8(!>gG5_>5n5 zva$d%SVwE2$c!r{7Fa58D}Y#NuSZ0D#&m%l$`Q5%0~j$Ju)^D97~ zAMc)3l5e0U?;bm{J9@)JA~K)d)H>Ezdz%#T0Ct_Bo8j)JU%fj*9ke9pgnGvrFr>fh zf3EBj}NEVB`{y@WW9&-v>oJ6i3LhwF{ zpK+7Hx7*9!I*KvXL@&^LOz;|t{fiBy2rM(u!<481)nQd=jJ0z}gNq3ZkTf z{^)CO&R*;m=QM9jBmZd+H&(al`oN#j|(@2o|W7VY3Hi1#F+!bkqVE+!0zoq71+Q8yxRz?0u80Q0qc&s!oXe|1s+rab}s{U>xw^72cu-`z}V&ullT=RNFfv7 delta 1061 zcmV+=1ls$YESxN`T?-&XA!(B>$Dl@Z{};Fx%L~z$b}L2j$J*fjfE6xX>}L^^eG5TB z-AMv&%S8Rm0gxWOsae+%3f|#I7D5i!>j9t`)8JFr!= z6Axtrf3(m)v~={nwAtM~H!8xL5&i6elMJ`43UPsy8}+Cts`8r5<+=qzmu%;Z#+4u+b})S9n|^{k)$W`&GMg zU6rcB`5RqGI^f0X29vLy9!8Khwm?4b5saUJr}bV3UHcd`VVgukp~Q1amllpu`UibY zf20Jr(PiTxZ2}@79zK`N3wjifPBynfDiNfN;Wig2d~9VoKcHC%t{j&GieS1=-f{h< zv>*nrMF==3Ezl}e$+0v5Hn{pDuX$KD4Ax;u3~Y1$e(U*njn6=~9@ZjV>Ff1Ob-j)=gEsd77Vsi1^}%hLbjm#tdE9TLLu z9?TPW>|;H%_5V}yKK-_LYiJ}Gi3S!}Zn5Dr(;bl_b3Ria4S(MQiFb zU)_sL@9_}Hh9Xj?-Mg<{2xM+fo-`q%I1bAMr^)fxm>Ajlvn2o);xgYbZcwL&e{b9Z zmxoB;vEy>Z(2xK@4lsfj+ot~wqcP@w7J}xjA~bu(9Taj$^-I!s&Zm-I%C0+0#w@jr zet>}-=4%8WRCM)G`cyN4tQTF(A&tu>5KBip_JJaaQ`9bX-r2rtobNoWt#P(iB70#J zE_bzR^nj#V*m-G8Oz~p&J2$~}e>Lda@lJ|76FI5zB&$pW$j~yhbf5Q_m{JMtPThDJ z4bH2r+)+-i^-|jfIb6ES^iv0qcs`|G2+?smmKwmVP(@S~s^+1hcq0d7K8wVYekW3l zL1I<9mJ8K&7EIR^sL{7O0iYM8RRD7JVav-G#SfytWn0JPmgWf|UX-35f1jF5g3*P{ zk-SPXp!zTqQd;NswPVb(n(vLNyHo77P?)wAl_k@O*@Bi{((iGwBfa f9)bK-eD0S6FV#8UT=Bmc2PIl#s5Qk4llT=R25JLA diff --git a/test_fixtures/masp_proofs/F4F0D829373DDA78336CF39EBA3356453E412F862D949ABE9671C24A3903909E.bin b/test_fixtures/masp_proofs/F4F0D829373DDA78336CF39EBA3356453E412F862D949ABE9671C24A3903909E.bin index 7473a8c1f03c7e9b635176336a99c09025f7d78e..77bf2689797d5f9eb972b0faae98d212fc3ae8b4 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6>Qfr!<^nw&f+n`iI~A2z9{rrrT@b0=J73Bf@=CYcGdyaOcz ze~V%fK;iuJS}3GkG5LM9l$HrrS;mM@WW?GCDz!`d5m4A7*{%#NT|nS`K| za7{2>C%9{U^>Hiwn3vd&qjOeJJxm2*<-}-yd96mnDawB7C5SFi)vW3nKn-OJ4ffY@ zh7LZDufU6q*&L<@lpZ<4+TEX&M}gu`e;84&$;hHio14BdvxNmrZY!gxudzyAP7HCe zyOHuG!m^R?Z~~k+!(>xm1TFg$cK>$dA+Fz_&GvY756!A+Q}w!n2Hm-Lvj5^miL54W z?d~7S(F@~hY;|o#(MuBdIZ@}k=5)tEsWZv|4ai$)iJ0(E-pi4^0&PF-d~QEFC4eQ#?1kRlMY$H}}BTp`Bc_yaOcz ze}F&)Di0{7^NdqIB0Qa+$u5X`kOE112(&0Aiu*97prYo03RayF$3EJ$B^!d zy%1;UYpVt zuyBo)aGNdpvvO#@tz+-8xxERh!6z4Ef1KN7q?qOdafYrle-qhca;$)t-U8mfpwe5x zs|lc<>=1%UuyuMG#taRv1Y?})O0x&^3Wx8HRdtf=f#mgA6q8OY^jdh%h+&StmE}S! z1<>Xc2#|>ovQ4XWDQpzq`R6G=KlQi!WUojN>e+3ycpHdYaOIi$45eZJoQ+W(0wfEQ G;RhTv_m?98 diff --git a/test_fixtures/masp_proofs/F7D91D1E43AA598631284A69E9861C7F98EA4325D94989648024831E350D8F98.bin b/test_fixtures/masp_proofs/F7D91D1E43AA598631284A69E9861C7F98EA4325D94989648024831E350D8F98.bin index 38ecef6e7bb35b24fd680fa427af6c0e3c32e422..1982839e223dece5cdd16786e2b77ff3befc8dc0 100644 GIT binary patch delta 307 zcmV-30nGmW5B(3YoC6@w%3jtMFDQC88hM@1wn(cRGy(958aP1Z;9;hC^T@KZyaOcz zf1#i4djSubhcR{62-%OlN13>ngBvJ+Eybn|;f$;fPZfj2x<2!eb#ZOTR&ywCZI)(~ zvJNPLDH~faSNX8Tb7U8+K9i8;%^gA|$ZDUaU!PZ(zby>f3((n#f)v?Ff0@sj zi}~T&r3c197_K%Hr4AKaBC+KBM5MDmf6Npfh;;xvnYdG(-oPq8P@R~_%h)#3u=hQzSz?jLAJl?Ez)|enb0PB1h za{yZZ3=0JNmOR+kr=|S{v0eOp^Wj$0lOR91w~s19B{@joPW3rre(~S-KR<;40i%=P F2OS-hlcE3s delta 307 zcmV-30nGmW5B(3YoC6?c(L4#`-92hOWiD7CCnbt0ktjZo5O1ILe|#i}vKr8{yaOcz zf0DI!0jFn})*yZhQ~x2~m_H|42$cfX=21msp@bj3$ubnQRY7v(os8bXsQq8SNR(T+ z4t|xfgc0lUhMs!8jWMXT60iDLR`?&&uj+`30nFS{!W8e_ao4tT!eGMx0b{O7MJ=f!#};L~hWqfh zDMH2X2Z32V6n0zb;>QL^d+3)|sEymX-dl7iLy+<@1G&wq;4+o9-a7&ck~sIrYpl0_ zsbs^~+&6{}npadVWdQsbA=p}?9iE+_lqY4PP}^gaaue4HivhqZN32GM>A*mX0b-Nj F2OY3mky!u$ From ae8c439648d23d4a3398d9310e84b2df46305134 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Sun, 4 Feb 2024 20:32:33 +0100 Subject: [PATCH 12/16] Wip --- crates/apps/src/lib/bench_utils.rs | 3 - crates/apps/src/lib/cli/client.rs | 15 +-- crates/apps/src/lib/client/tx.rs | 3 +- crates/sdk/src/masp.rs | 92 ++----------- crates/sdk/src/signing.rs | 6 +- crates/sdk/src/tx.rs | 190 +++++++++++++++++++-------- crates/tests/src/integration/masp.rs | 9 +- 7 files changed, 149 insertions(+), 169 deletions(-) diff --git a/crates/apps/src/lib/bench_utils.rs b/crates/apps/src/lib/bench_utils.rs index 5211e8774d..77ecd1ea32 100644 --- a/crates/apps/src/lib/bench_utils.rs +++ b/crates/apps/src/lib/bench_utils.rs @@ -772,9 +772,6 @@ impl ShieldedUtils for BenchShieldedUtils { .to_path_buf() .join(SPECULATIVE_FILE_NAME), )?; - // // Finally, remove our temporary file to allow future saving of - // // shielded contexts. - // std::fs::remove_file(tmp_path)?; //FIXME: probably not needed Ok(()) } } diff --git a/crates/apps/src/lib/cli/client.rs b/crates/apps/src/lib/cli/client.rs index c99811db01..44ae88064a 100644 --- a/crates/apps/src/lib/cli/client.rs +++ b/crates/apps/src/lib/cli/client.rs @@ -318,13 +318,12 @@ impl CliApi { .await?; } Sub::ShieldedSync(ShieldedSync(args)) => { - eprintln!("IN SHIELDED SYNC"); //FIXME :remove let client = client.unwrap_or_else(|| { C::from_tendermint_address(&args.ledger_address) }); client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let mut chain_ctx = ctx.take_chain_or_exit(); + let chain_ctx = ctx.take_chain_or_exit(); let vks = chain_ctx .wallet .get_viewing_keys() @@ -340,18 +339,6 @@ impl CliApi { .into_iter() .map(|sk| sk.into()) .collect::>(); - // //FIXME: make sure this laod the confirmed one, never the speculative, it does - //FIXME: if I enable this I get a stack overflow!!! - //FIXME: atually I don't get the overflow anymore - // let _ = chain_ctx.shielded.load_confirmed().await; //FIXME: probably unneeeded since we reload it later anyway - //FIXME: remove block - if let ContextSyncStatus::Confirmed = - chain_ctx.shielded.sync_status - { - eprintln!("FOUND OCNFIRMED STATUS"); - } else { - eprintln!("FOUND SPECULATIVE STATUS"); - } crate::client::masp::syncing( chain_ctx.shielded, &client, diff --git a/crates/apps/src/lib/client/tx.rs b/crates/apps/src/lib/client/tx.rs index ffa20f42f9..0c81137c57 100644 --- a/crates/apps/src/lib/client/tx.rs +++ b/crates/apps/src/lib/client/tx.rs @@ -946,9 +946,7 @@ pub async fn submit_transfer( } else { sign(namada, &mut tx, &args.tx, signing_data).await?; - eprintln!("BEFORE SUBMIT"); //FIXME: remove let result = namada.submit(tx, &args.tx).await?; - eprintln!("AFTER SUBMIT"); //FIXME: remove match result { ProcessTxResponse::Applied(resp) if @@ -961,6 +959,7 @@ pub async fn submit_transfer( // And its submission epoch doesn't match construction epoch if tx_epoch.unwrap() != submission_epoch { //FIXME: here if in sepculative context fetch the updated conversion anchor + //FIXME: actually probably not needed, make an e2e test to test this // Then we probably straddled an epoch boundary. Let's retry... edisplay_line!(namada.io(), "MASP transaction rejected and this may be due to the \ diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 23a400ed6b..008ddb6f74 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -684,22 +684,10 @@ impl ShieldedContext { /// unchanged. pub async fn load_confirmed(&mut self) -> std::io::Result<()> { self.utils.clone().load(self).await?; - // self.sync_status = ContextSyncStatus::Confirmed; //FIXME: change this directly inside the function we call here above Ok(()) } - // FIXME: what' the first state that we load when we start this thing? The - // confirmed or the speculative FIXME: copy this logic in the docstring - // of the ContextSync enum FIXME: the logic should be the following: - // - save are fine, I just save whatever state I am in and if it is - // confirmed than I also delete the speculative one if available - // - load, I should try to load the speculative state all the times and - // fallback to the confirmed one? - // - Only in fetching I should always load the confirmed state - // - At startup if I have a speculative file I load that one, otherwise I - // fallback to the confirmed one - //FIXME: probably I query the conversions everytime so the speculative context works anyway /// Save this shielded context into its associated context directory. If the @@ -736,27 +724,9 @@ impl ShieldedContext { Error::Other("note commitment tree is full".to_string()) })?; } - //FIXME: probably need to review validation and update the merkle root for every masp transaction - //FIXME: No wait, I still belive this should work even with the current protocol logic of updating the anchor only once per block - //FIXME: I probably just need to construct the wrapper before the inner, at the moment I'm switching them but than the wrapper is executed first and it carries invalida data (wrong commitment anchor) - //FIXME: also because an unshielding does not update the commitment tree - // if let ContextSyncStatus::Confirmed = self.sync_status { - //FIXME: so in here we effectively update the merkle tree with ALL the notes, not just the ones I can decrypt - - //FIXME: BIG PROBLEM, if I use the speculative context I produce some new output descriptions that I cache for usage. The problem is that I don't have the merkle tree for these new notes and therefore I don't have the anchor and a valid markle path, because to have those I would need to fetch all the notes (even the ones from the other transactions) and reconstruct the merkle tree locally to produce a valid merkle path. SO I would still need to fetch data from the blockchain in the end - //FIXME: what I can do is to just invalidate the spend descriptions I've used so that if I have more than one I can use the others, so in some cases I will still be able to construct a valid transaction, but not always unfortunatly - - //FIXME: regarding the choice to not update the commitment tree anchor with every transaction: - // - for fee unshielding the one above is the only solution, because the inner is executed in the next block, so unless the previous block had only my transaction, I would still need to fetch data (which is impossible), actually is this the case? NO it would actually work, I would just need to refer to the merkle tree of my fee unshielding!! - // - for sequential masp transaction in a same block (no fee unshielding) it's the same thing, if I use the speculative notes than I don't have a valid anchor and merkle path - - //FIXME: to conclude, if I want to use the speculative notes I need to update che ledger to update the anchor with every transaction, because otherwise the notes that I used are still unkown to the ledger in the case of sequential txs and have an invalid anchor in case of fee unshielding. I also need to revert the construciton of the wrapper and the inner, must construct the inner first and wrapper after - - //FIXME: for the conversion tree, at the epoch boundary that changes and if I need to use conversions in my txs those would be invalid, but I could query just the new anchor without querying everything else and still preserve my specyulative context. I could do that if I see that the transactio nfails because of epoch self.tree.append(node).map_err(|()| { Error::Other("note commitment tree is full".to_string()) })?; - // } // Finally, make it easier to construct merkle paths to this new // note let witness = IncrementalWitness::::from_tree(&self.tree); @@ -778,12 +748,9 @@ impl ShieldedContext { fvks: &[ViewingKey], ) -> Result<(), Error> { // add new viewing keys - //FIXME: reload alwyas cause I could have parallel clients! - // if let ContextSyncStatus::Speculative = self.sync_status { // Reload the state from file to get the last confirmed state and // discard any speculative data, we cannot fetch on top of a // speculative state - // eprintln!("IN FETCH, RELOADING CONFIRMED FROM SPECULATIVE"); //FIXME: remove // Always reload the confirmed context or initialize a new one if not found if self.load_confirmed().await.is_err() { // Initialize a default context if we couldn't load a valid one @@ -793,10 +760,6 @@ impl ShieldedContext { ..Default::default() }; } - // } else { - // //FIXME :remove else branch - // eprintln!("IN FETCH, FOUND CONFIRMED STATE"); //FIXME: remove - // } for esk in sks { let vk = to_viewing_key(esk).vk; @@ -849,7 +812,7 @@ impl ShieldedContext { vk, native_token.clone(), )?; - *h = Some(indexed_tx); //FIXME: probably this is the part I'm missing in prefetch + *h = Some(indexed_tx); } // possibly remove unneeded elements from the cache. self.unscanned.scanned(&indexed_tx); @@ -1687,12 +1650,7 @@ impl ShieldedContext { let mut val_acc = I128Sum::zero(); let mut normed_val_acc = I128Sum::zero(); let mut notes = Vec::new(); - eprintln!( - "BEFORE LOOP IN COLLECT UNSPENT. POS MASP: {:#?}", - self.pos_map - ); //FIXME: remove - //FIXME: error here, I never enter the Some branch, am I passing the wrong viewing key? No the pos map is actually empty!!! - // Retrieve the notes that can be spent by this key + // Retrieve the notes that can be spent by this key if let Some(avail_notes) = self.pos_map.get(vk).cloned() { for note_idx in &avail_notes { // No more transaction inputs are required once we have met @@ -1704,7 +1662,6 @@ impl ShieldedContext { if self.spents.contains(note_idx) { continue; } - //FIXME: the masp vp must verify the merkle path somewhere oterwise it's useless, verifying only the merkle root is only half of the check // Get note, merkle path, diversifier associated with this ID let note = *self.note_map.get(note_idx).ok_or_else(|| { Error::Other(format!("Unable to get note {note_idx}")) @@ -1741,7 +1698,6 @@ impl ShieldedContext { normed_val_acc += normed_contr; // Commit the conversions that were used to exchange conversions = proposed_convs; - //FIXME: problem here, I take the merkle path from the witness map but this is invalid if we are in a speculative context let merkle_path = self .witness_map .get(note_idx) @@ -1764,7 +1720,6 @@ impl ShieldedContext { )) })?; // Commit this note to our transaction - eprintln!("FOUND UNSPENT NOTE: {:#?}", note); //FIXME: remove notes.push((*diversifier, note, merkle_path)); } } @@ -2027,10 +1982,7 @@ impl ShieldedContext { { // Load the current shielded context given the spending key we // possess - //FIXME: it's more complicated than this. I could have multiple parallels clients loading and storing contexts in differents status (speculative or confirmed). So what should I do? let mut shielded = context.shielded_mut().await; - eprintln!("BEFORE CONTEXT LOAD IN GEN SHIELDD"); //FIXME: remove - //FIXME: really need to reload here??? let _ = shielded.load().await; } // Determine epoch in which to submit potential shielded transaction @@ -2128,8 +2080,6 @@ impl ShieldedContext { amount }; - //FIXME: does the speculative context work across epochs? IN this case the protocol updates the conversion tree root and therefore I'm not sure the speculative context can still produce valid transactions, verify it - //FIXME: maybe we can just query the updated conversion tree without fetching everything else? // If there are shielded inputs if let Some(sk) = spending_key { // Locate unspent notes that can help us meet the transaction amount @@ -2520,9 +2470,7 @@ impl ShieldedContext { epoch: Epoch, native_token: Address, ) -> Result<(), Error> { - //FIXME: somehting wrong in here, I'm not saving the data correctly because whe ntrying to construct from a speculative context it doesn't work - eprintln!("IN PRECACHE TRANSACTIONS"); //FIXME: remove - // Need to mock the changed balance keys + // Need to mock the changed balance keys let mut changed_balance_keys = BTreeSet::default(); match (source.effective_address(), target.effective_address()) { // Shielded transactions don't write balance keys @@ -2532,7 +2480,6 @@ impl ShieldedContext { changed_balance_keys.insert(balance_key(token, &target)); } } - eprintln!("PRE CACHE CHANGED KEYS: {:#?}", changed_balance_keys); //FIXME: remove let mut vks = Vec::with_capacity(2); if let Some(esk) = esk { @@ -2573,11 +2520,7 @@ impl ShieldedContext { // FIXME: I should try to mock the correct block height? yes |indexed| IndexedTx { height: indexed.height, - index: indexed.index + 1, /* FIXME: this seems to never - * be updated, is it ok? - * Probably because I'm not - * saving the speculative - * context */ + index: indexed.index + 1, }, ); eprintln!("NED INDEXED TX: {:#?}", indexed_tx); //FIXME: remove @@ -2595,12 +2538,9 @@ impl ShieldedContext { *self.vk_heights.get_mut(&vk).unwrap() = Some(indexed_tx); } - //FIXME: I'm probably forgetting to update vk height! self.sync_status = ContextSyncStatus::Speculative; // Save the speculative state for future usage - eprintln!("BEFORE SAVE SPECULATIVE"); //FIXME: remove - self.save().await.map_err(|e| Error::Other(e.to_string()))?; //FIXME: error here - eprintln!("AFTER SAVE SPECULATIVE"); //FIXME: remove + self.save().await.map_err(|e| Error::Other(e.to_string()))?; Ok(()) } @@ -3847,11 +3787,9 @@ pub mod fs { if std::fs::read(context_dir.join(SPECULATIVE_FILE_NAME)) .is_ok() { - eprintln!("FOUND SPECULATIVE FILE"); //FIXME: remove - // Load speculative state + // Load speculative state ContextSyncStatus::Speculative } else { - eprintln!("LOADING CONFIRMED FILE"); //FIXME: remove ContextSyncStatus::Confirmed }; @@ -3893,7 +3831,6 @@ pub mod fs { /// Try to load the last saved shielded context from the given context /// directory. If this fails, then leave the current context unchanged. async fn load( - //FIXME: review the use of this! &self, ctx: &mut ShieldedContext, ) -> std::io::Result<()> { @@ -3936,7 +3873,6 @@ pub mod fs { ctx: &ShieldedContext, ) -> std::io::Result<()> { // TODO: use mktemp crate? - eprintln!("IN INNER SAVE CONFIMRED!"); //FIXME: remove let tmp_path = self.context_dir.join(TMP_FILE_NAME); { // First serialize the shielded context into a temporary file. @@ -3961,15 +3897,9 @@ pub mod fs { // Remove the speculative file if present since it's state is // overruled by the confirmed one we just saved - // let _ = std::fs::remove_file(SPECULATIVE_FILE_NAME); //FIXME: uncomment - //FIXME: remove block - if let Err(e) = std::fs::remove_file( + let _ = std::fs::remove_file( self.context_dir.join(SPECULATIVE_FILE_NAME), - ) { - eprintln!("COULD NOT REMOTE SPECULATVE FILE!: {}", e); - } else { - eprintln!("SUCCEFULY REMOVED SPECULATIVE FILE"); - } + ); Ok(()) } @@ -3983,7 +3913,6 @@ pub mod fs { ctx: &ShieldedContext, ) -> std::io::Result<()> { // TODO: use mktemp crate? - eprintln!("IN INNER SAVE SPECULATIVE!"); //FIXME: remove let tmp_path = self.context_dir.join(SPECULATIVE_TMP_FILE_NAME); { // First serialize the shielded context into a temporary file. @@ -4001,18 +3930,13 @@ pub mod fs { .expect("cannot serialize shielded context"); ctx_file.write_all(&bytes[..])?; } - // FIXME: there's an error here somewhere // Atomically update the old shielded context file with new data. // Atomicity is required to prevent other client instances from // reading corrupt data. - eprintln!("BEFORE RENAME"); //FIXME: remove std::fs::rename( tmp_path, self.context_dir.join(SPECULATIVE_FILE_NAME), )?; - // std::fs::remove_file(tmp_path)?; //FIXME: breaks here, why? I - // renamed the file, why do I even delete it? FIXME: but - // it works for the confirmed file Ok(()) } } diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index a0993f6615..f041acfc77 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -577,7 +577,7 @@ pub async fn validate_fee_and_gen_unshield( )); } - //FIXME: should update the balance to 0 here? + updated_balance.post_balance = Amount::zero(); None } Err(e) => { @@ -586,7 +586,7 @@ pub async fn validate_fee_and_gen_unshield( TxSubmitError::FeeUnshieldingError(e.to_string()), )); } - //FIXME: should update the balance to 0 here? + updated_balance.post_balance = Amount::zero(); None } } @@ -608,7 +608,7 @@ pub async fn validate_fee_and_gen_unshield( )); } - //FIXME: should update the balance to 0 here? + updated_balance.post_balance = Amount::zero(); None } } diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 0f28c00a4a..b54f351db2 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -358,7 +358,6 @@ pub async fn broadcast_tx( } Ok(response) } else { - eprintln!("TX NOT ADDED TO MEMPOOL"); //FIXME: remove Err(Error::from(TxSubmitError::TxBroadcast(RpcError::server( serde_json::to_string(&response).map_err(|err| { Error::from(EncodingError::Serde(err.to_string())) @@ -1810,24 +1809,49 @@ pub async fn build_bond( // balance let bond_source = source.as_ref().unwrap_or(&validator); let native_token = context.native_token(); - let balance_key = balance_key(&native_token, bond_source); - - // TODO Should we state the same error message for the native token? - //FIXME: use the updated balance here if it's the same source and token - let post_balance = check_balance_too_low_err( - &native_token, - bond_source, - *amount, - balance_key, - tx_args.force, - context, - ) - .await?; - let tx_source_balance = Some(TxSourcePostBalance { - post_balance, - source: bond_source.clone(), - token: native_token, - }); + if &updated_balance.source == bond_source + && updated_balance.token == native_token + { + if *amount > updated_balance.post_balance { + if tx_args.force { + edisplay_line!( + context.io(), + "The balance of the source {} of token {} is lower \ + than the amount to be transferred. Amount to \ + transfer is {} and the balance is {}.", + bond_source, + native_token, + context.format_amount(&native_token, *amount).await, + context + .format_amount( + &native_token, + updated_balance.post_balance + ) + .await, + ); + } else { + return Err(Error::from(TxSubmitError::BalanceTooLow( + bond_source.clone(), + native_token, + amount.to_string_native(), + updated_balance.post_balance.to_string_native(), + ))); + } + } + } else { + let balance_key = balance_key(&native_token, bond_source); + + // TODO Should we state the same error message for the native token? + check_balance_too_low_err( + &native_token, + bond_source, + *amount, + balance_key, + tx_args.force, + context, + ) + .await?; + } let data = pos::Bond { validator, @@ -2134,24 +2158,49 @@ pub async fn build_ibc_transfer( ))); } - // Check source balance - let balance_key = balance_key(&args.token, &source); - - //FIXME: use updated balance if fee payer is also source - let post_balance = check_balance_too_low_err( - &args.token, - &source, - validated_amount.amount(), - balance_key, - args.tx.force, - context, - ) - .await?; - let tx_source_balance = Some(TxSourcePostBalance { - post_balance, - source: source.clone(), - token: args.token.clone(), - }); + if updated_balance.source == source && updated_balance.token == args.token { + if validated_amount.amount() > updated_balance.post_balance { + if args.tx.force { + edisplay_line!( + context.io(), + "The balance of the source {} of token {} is lower \ + than the amount to be transferred. Amount to \ + transfer is {} and the balance is {}.", + source, + args.token, + context + .format_amount(&args.token, validated_amount.amount()) + .await, + context + .format_amount( + &args.token, + updated_balance.post_balance + ) + .await, + ); + } else { + return Err(Error::from(TxSubmitError::BalanceTooLow( + source.clone(), + args.token.clone(), + validated_amount.amount().to_string_native(), + updated_balance.post_balance.to_string_native(), + ))); + } + } + } else { + // Check source balance + let balance_key = balance_key(&args.token, &source); + + check_balance_too_low_err( + &args.token, + &source, + validated_amount.amount(), + balance_key, + args.tx.force, + context, + ) + .await?; + } let tx_code_hash = query_wasm_code_hash(context, args.tx_code_path.to_str().unwrap()) @@ -2439,8 +2488,6 @@ pub async fn build_transfer( source_exists_or_err(source.clone(), args.tx.force, context).await?; // Check that the target address exists on chain target_exists_or_err(target.clone(), args.tx.force, context).await?; - // Check source balance - let balance_key = balance_key(&args.token, &source); // validate the amount given let validated_amount = @@ -2448,17 +2495,49 @@ pub async fn build_transfer( .await?; args.amount = InputAmount::Validated(validated_amount); - //FIXME: here use the updated balance if the source matches the fee payer - //FIXME: don't need to return the post_balane naymore - let post_balance = check_balance_too_low_err( - &args.token, - &source, - validated_amount.amount(), - balance_key, - args.tx.force, - context, - ) - .await?; + + // Check source balance + if updated_balance.source == source && updated_balance.token == args.token { + if validated_amount.amount() > updated_balance.post_balance { + if args.tx.force { + edisplay_line!( + context.io(), + "The balance of the source {} of token {} is lower \ + than the amount to be transferred. Amount to \ + transfer is {} and the balance is {}.", + source, + args.token, + context + .format_amount(&args.token, validated_amount.amount()) + .await, + context + .format_amount( + &args.token, + updated_balance.post_balance + ) + .await, + ); + } else { + return Err(Error::from(TxSubmitError::BalanceTooLow( + source.clone(), + args.token.clone(), + validated_amount.amount().to_string_native(), + updated_balance.post_balance.to_string_native(), + ))); + } + } + } else { + let balance_key = balance_key(&args.token, &source); + check_balance_too_low_err( + &args.token, + &source, + validated_amount.amount(), + balance_key, + args.tx.force, + context, + ) + .await?; + } let masp_addr = MASP; @@ -2567,7 +2646,6 @@ async fn construct_shielded_parts( Ok(Some(stx)) => stx, Ok(None) => return Ok(None), Err(Build(builder::Error::InsufficientFunds(_))) => { - //FIXME: I'm failing here return Err(TxSubmitError::NegativeBalanceAfterTransfer( Box::new(source.effective_address()), amount.amount().to_string_native(), @@ -3029,7 +3107,7 @@ async fn target_exists_or_err( /// Checks the balance at the given address is enough to transfer the /// given amount, along with the balance even existing. Force -/// overrides this. Returns the updated balance for fee check if necessary +/// overrides this. async fn check_balance_too_low_err( token: &Address, source: &Address, @@ -3037,7 +3115,7 @@ async fn check_balance_too_low_err( balance_key: storage::Key, force: bool, context: &N, -) -> Result { +) -> Result<()> { match rpc::query_storage_value::( context.client(), &balance_key, @@ -3045,7 +3123,7 @@ async fn check_balance_too_low_err( .await { Ok(balance) => match balance.checked_sub(amount) { - Some(diff) => Ok(diff), + Some(_) => Ok(()), None => { if force { edisplay_line!( @@ -3058,7 +3136,7 @@ async fn check_balance_too_low_err( context.format_amount(token, amount).await, context.format_amount(token, balance).await, ); - Ok(token::Amount::zero()) + Ok(()) } else { Err(Error::from(TxSubmitError::BalanceTooLow( source.clone(), @@ -3079,7 +3157,7 @@ async fn check_balance_too_low_err( source, token ); - Ok(token::Amount::zero()) + Ok(()) } else { Err(Error::from(TxSubmitError::NoBalanceForToken( source.clone(), diff --git a/crates/tests/src/integration/masp.rs b/crates/tests/src/integration/masp.rs index 313a183ff4..e1b5e66a83 100644 --- a/crates/tests/src/integration/masp.rs +++ b/crates/tests/src/integration/masp.rs @@ -1452,7 +1452,6 @@ fn masp_txs_and_queries() -> Result<()> { /// shielded transfer with the same source /// 4. Submit a new wrapper with an invalid unshielding tx and assert the /// failure -//FIXME: do a separate test without the syncs #[test] fn wrapper_fee_unshielding() -> Result<()> { // This address doesn't matter for tests. But an argument is required. @@ -1471,7 +1470,6 @@ fn wrapper_fee_unshielding() -> Result<()> { "--source", ALBERT_KEY, "--target", - //FIXME: I believe this is not known to the context yet so it doesn't get fetched. But it could be knwn if I take it from somewhere else? Meybe from wallet? AA_PAYMENT_ADDRESS, "--token", NAM, @@ -1494,7 +1492,6 @@ fn wrapper_fee_unshielding() -> Result<()> { "shielded-sync", "--viewing-keys", AA_VIEWING_KEY, - // AB_VIEWING_KEY, //FIXME: remove if not needed "--node", validator_one_rpc, ], @@ -1535,8 +1532,6 @@ fn wrapper_fee_unshielding() -> Result<()> { assert!(captured.result.is_ok()); assert!(captured.contains("nam: 1979999")); - //FIXME: seems like the speculative context is not working, if I don't fetch this doesn't pass - //FIXME: ah it's because the viewing key is unknown _ = node.next_epoch(); // 2. Valid unshielding run( @@ -1608,7 +1603,6 @@ fn wrapper_fee_unshielding() -> Result<()> { // 3. Try another valid fee unshielding and masp transaction in the same tx, // with the same source. This tests that the client can properly fetch data // and construct these kind of transactions - //FIXME: I break here, it succesfuly executes the wrapper but I've got a broadcast error before the inner gets executed run( &node, Bin::Client, @@ -1654,7 +1648,6 @@ fn wrapper_fee_unshielding() -> Result<()> { assert!(captured.contains("nam: 1939998")); // 4. Invalid unshielding - eprintln!("BEFORE THE LAST ONE"); //FIXME: remove let tx_args = vec![ "transfer", "--source", @@ -1689,6 +1682,8 @@ fn wrapper_fee_unshielding() -> Result<()> { } //FIXME: add a test that checks that two transactions generated from sequential notes can be applied in the same block +//FIXME: do a separate test without the syncs +//FIXME: test for seculative context over epoch boundary (check that the tx still passes and I don't need to manulaly requery the conversions) // Test that a masp unshield transaction can be succesfully executed even across // an epoch boundary. From 72c427108e05e26dc4c80b68c4814389e881a519 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Sun, 4 Feb 2024 22:06:43 +0100 Subject: [PATCH 13/16] Wip --- crates/sdk/src/masp.rs | 50 +++++++++++------------------------- crates/sdk/src/wallet/mod.rs | 2 +- 2 files changed, 16 insertions(+), 36 deletions(-) diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 008ddb6f74..32543a491b 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -1075,7 +1075,7 @@ impl ShieldedContext { .sapling_bundle() .map_or(&vec![], |x| &x.shielded_outputs) { - // Let's try to see if any of our viewing keys can decrypt latest + // Let's try to see if this viewing key can decrypt latest // note let notes = self.pos_map.entry(*vk).or_default(); let decres = try_sapling_note_decryption::<_, OutputDescription<<::SaplingAuth as masp_primitives::transaction::components::sapling::Authorization>::Proof>>( @@ -2381,18 +2381,15 @@ impl ShieldedContext { .map_err(|_e| Error::Other(exp_str))?; // Cache the generated transfer - let native_token = query_native_token(context.client()).await?; let mut shielded_ctx = context.shielded_mut().await; shielded_ctx .pre_cache_transaction( - spending_key, - payment_address, + context, &loaded.masp_tx, source, target, token, epoch, - native_token, ) .await?; @@ -2412,18 +2409,15 @@ impl ShieldedContext { } // Cache the generated transfer - let native_token = query_native_token(context.client()).await?; let mut shielded_ctx = context.shielded_mut().await; shielded_ctx .pre_cache_transaction( - spending_key, - payment_address, + context, &built.masp_tx, source, target, token, epoch, - native_token, ) .await?; @@ -2438,18 +2432,15 @@ impl ShieldedContext { context.shielded().await.utils.local_tx_prover(), )?; - let native_token = query_native_token(context.client()).await?; let mut shielded_ctx = context.shielded_mut().await; shielded_ctx .pre_cache_transaction( - spending_key, - payment_address, + context, &built.masp_tx, source, target, token, epoch, - native_token, ) .await?; @@ -2461,14 +2452,12 @@ impl ShieldedContext { // transaction async fn pre_cache_transaction( &mut self, - esk: Option, - payment_address: Option, + context: &impl Namada, masp_tx: &Transaction, source: &TransferSource, target: &TransferTarget, token: &Address, epoch: Epoch, - native_token: Address, ) -> Result<(), Error> { // Need to mock the changed balance keys let mut changed_balance_keys = BTreeSet::default(); @@ -2482,28 +2471,20 @@ impl ShieldedContext { } let mut vks = Vec::with_capacity(2); - if let Some(esk) = esk { - vks.push(to_viewing_key(&esk).vk); - } - //FIXME: don't do it like that, get the viewing key from the wallet which is inside the Namada contexts in gen_shielded_transfer! - // FIXME: clane up this, use find on iterators - if let Some(pa) = payment_address { - // Try to look for the viewing key associated to this payent address - // in the shielded context - 'outer: for (vk, positions) in &self.pos_map { - for pos in positions { - if let Some(div) = self.div_map.get(pos) { - if let Some(ref p) = vk.to_payment_address(*div) { - if p == &masp_primitives::sapling::PaymentAddress::from(pa) { - vks.push(*vk); - break 'outer; - } - } - } + if let Some(esk) = source.spending_key() { + vks.push(to_viewing_key(&esk.into()).vk); + } + + if let Some(pa) = target.payment_address() { + let wallet = context.wallet().await; + if let Some(alias) = wallet.find_alias_by_payment_addr(&pa) { + if let Ok(vk) = wallet.find_viewing_key(alias) { + vks.push(vk.clone().into()); } } } + let native_token = query_native_token(context.client()).await?; //FIXME: I never enter this loop!!! eprintln!("ABOUT OT ITERATE ON VKS"); //FIXME: remove for vk in vks { @@ -2517,7 +2498,6 @@ impl ShieldedContext { height: BlockHeight::first(), index: TxIndex(0), }, - // FIXME: I should try to mock the correct block height? yes |indexed| IndexedTx { height: indexed.height, index: indexed.index + 1, diff --git a/crates/sdk/src/wallet/mod.rs b/crates/sdk/src/wallet/mod.rs index 5fae3db2ad..dc2fd5aafd 100644 --- a/crates/sdk/src/wallet/mod.rs +++ b/crates/sdk/src/wallet/mod.rs @@ -381,7 +381,7 @@ impl Wallet { /// Find the viewing key with the given alias in the wallet and return it pub fn find_viewing_key( - &mut self, + &self, alias: impl AsRef, ) -> Result<&ExtendedViewingKey, FindKeyError> { self.store.find_viewing_key(alias.as_ref()).ok_or_else(|| { From d196737c37ae701e99a82f78b86197ba24617c12 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Mon, 5 Feb 2024 23:40:34 +0100 Subject: [PATCH 14/16] Final wip --- crates/apps/src/lib/bench_utils.rs | 2 +- crates/apps/src/lib/cli/client.rs | 1 - crates/apps/src/lib/client/tx.rs | 6 +- crates/sdk/src/eth_bridge/bridge_pool.rs | 2 +- crates/sdk/src/masp.rs | 96 ++++++++++-------------- crates/sdk/src/signing.rs | 6 +- crates/sdk/src/tx.rs | 85 ++++++++++----------- 7 files changed, 87 insertions(+), 111 deletions(-) diff --git a/crates/apps/src/lib/bench_utils.rs b/crates/apps/src/lib/bench_utils.rs index 77ecd1ea32..bcb4aac198 100644 --- a/crates/apps/src/lib/bench_utils.rs +++ b/crates/apps/src/lib/bench_utils.rs @@ -765,7 +765,7 @@ impl ShieldedUtils for BenchShieldedUtils { // Atomicity is required to prevent other client instances from // reading corrupt data. std::fs::rename( - tmp_path.clone(), + tmp_path, self.context_dir .0 .path() diff --git a/crates/apps/src/lib/cli/client.rs b/crates/apps/src/lib/cli/client.rs index 44ae88064a..969e85f2d3 100644 --- a/crates/apps/src/lib/cli/client.rs +++ b/crates/apps/src/lib/cli/client.rs @@ -1,7 +1,6 @@ use color_eyre::eyre::Result; use masp_primitives::zip32::ExtendedFullViewingKey; use namada::types::io::Io; -use namada_sdk::masp::ContextSyncStatus; use namada_sdk::{Namada, NamadaImpl}; use crate::cli; diff --git a/crates/apps/src/lib/client/tx.rs b/crates/apps/src/lib/client/tx.rs index 0c81137c57..c7edf4adba 100644 --- a/crates/apps/src/lib/client/tx.rs +++ b/crates/apps/src/lib/client/tx.rs @@ -423,7 +423,7 @@ pub async fn submit_change_consensus_key( .await?; tx::prepare_tx( - namada, + namada.client(), &tx_args, &mut tx, unshield, @@ -758,7 +758,7 @@ pub async fn submit_become_validator( .await?; tx::prepare_tx( - namada, + namada.client(), &tx_args, &mut tx, unshield, @@ -958,8 +958,6 @@ pub async fn submit_transfer( let submission_epoch = rpc::query_and_print_epoch(namada).await; // And its submission epoch doesn't match construction epoch if tx_epoch.unwrap() != submission_epoch { - //FIXME: here if in sepculative context fetch the updated conversion anchor - //FIXME: actually probably not needed, make an e2e test to test this // Then we probably straddled an epoch boundary. Let's retry... edisplay_line!(namada.io(), "MASP transaction rejected and this may be due to the \ diff --git a/crates/sdk/src/eth_bridge/bridge_pool.rs b/crates/sdk/src/eth_bridge/bridge_pool.rs index baa8ea05a9..c8aeb0bb92 100644 --- a/crates/sdk/src/eth_bridge/bridge_pool.rs +++ b/crates/sdk/src/eth_bridge/bridge_pool.rs @@ -110,7 +110,7 @@ pub async fn build_bridge_pool_tx( .add_data(transfer); prepare_tx( - context, + context.client(), &tx_args, &mut tx, unshield, diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 32543a491b..4c895fe5f3 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -668,12 +668,8 @@ impl ShieldedContext { /// directory. If this fails, then leave the current context unchanged. pub async fn load(&mut self) -> std::io::Result<()> { match self.sync_status { - ContextSyncStatus::Confirmed => { - eprintln!("LOADIGN CONFIRMED CONTEXT"); //FIXME: remove - self.utils.clone().load(self).await - } + ContextSyncStatus::Confirmed => self.utils.clone().load(self).await, ContextSyncStatus::Speculative => { - eprintln!("LOADING SPECULATIVE CONTEXT"); //FIXME: remove self.utils.clone().load_speculative(self).await } } @@ -688,8 +684,6 @@ impl ShieldedContext { Ok(()) } - //FIXME: probably I query the conversions everytime so the speculative context works anyway - /// Save this shielded context into its associated context directory. If the /// state to be saved is confirmed than also delete the speculative one (if /// available) @@ -751,7 +745,8 @@ impl ShieldedContext { // Reload the state from file to get the last confirmed state and // discard any speculative data, we cannot fetch on top of a // speculative state - // Always reload the confirmed context or initialize a new one if not found + // Always reload the confirmed context or initialize a new one if not + // found if self.load_confirmed().await.is_err() { // Initialize a default context if we couldn't load a valid one // from storage @@ -2301,27 +2296,28 @@ impl ShieldedContext { // To speed up integration tests, we can save and load proofs #[cfg(feature = "testing")] - let load_or_save = - if let Ok(masp_proofs) = env::var(ENV_VAR_MASP_TEST_PROOFS) { - let parsed = match masp_proofs.to_ascii_lowercase().as_str() { - "load" => LoadOrSaveProofs::Load, - "save" => LoadOrSaveProofs::Save, - env_var => Err(Error::Other(format!( + let load_or_save = if let Ok(masp_proofs) = + env::var(ENV_VAR_MASP_TEST_PROOFS) + { + let parsed = match masp_proofs.to_ascii_lowercase().as_str() { + "load" => LoadOrSaveProofs::Load, + "save" => LoadOrSaveProofs::Save, + env_var => Err(Error::Other(format!( "Unexpected value for {ENV_VAR_MASP_TEST_PROOFS} env var. \ Expecting \"save\" or \"load\", but got \"{env_var}\"." )))?, - }; - if env::var(ENV_VAR_MASP_TEST_SEED).is_err() { - Err(Error::Other(format!( + }; + if env::var(ENV_VAR_MASP_TEST_SEED).is_err() { + Err(Error::Other(format!( "Ensure to set a seed with {ENV_VAR_MASP_TEST_SEED} env \ var when using {ENV_VAR_MASP_TEST_PROOFS} for \ deterministic proofs." )))?; - } - parsed - } else { - LoadOrSaveProofs::Neither - }; + } + parsed + } else { + LoadOrSaveProofs::Neither + }; let builder_clone = builder.clone().map_builder(WalletMap); #[cfg(feature = "testing")] @@ -2470,42 +2466,30 @@ impl ShieldedContext { } } - let mut vks = Vec::with_capacity(2); - if let Some(esk) = source.spending_key() { - vks.push(to_viewing_key(&esk.into()).vk); - } - - if let Some(pa) = target.payment_address() { - let wallet = context.wallet().await; - if let Some(alias) = wallet.find_alias_by_payment_addr(&pa) { - if let Ok(vk) = wallet.find_viewing_key(alias) { - vks.push(vk.clone().into()); - } - } - } - let native_token = query_native_token(context.client()).await?; - //FIXME: I never enter this loop!!! - eprintln!("ABOUT OT ITERATE ON VKS"); //FIXME: remove + let vks: Vec<_> = context + .wallet() + .await + .get_viewing_keys() + .values() + .map(|evk| ExtendedFullViewingKey::from(*evk).fvk.vk) + .collect(); + let last_witnessed_tx = self.tx_note_map.keys().max(); + // This data will be discarded at the next fetch so we don't need to + // populate it accurately + let indexed_tx = last_witnessed_tx.map_or_else( + || IndexedTx { + height: BlockHeight::first(), + index: TxIndex(0), + }, + |indexed| IndexedTx { + height: indexed.height, + index: indexed.index + 1, + }, + ); + self.update_witness_map(indexed_tx, masp_tx)?; for vk in vks { - eprintln!("IN ITERATE VKS: {:#?}", vk); //FIXME: RMEOVE - //FIXME: can share this code with fetch? self.vk_heights.entry(vk).or_default(); - // This data will be discarded at the next fetch so we don't need to - // populate it accurately - let indexed_tx = self.vk_heights.get(&vk).unwrap().map_or_else( - || IndexedTx { - height: BlockHeight::first(), - index: TxIndex(0), - }, - |indexed| IndexedTx { - height: indexed.height, - index: indexed.index + 1, - }, - ); - eprintln!("NED INDEXED TX: {:#?}", indexed_tx); //FIXME: remove - - self.update_witness_map(indexed_tx, masp_tx)?; self.scan_tx( indexed_tx, @@ -3847,7 +3831,7 @@ pub mod fs { } /// Save this confirmed shielded context into its associated context - /// directory. At the same time, delete the speculative file if present + /// directory. At the same time, delete the speculative file if present async fn save( &self, ctx: &ShieldedContext, diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index f041acfc77..7bc127c68d 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -415,7 +415,8 @@ pub struct TxSourcePostBalance { pub token: Address, } -/// Validate the fee of the transaction and generate the fee unshielding transaction if needed +/// Validate the fee of the transaction and generate the fee unshielding +/// transaction if needed pub async fn validate_fee_and_gen_unshield( context: &N, args: &args::Tx, @@ -632,8 +633,7 @@ pub async fn validate_fee_and_gen_unshield( /// wrapper and its payload which is needed for monitoring its /// progress on chain. #[allow(clippy::too_many_arguments)] -pub async fn wrap_tx( - context: &N, +pub async fn wrap_tx( tx: &mut Tx, args: &args::Tx, epoch: Epoch, diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index b54f351db2..a95aa5cc75 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -63,9 +63,7 @@ use crate::rpc::{ self, query_wasm_code_hash, validate_amount, InnerTxResult, TxBroadcastData, TxResponse, }; -use crate::signing::{ - self, validate_fee_and_gen_unshield, SigningTxData, TxSourcePostBalance, -}; +use crate::signing::{self, validate_fee_and_gen_unshield, SigningTxData}; use crate::tendermint_rpc::endpoint::broadcast::tx_sync::Response; use crate::tendermint_rpc::error::Error as RpcError; use crate::wallet::WalletIo; @@ -184,8 +182,8 @@ pub fn dump_tx(io: &IO, args: &args::Tx, tx: Tx) { /// Prepare a transaction for signing and submission by adding a wrapper header /// to it. #[allow(clippy::too_many_arguments)] -pub async fn prepare_tx( - context: &impl Namada, +pub async fn prepare_tx( + client: &C, args: &args::Tx, tx: &mut Tx, unshield: Option, @@ -193,12 +191,9 @@ pub async fn prepare_tx( fee_payer: common::PublicKey, ) -> Result<()> { if !args.dry_run { - let epoch = rpc::query_epoch(context.client()).await?; + let epoch = rpc::query_epoch(client).await?; - signing::wrap_tx( - context, tx, args, epoch, unshield, fee_amount, fee_payer, - ) - .await + signing::wrap_tx(tx, args, epoch, unshield, fee_amount, fee_payer).await } else { Ok(()) } @@ -293,7 +288,7 @@ pub async fn build_reveal_pk( signing::aux_signing_data(context, args, None, Some(public_key.into())) .await?; let (fee_amount, _, unshield) = - validate_fee_and_gen_unshield(context, &args, &signing_data.fee_payer) + validate_fee_and_gen_unshield(context, args, &signing_data.fee_payer) .await?; build( @@ -587,7 +582,7 @@ pub async fn build_validator_commission_change( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -713,7 +708,7 @@ pub async fn build_validator_metadata_change( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -848,7 +843,7 @@ pub async fn build_update_steward_commission( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -915,7 +910,7 @@ pub async fn build_resign_steward( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -964,7 +959,7 @@ pub async fn build_unjail_validator( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -1073,7 +1068,7 @@ pub async fn build_deactivate_validator( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -1151,7 +1146,7 @@ pub async fn build_reactivate_validator( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -1374,7 +1369,7 @@ pub async fn build_redelegation( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -1421,7 +1416,7 @@ pub async fn build_withdraw( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -1511,7 +1506,7 @@ pub async fn build_claim_rewards( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -1592,7 +1587,7 @@ pub async fn build_unbond( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -1800,7 +1795,7 @@ pub async fn build_bond( let (fee_amount, updated_balance, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -1816,9 +1811,9 @@ pub async fn build_bond( if tx_args.force { edisplay_line!( context.io(), - "The balance of the source {} of token {} is lower \ - than the amount to be transferred. Amount to \ - transfer is {} and the balance is {}.", + "The balance of the source {} of token {} is lower than \ + the amount to be transferred. Amount to transfer is {} \ + and the balance is {}.", bond_source, native_token, context.format_amount(&native_token, *amount).await, @@ -1894,8 +1889,8 @@ pub async fn build_default_proposal( default_signer, ) .await?; - let (fee_amount, updated_balance, unshield) = - validate_fee_and_gen_unshield(context, &tx, &signing_data.fee_payer) + let (fee_amount, _updated_balance, unshield) = + validate_fee_and_gen_unshield(context, tx, &signing_data.fee_payer) .await?; let init_proposal_data = InitProposalData::try_from(proposal.clone()) @@ -1953,7 +1948,7 @@ pub async fn build_vote_proposal( ) .await?; let (fee_amount, _, unshield) = - validate_fee_and_gen_unshield(context, &tx, &signing_data.fee_payer) + validate_fee_and_gen_unshield(context, tx, &signing_data.fee_payer) .await?; let proposal_vote = ProposalVote::try_from(vote.clone()) @@ -2042,8 +2037,8 @@ pub async fn build_pgf_funding_proposal( default_signer, ) .await?; - let (fee_amount, updated_balance, unshield) = - validate_fee_and_gen_unshield(context, &tx, &signing_data.fee_payer) + let (fee_amount, _updated_balance, unshield) = + validate_fee_and_gen_unshield(context, tx, &signing_data.fee_payer) .await?; // TODO: need to pay the fee to submit a proposal, check enough balance @@ -2091,8 +2086,8 @@ pub async fn build_pgf_stewards_proposal( default_signer, ) .await?; - let (fee_amount, updated_balance, unshield) = - validate_fee_and_gen_unshield(context, &tx, &signing_data.fee_payer) + let (fee_amount, _updated_balance, unshield) = + validate_fee_and_gen_unshield(context, tx, &signing_data.fee_payer) .await?; // TODO: need to pay the fee to submit a proposal, check enough balance @@ -2163,9 +2158,9 @@ pub async fn build_ibc_transfer( if args.tx.force { edisplay_line!( context.io(), - "The balance of the source {} of token {} is lower \ - than the amount to be transferred. Amount to \ - transfer is {} and the balance is {}.", + "The balance of the source {} of token {} is lower than \ + the amount to be transferred. Amount to transfer is {} \ + and the balance is {}.", source, args.token, context @@ -2323,7 +2318,7 @@ pub async fn build_ibc_transfer( .add_serialized_data(data); prepare_tx( - context, + context.client(), &args.tx, &mut tx, unshield, @@ -2393,7 +2388,7 @@ where .add_data(data); prepare_tx( - context, + context.client(), tx_args, &mut tx_builder, unshield, @@ -2502,9 +2497,9 @@ pub async fn build_transfer( if args.tx.force { edisplay_line!( context.io(), - "The balance of the source {} of token {} is lower \ - than the amount to be transferred. Amount to \ - transfer is {} and the balance is {}.", + "The balance of the source {} of token {} is lower than \ + the amount to be transferred. Amount to transfer is {} \ + and the balance is {}.", source, args.token, context @@ -2682,7 +2677,7 @@ pub async fn build_init_account( signing::aux_signing_data(context, tx_args, None, None).await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -2753,7 +2748,7 @@ pub async fn build_update_account( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -2846,7 +2841,7 @@ pub async fn build_custom( .await?; let (fee_amount, _, unshield) = validate_fee_and_gen_unshield( context, - &tx_args, + tx_args, &signing_data.fee_payer, ) .await?; @@ -2874,7 +2869,7 @@ pub async fn build_custom( }; prepare_tx( - context, + context.client(), tx_args, &mut tx, unshield, From cb5a3f3b8ec6d53238a638f999231562dc7dc2e5 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 6 Feb 2024 00:43:27 +0100 Subject: [PATCH 15/16] Adds new integration tests --- .../src/lib/node/ledger/shell/testing/node.rs | 23 +- crates/tests/src/integration/masp.rs | 344 +++++++++++++++++- 2 files changed, 360 insertions(+), 7 deletions(-) diff --git a/crates/apps/src/lib/node/ledger/shell/testing/node.rs b/crates/apps/src/lib/node/ledger/shell/testing/node.rs index a3ab32dcb6..ceb4fe1637 100644 --- a/crates/apps/src/lib/node/ledger/shell/testing/node.rs +++ b/crates/apps/src/lib/node/ledger/shell/testing/node.rs @@ -438,7 +438,26 @@ impl MockNode { votes, }; - locked.finalize_block(req).expect("Test failed"); + let resp = locked.finalize_block(req).expect("Test failed"); + let mut error_codes = resp + .events + .into_iter() + .map(|e| { + let code = ResultCode::from_u32( + e.attributes + .get("code") + .map(|e| u32::from_str(e).unwrap()) + .unwrap_or_default(), + ) + .unwrap(); + if code == ResultCode::Ok { + NodeResults::Ok + } else { + NodeResults::Failed(code) + } + }) + .collect::>(); + self.results.lock().unwrap().append(&mut error_codes); locked.commit(); // Cache the block @@ -501,7 +520,7 @@ impl MockNode { /// Send a tx through Process Proposal and Finalize Block /// and register the results. - fn submit_txs(&self, txs: Vec>) { + pub fn submit_txs(&self, txs: Vec>) { // The block space allocator disallows encrypted txs in certain blocks. // Advance to block height that allows txs. self.advance_to_allowed_block(); diff --git a/crates/tests/src/integration/masp.rs b/crates/tests/src/integration/masp.rs index e1b5e66a83..26949373c2 100644 --- a/crates/tests/src/integration/masp.rs +++ b/crates/tests/src/integration/masp.rs @@ -4,9 +4,11 @@ use std::str::FromStr; use color_eyre::eyre::Result; use color_eyre::owo_colors::OwoColorize; use namada::state::StorageWrite; -use namada::token; +use namada::token::{self, DenominatedAmount}; use namada_apps::node::ledger::shell::testing::client::run; +use namada_apps::node::ledger::shell::testing::node::NodeResults; use namada_apps::node::ledger::shell::testing::utils::{Bin, CapturedOutput}; +use namada_apps::wallet::defaults::christel_keypair; use namada_core::types::dec::Dec; use namada_sdk::masp::fs::FsShieldedUtils; use test_log::test; @@ -1461,6 +1463,35 @@ fn wrapper_fee_unshielding() -> Result<()> { let (mut node, _services) = setup::setup()?; _ = node.next_epoch(); + // Add the relevant viewing keys to the wallet otherwise the shielded + // context won't precache the masp data + run( + &node, + Bin::Wallet, + vec![ + "add", + "--alias", + "alias_a", + "--value", + AA_VIEWING_KEY, + "--unsafe-dont-encrypt", + ], + )?; + node.assert_success(); + run( + &node, + Bin::Wallet, + vec![ + "add", + "--alias", + "alias_b", + "--value", + AB_VIEWING_KEY, + "--unsafe-dont-encrypt", + ], + )?; + node.assert_success(); + // 1. Shield some tokens run( &node, @@ -1681,14 +1712,317 @@ fn wrapper_fee_unshielding() -> Result<()> { Ok(()) } -//FIXME: add a test that checks that two transactions generated from sequential notes can be applied in the same block -//FIXME: do a separate test without the syncs -//FIXME: test for seculative context over epoch boundary (check that the tx still passes and I don't need to manulaly requery the conversions) +/// Tests that multiple chained transactions can be constructed from the +/// shielded context and executed in the same block +#[test] +fn chained_txs_same_block() -> Result<()> { + // This address doesn't matter for tests. But an argument is required. + let validator_one_rpc = "127.0.0.1:26567"; + // Download the shielded pool parameters before starting node + let _ = FsShieldedUtils::new(PathBuf::new()); + let (mut node, _services) = setup::setup()?; + _ = node.next_epoch(); + + // Add the relevant viewing keys to the wallet otherwise the shielded + // context won't precache the masp data + run( + &node, + Bin::Wallet, + vec![ + "add", + "--alias", + "alias_a", + "--value", + AA_VIEWING_KEY, + "--unsafe-dont-encrypt", + ], + )?; + node.assert_success(); + run( + &node, + Bin::Wallet, + vec![ + "add", + "--alias", + "alias_b", + "--value", + AB_VIEWING_KEY, + "--unsafe-dont-encrypt", + ], + )?; + node.assert_success(); + + // 1. Shield tokens + _ = node.next_epoch(); + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + ALBERT_KEY, + "--target", + AA_PAYMENT_ADDRESS, + "--token", + NAM, + "--amount", + "100", + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + + // 2. Shielded consecutive operations without fetching. The second and third + // operations are constructed by the speculative context based on the notes + // produces by the previous one. Dump the txs to than reload and submit in + // the same block + let tempdir = tempfile::tempdir().unwrap(); + let mut txs_bytes = vec![]; + + _ = node.next_epoch(); + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + A_SPENDING_KEY, + "--target", + AB_PAYMENT_ADDRESS, + "--token", + NAM, + "--amount", + "50", + "--gas-payer", + ALBERT_KEY, + "--output-folder-path", + tempdir.path().to_str().unwrap(), + "--dump-tx", + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + let file_path = tempdir + .path() + .read_dir() + .unwrap() + .next() + .unwrap() + .unwrap() + .path(); + txs_bytes.push(std::fs::read(&file_path).unwrap()); + std::fs::remove_file(&file_path).unwrap(); + + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + A_SPENDING_KEY, + "--target", + AC_PAYMENT_ADDRESS, + "--token", + NAM, + "--amount", + "50", + "--gas-payer", + CHRISTEL_KEY, + "--output-folder-path", + tempdir.path().to_str().unwrap(), + "--dump-tx", + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + let file_path = tempdir + .path() + .read_dir() + .unwrap() + .next() + .unwrap() + .unwrap() + .path(); + txs_bytes.push(std::fs::read(&file_path).unwrap()); + std::fs::remove_file(&file_path).unwrap(); + + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + B_SPENDING_KEY, + "--target", + AC_PAYMENT_ADDRESS, + "--token", + NAM, + "--amount", + "50", + "--gas-payer", + CHRISTEL_KEY, + "--output-folder-path", + tempdir.path().to_str().unwrap(), + "--dump-tx", + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + let file_path = tempdir + .path() + .read_dir() + .unwrap() + .next() + .unwrap() + .unwrap() + .path(); + txs_bytes.push(std::fs::read(&file_path).unwrap()); + std::fs::remove_file(&file_path).unwrap(); + + let sk = christel_keypair(); + let pk = sk.to_public(); + + let native_token = node + .shell + .lock() + .unwrap() + .wl_storage + .storage + .native_token + .clone(); + let mut txs = vec![]; + for bytes in txs_bytes { + let mut tx = namada::tx::Tx::deserialize(&bytes).unwrap(); + tx.add_wrapper( + namada::tx::data::wrapper_tx::Fee { + amount_per_gas_unit: DenominatedAmount::native(1.into()), + token: native_token.clone(), + }, + pk.clone(), + Default::default(), + 20000.into(), + None, + ); + tx.sign_wrapper(sk.clone()); + + txs.push(tx.to_bytes()); + } + + node.clear_results(); + node.submit_txs(txs); + { + let results = node.results.lock().unwrap(); + // If empty than failed in process proposal + assert!(!results.is_empty()); + + for result in results.iter() { + assert!(matches!(result, NodeResults::Ok)); + } + } + // Finalize the next block to actually execute the decrypted txs + node.clear_results(); + node.finalize_and_commit(); + { + let results = node.results.lock().unwrap(); + for result in results.iter() { + assert!(matches!(result, NodeResults::Ok)); + } + } + + Ok(()) +} + +// Test that the shielded context can spend some notes produced in a previous tx +// without fetching and in a different epoch (the second requirement to test +// that conversions are correctly queried) +#[test] +fn unfetched_cross_epoch_shielded() -> Result<()> { + // This address doesn't matter for tests. But an argument is required. + let validator_one_rpc = "127.0.0.1:26567"; + // Download the shielded pool parameters before starting node + let _ = FsShieldedUtils::new(PathBuf::new()); + let (mut node, _services) = setup::setup()?; + _ = node.next_epoch(); + + // Add the relevant viewing key to the wallet otherwise the shielded context + // won't precache the masp data + run( + &node, + Bin::Wallet, + vec![ + "add", + "--alias", + "alias", + "--value", + AA_VIEWING_KEY, + "--unsafe-dont-encrypt", + ], + )?; + node.assert_success(); + + // 1. Shield tokens + _ = node.next_epoch(); + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + ALBERT_KEY, + "--target", + AA_PAYMENT_ADDRESS, + "--token", + NAM, + "--amount", + "1980000", // Reduce the balance of the fee payer artificially to 0 + "--gas-price", + "1", + "--gas-limit", + "20000", + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + + _ = node.next_epoch(); + // 2. Shielded operation in the next epoch without fetching + run( + &node, + Bin::Client, + vec![ + "transfer", + "--source", + A_SPENDING_KEY, + "--target", + AB_PAYMENT_ADDRESS, + "--token", + NAM, + "--amount", + "1", + "--gas-payer", + ALBERT_KEY, + // fee unshielding with the same source key to add more stress to + // the test + "--gas-spending-key", + A_SPENDING_KEY, + "--ledger-address", + validator_one_rpc, + ], + )?; + node.assert_success(); + + Ok(()) +} // Test that a masp unshield transaction can be succesfully executed even across // an epoch boundary. #[test] -fn cross_epoch_tx() -> Result<()> { +fn cross_epoch_unshield() -> Result<()> { // This address doesn't matter for tests. But an argument is required. let validator_one_rpc = "127.0.0.1:26567"; // Download the shielded pool parameters before starting node From 2bdc5150e321a247ce06021c7fe3edbdc6e232a2 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 6 Feb 2024 00:43:41 +0100 Subject: [PATCH 16/16] Recomputes masp proofs --- ...56EE712BC279DFB681673A7513CE688FD54D62.bin | Bin 0 -> 6393 bytes ...EF1861C5C360B54F42D041F181BC79077AF7D5.bin | Bin 0 -> 2045 bytes ...582DAD9FBD3ACA2E0F8314642810FC958594E7.bin | Bin 10105 -> 10105 bytes ...A016B823DA3B4C354320DE314EAF403C85E300.bin | Bin 0 -> 5412 bytes ...D4D70154B89179E7DA6F14C700AAE1EC531E80.bin | Bin 2045 -> 2045 bytes ...A0D10D24963CD60561FA8ADF3118E192AED9F8.bin | Bin 0 -> 4679 bytes ...B30049BA56A2A99E9EA9B09BE15B931CB7D476.bin | Bin 0 -> 6910 bytes ...FD0A13DAD049EAA1ECA95234C8AB02601FC0F0.bin | Bin 2045 -> 2045 bytes ...11DFBCF2AAA7876CE5FACD48AD18CB552E7349.bin | Bin 2045 -> 2045 bytes ...DB8CE4F984EEA5DE6991947DC46912C5EEEC72.bin | Bin 8392 -> 8392 bytes ...753FB3BE606A5729D43A6EA8F79007D34F6C60.bin | Bin 2045 -> 2045 bytes ...0F3AD4FA4AB61D0B965BB9ED02971491A2B7FC.bin | Bin 2045 -> 2045 bytes ...16BE737B7C747CD18D3B832DEC3C9DDCF3DBF8.bin | Bin 4895 -> 4895 bytes ...72B0D2BB1E2337D71D21CD8DB40EBC58CFAD73.bin | Bin 0 -> 6910 bytes ...DBE3DA9201B7C90E74A7B6C2B9B7320F006872.bin | Bin 6393 -> 6393 bytes ...0DF6893C1C09CF3101C402BFE1465005639F14.bin | Bin 14387 -> 14387 bytes ...83E61BED82F25C4452CA41B769C3BABEB62D2B.bin | Bin 2045 -> 2045 bytes ...06FB77DB730FFFE562F2565B0431F7A901CC9A.bin | Bin 2045 -> 2045 bytes ...6B143F55D67FD17124ECAE16FAD6286D804362.bin | Bin 0 -> 4679 bytes ...DC5356710DE7B6F6FA2B23C19412005669DC2B.bin | Bin 10105 -> 10105 bytes ...9384EF0421F46F7732EE62196DEB73ECB4C225.bin | Bin 8608 -> 8608 bytes ...2A4E4AA763188BD9D5DDAC6E217228B95AD57F.bin | Bin 0 -> 2045 bytes ...1E2DCE33145F68A217FD50B065966646F59116.bin | Bin 2045 -> 2045 bytes ...9AFB3B6AE2AA3ADCACF75E6520A66B2F7D184C.bin | Bin 7875 -> 7875 bytes ...A81A7DF315190329C7C2F708876D51F60D2D60.bin | Bin 4895 -> 4895 bytes ...7B62D6F3F03E1332D2B25890911CE8375D1280.bin | Bin 0 -> 6393 bytes ...9BC3BBACE79DF98801EB8154EA1904597854A1.bin | Bin 4679 -> 4679 bytes ...E298FEBBEA9975D764A6A9E2F98E10810859D.bin} | Bin 5412 -> 5412 bytes ...EF52D368B771AD525817E722EA3E12B0A96971.bin | Bin 7650 -> 7650 bytes ...F7858007C4DA521F8E3BF250A46E9342178EEB.bin | Bin 5660 -> 5660 bytes ...3356453E412F862D949ABE9671C24A3903909E.bin | Bin 2045 -> 2045 bytes ...861C7F98EA4325D94989648024831E350D8F98.bin | Bin 2045 -> 2045 bytes 32 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test_fixtures/masp_proofs/0E64D319134C2890884AB8CC8856EE712BC279DFB681673A7513CE688FD54D62.bin create mode 100644 test_fixtures/masp_proofs/0F1E22C136B5E0A08948FF20DDEF1861C5C360B54F42D041F181BC79077AF7D5.bin create mode 100644 test_fixtures/masp_proofs/14AA8F00D776FA8BFE458925D5A016B823DA3B4C354320DE314EAF403C85E300.bin create mode 100644 test_fixtures/masp_proofs/3403F505B8B74E42E29C9EA054A0D10D24963CD60561FA8ADF3118E192AED9F8.bin create mode 100644 test_fixtures/masp_proofs/3E8EFC1EFCFDF6F01065414ADAB30049BA56A2A99E9EA9B09BE15B931CB7D476.bin create mode 100644 test_fixtures/masp_proofs/7CF9F01C0531594091F642C6EB72B0D2BB1E2337D71D21CD8DB40EBC58CFAD73.bin create mode 100644 test_fixtures/masp_proofs/B6BF8444CE901DD0D10F1C8BA46B143F55D67FD17124ECAE16FAD6286D804362.bin create mode 100644 test_fixtures/masp_proofs/C5EF7E4D76C16E75B400531D982A4E4AA763188BD9D5DDAC6E217228B95AD57F.bin create mode 100644 test_fixtures/masp_proofs/D39FEE41A59DA80C4DBCAFC36E7B62D6F3F03E1332D2B25890911CE8375D1280.bin rename test_fixtures/masp_proofs/{D1F174D8596E8C1DA892DDC23D322056C14747EAC3FB1625F0A86957E00ED109.bin => E750A2B670666F8788E71B3F685E298FEBBEA9975D764A6A9E2F98E10810859D.bin} (63%) diff --git a/test_fixtures/masp_proofs/0E64D319134C2890884AB8CC8856EE712BC279DFB681673A7513CE688FD54D62.bin b/test_fixtures/masp_proofs/0E64D319134C2890884AB8CC8856EE712BC279DFB681673A7513CE688FD54D62.bin new file mode 100644 index 0000000000000000000000000000000000000000..c97e831aee39b43ae766d827de939e849b6a8e29 GIT binary patch literal 6393 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 S{&kJ}OaHz9*ZW_kq<;WuI{5tn literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/0F1E22C136B5E0A08948FF20DDEF1861C5C360B54F42D041F181BC79077AF7D5.bin b/test_fixtures/masp_proofs/0F1E22C136B5E0A08948FF20DDEF1861C5C360B54F42D041F181BC79077AF7D5.bin new file mode 100644 index 0000000000000000000000000000000000000000..eed08a5aa3c51a6eb7e1fdcca4d63848fec794b0 GIT binary patch literal 2045 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 delta 1797 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 AY5)KL literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/2B6C3CEF478B4971AF997B08C8D4D70154B89179E7DA6F14C700AAE1EC531E80.bin b/test_fixtures/masp_proofs/2B6C3CEF478B4971AF997B08C8D4D70154B89179E7DA6F14C700AAE1EC531E80.bin index 65e1f5ddc8e8bf282a8f715e28371a528414925e..5179ac037f19ae846fa17a1c46a73ac9822aaccf 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6@OaT{rOaeedN_HPlF6gk1pWQoC_)miaazU<`LH2y}jyaOcz zf0)#p^@H0Wbq7boJBwhJnt?$qtT0U1fz}GGb=}Zo_jrZ|Toldh)@%`o=v|{=y0AT- zXcn-@-FanqhT>Z*p%MjN1bP2U@^=H1IP-K~2LkvB&E$<_c5)=}hQK zy6sUd*Mr~lA-{;qn~Oj}=(969@1=Qm01|$^%#SI6y<*u+JdQlbIqjwbENrI zE$zcJy5ear?Q`cdNlv;OaPCmtUa0)GgT G;RhVGoSaes delta 308 zcmV-40n7gV5B(3YoC6>;QpsejpT*Z=<#!kP90yxd{(+A9b8}Nn&FVtR%rr~0yaOcz zf4HKowS8d0=<8w=1?{EAH`wG zVL^*l1TlHJZZdG@<*hE|MNaRcWTI9^f0E^js~Q9%^89d)XtG7K30kj!W;w#PVkkF& z!%6O!1*fg~QB~4`-~Qw13yBROuzN!{UIc}vOeCm#=Ge@bzH2X0sqK)F~CSy_wp-QctJc8aytg!0+RYsKc)2UZ@|t&i_5!wtcUHl7!{KI0wD~O G;RhUw43l>N diff --git a/test_fixtures/masp_proofs/3403F505B8B74E42E29C9EA054A0D10D24963CD60561FA8ADF3118E192AED9F8.bin b/test_fixtures/masp_proofs/3403F505B8B74E42E29C9EA054A0D10D24963CD60561FA8ADF3118E192AED9F8.bin new file mode 100644 index 0000000000000000000000000000000000000000..b9b6fc109e7cded05596bba68c38a504b8ba84d3 GIT binary patch literal 4679 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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/3E8EFC1EFCFDF6F01065414ADAB30049BA56A2A99E9EA9B09BE15B931CB7D476.bin b/test_fixtures/masp_proofs/3E8EFC1EFCFDF6F01065414ADAB30049BA56A2A99E9EA9B09BE15B931CB7D476.bin new file mode 100644 index 0000000000000000000000000000000000000000..88b9bb83015f515d5ac45b1735ba494afd8463af GIT binary patch literal 6910 zcmeI1RZ!env%ql@2FRen68;3Y3GN!)hCm=#aF@Y7cyNN-0D<7{?z*^ZkPQ}s1Q{gA z5aiq3o2}ZnRNcC7-}XzNI@NW$`c&8Nbobf6|6f7*C8*sd%&V@b^|sGhBE_xq6UN}` zuG5Im6}9p;%v2Yf`=I^5?0?##erNRx1ZS-_H`b-%FTsju{g6KC^M0W@S~0?NJhxy` z)W47Xsmp!Daqy!ji)g9&zbb-hjmYKS-(p|xnkG~;t&;nGnC{RbAq2&$fT)D(aeMM6 zlANubdmBb`b*-iGal4A15hfSB;QV%ZIEOFaQ`Y4B(jEzrO<$mZ!uuI0`TJGsvjK4v_M|Ckcn$fNzI3c7Nm7*$NIfEcw!Fv$eU__g@7ZK8FFOWV-dLV5RhZx)w_ zjo1njl3Om{c{A4iXAWsgADa`k$^|RsiSK!X>&iF^W)v<+$ar7L!y2ODo}S&&Tdb)K z54u%AIzxX2SGuxmHZq@)QV}@$idzAOBl9l)rb+8SzRI=Oo1cVjRqsuWZeHU&j;q+& zB??ex;8>Vy$Ip{a6VD7`JR6BOLM!*j%c{(u>(UTt4*Q~ld*$a3U-B)&zegc^DgTzO zk`~vH+Pgj-1pVT7AgyP`jY#D4K1h>{yA+oS610baFaTgx3OVY0pocmvbWa{wIO<_u zw?2SBK6m`N=j3y)`aM2SL4s_;^pocN4thL0=1#8iPO#?l(jo}p1<*`oP0b)c#I2cd z*U@=>=+e-Lmf5P)PX z!hO9;tVM*klbs7%K-So3SoWz1k~e@7cB}lTqL&Ej+P-N5xt>|#*~FoG!$i@Vv)42H z6hApYQto^%c|m%wSN5UsN&!XEoXVGsdfqchka|k8V{0c2Xn3{(*~lrC&e(J%X#0NE zfy9Xnv~`j`jflVIaF^Dg1Qw&(XQdrw5v0mr_&Qn^W^}!+=|-T=F2n2>6VT9mP>W>WLLsR>?`ZPK3*nj*f?CK6Juz zz-4wAA`C?E=;)OhKS0)QU%Sn1%!KTFc~Kd-gLxyzO>C4NqtO5@0$#(-axhy#^+b_( z+1>+{`=}S~sg#xy%kISaz9rg#kWIghq{8lSM89X zfPB1PX@>Gc73%|yR1CM-HCY=tbg%Lgb}FuQdvdJ3F_3i_zJ+YFoYO>Bb~KhjuNo|> z#c3a444wxOV+hY}IRR`l8@l%Dl&V**gACN8#UPI$bq8A8OCH_{V4n!4%ngVY(YoGQ zL2Y6h=HOV|G|@RJBXub^pVzE7leyq$Tbh7Z3=e6t1;Mq2)>H6TP!tu*i|a^N|~5A$|nRR?LY(E|aY)94So6>Je4?SMCDgI0eg2{D~(}p;dF>>SY|b z1(jB1OlMumk?_U|X*p)Dx|=V9=f(^FhPlcK6tDY@igpFlyYyMPyMzjDjt0Fwi+2cl zhmPEgf+53ofM&fjB8Ocl));GTyDT+=F#qTWYJ>)C8-ddk8MTg0fcA^PKS_-CJFJo2 z{CWv~sgM4Z)_aRtj%Uku<@3oq9U2y6q&2(p?3~|p0NQcY@Llv@r~gtZr3Ieyb6IROy zK8y^gUzuSO&}IGwl%MoM{asyWU7*CEyxcCVHYCV*JLI9?Uu0NpW2T4u&={aAJkPi= zDOyC3v9q~Fp%wfNXc8|T{f}o&ot{H|jOr&eRq8qClrXwJH3bChX5~wUHweRO(lGdU zetuimUHl60U-jR41HVn`e>5Y%Ya)J^)B&Iy?f;i%rLAcW^tO46N)s#P7U6k+aZJ?4 zWAe5DH+MnUK6vul?%$;T?@Z>uqy9;29L6GsLbv<9pL;*6$iMh4y2;Wk{35gAND^#HDi&kqJu4hxJa)>~cMSwA)0xTVEmW5`hGDkgzJ3nnR-%x@% zp9P_1Zu1tJy_Kx>a6hKKH=<5m%JXJOP?e4~69?m>wsxL9&&MOr-;BmYTV?b_A;+gb!QP*#wK}N(z^2c8NPCo? z^&sv1v+kxcT%ovUL5xLedz-FX+ugp|n>7Tp6gRSjIGJVU(u9p^Dk5 zCuNMy!F;;oR(Nuklvsi=gm_?)F~viuk)ol#UZ+sIuST3R6g^)De2_wd#L7IfrL9zy zj!t&H63B}E;H(g%dIT@5T$DmT$7IrxeCG0++wG~QSL274TuvqP+4e%i4kfPOo$jwQ zdw$`?TA?4bw%_gyoeN6x(px#Gph+bN+rk2dd^P#Sx2eO@1D5D7riQ|a{6k~64>IS@ zo~t!MQS_)b4px{si8p#XS%|)sMPn>nRNr0X`)oLzy}OnP@L0dt(Df)f&G#D!#Y-C1 zV`=F=V)aNi@8_`RV0u5XMU785RW3whX;q^vC+<5mKti(#>AeI!v#QsM<#6 z_*Oyc&4BmiL$?Gc+pPzN=ua1NhO*0_--tLm&#Uv3G4M;D-X{yBZdufE z#*H-*k@FN1g~!U4yECUcV5xLuA8t8vf#uo*U%odnK8OIci`nZJr zd8_4d2f}7`-8V~iC!G|yaP`3R9g%x;Y?l_R$SgJISFAY<&Cd$L_57V5ig0I;4^;w%02T%{;*LqrQmuhjGu(o527h$RBOXY>n#btA! zXKcM-wuEKOAQfi{xLqIJaTS>0_K=Rk7%W0p9)I*&3^=;HV%&Br!yZm?#fR!k|516W z`^2DMvjbvmqLWTD?)K!8{Qen3EcrF+uIV^TS4*CSBS{?js;6d>kk8vT+gaI*rL1IX znV?ZckOMFOd*b@TH#|PYm^2 zWkUKF-ldlbMLJ&Y2%<~H-{YGTNad5`Z9lhBAScvU2N%v&bF%G!b>IEk7JnC#OTep! zWJc{Z(?a;ED_2XE&93>))9GZ;W@$^R@wQHP^%CascF=dfQNZJJ)NKVrorOzg)a?no zlF9HLIur>@l?*gPBp26QE&H=SC+rO0<-<35wEA9lO4gCFh+0=pTsncnvvIt=ST8~@ z!gR7cH~bPnyi1XckcJ9GusV;0k-CAzxd5#p)k*UEHn$OjoEkb2#e-|gu&5*+bQI)S z+0hwaP~TojcZ|{{DQczBh3Yu4@FB_R)@?V5mEB(FG0N`--@lu8hZ8(H*C~%en%6hD z_+Dw6=Pvqt1bo^~HR7nHw>HAok0u{6no(h@kXaHnlbCUj3Z5umnrMC9XVJ^{Qo^+0(6ml|)eIxx~t~!_a za%wo5Qd*C76PLC$1H1c3^!(QI%Vz8?w;R|DC)-=hxJ%MG6JybGnehFo zSNLca)3l2`1mnuVSmn)019hF9<_IqB5G-mQKObGV zdt7my(p29wjoKi4OSZF@R2EtNr+kD)D8abqBo^efI7a%ov^8ygQ-#7a5Xx4Xt&L%s zC@{iiFLA=JiVLI8lE%bpUppFEqYe$SKKk$^of24zr$clB50r| zrh017r*X2oSAa(813j3S-~;6&nKTXS7N&F7IFIYY8};Ho8J?kNyIZl+Z)BA`c-x*I zQ|6Wo89HNil*0e?u&$TUKWs3~P=W*^ciMAttb$Vh{NYq5uyM`X1(^@@TpaP%V+~Zw zEk5~}rDa90?xlL)X@^>mFdc%+oq>Mbei8ZhD(*#-V1PS6XD;>iGw`-NT&w(sAhP|X zX3)`ycxrTOLRwQ|9_<$h?jdeXw>E3wIh(n@bnN@%KTL^v__b=)H_hEF?RxF4XS+K1 zJf!%LJ@dq2a>0n|4b{B-12%%DPw@Tc?!LrJQA6w_!S8)J6v>PW YB~kzR-}KM*-&4?^Rq5aRf6p%e1CPxRX8-^I literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/3E93E8F4FC3498BA19EF4D4D70FD0A13DAD049EAA1ECA95234C8AB02601FC0F0.bin b/test_fixtures/masp_proofs/3E93E8F4FC3498BA19EF4D4D70FD0A13DAD049EAA1ECA95234C8AB02601FC0F0.bin index 3cf4fa54117172d4736374bcf5dd5c127f432a61..8425882840e8265a587638d64a36529618b1ddf2 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6>|X*|^!#8`+;2L_o>ImDpceZOX7@6JmbB7&{TU&QURyaOcz ze~(9LA=I0A9#1O&nzWQtumh~M;oK6h1|Zr|Bc~v+se2eU!S*cJgx*DnwPES8qN=%n zW}$M2Sha3!CxKj|)=k#YE0|HUpdYz#i%{9AYE9p>4;VUau3Znf8ru-QaSTMCycm|- z7`o_vSCkG0Ud&doHLyPY#MdrPsrx5be}U|y&F)2u`hl9K(OsEDY7>=Io@Y~XD-P>| zMh==+KKR2~iImKKY2UU?J(-Lo+d^Zl>$;xEs+XTGT%MhhcuoHS!ob|2=dbv0Z#Qst!|B^jl)GIN?gq2sCC6hFrz__^m; zz#faZ$T{_S2Sub(OVt;!;>0_}QL$Siq7ve}mc`>oe2l4&uEr_GH`^FlaqnGVz|;7PB*fw+A6sLvAz*+?NVQ-ZDgn0AF~0=f;8 G;RhU0+?UP( diff --git a/test_fixtures/masp_proofs/3FDD781F73CEEE5426EF9EF03811DFBCF2AAA7876CE5FACD48AD18CB552E7349.bin b/test_fixtures/masp_proofs/3FDD781F73CEEE5426EF9EF03811DFBCF2AAA7876CE5FACD48AD18CB552E7349.bin index 1452014ada1d9bd81330bd33b55f9682c76f18c4..82fe852cf65fa05d297beb537800a3c00dcfb669 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6@2??aqvRN$RG?)w&WNj671ZVH_R(^UuzXDiFWa{RoryaOcz zf2KovEzSk37V`Ag{5qBxA9Y8?(he=E{shRo$Q~z^11u1bgn<#zZ((t$djU?e8lpp_ zX9#EDFtGA&sPGyG=0`bv+E(=|-I)rwhQWmj+YwnI=$w@ZbX!RN`o!wiI~jsSey*P9 z2ZO2@EHnFSNJP_NTtK^UMf31LIM?zqe_w5zhbEJgi8d8LZ%970k#)GqDPpotlB9mR zQy;buB4j66sy}fcXDhq0{Cs%(p(g;BMM8**%bK&QGQ^))l5+gn(n?r5f!CEao70EW3W0wPmk5Wk9Vg9XmE^(nEx@89nDWOl{L=DWOhupOatz-yaOcz ze~=!BwCMoXa)b0m?I<2mo6vWq>%SVNn7(t(LU1!9Y>;FF?-yQD5rX@z2Eel@#j?(u z7vudCf}9D!DlnO(X$k%bTlurn(++q?aL2OKTPC60!dtaPu{LS*u}xVK0v1Dk7xCXv zDQmg9^aO6DU`p<*mbfsOy-pi}@e`6nf83m3+jn~WZ@4iw81Wv7@71x{-q>}>RlTKw ziyNJCw0a}-3LJz{L1NjAA}Y+LC^nIhQ%@Zkf;AaGbn3H#Q{GL^18DI|0kFJWM-~?p zWe)1=`{X7Rs5%u`AaH#PmB-&-SDmc%2}!J G;RhTgl9P!5 diff --git a/test_fixtures/masp_proofs/5355FAACD2BC8B1D4E226738EADB8CE4F984EEA5DE6991947DC46912C5EEEC72.bin b/test_fixtures/masp_proofs/5355FAACD2BC8B1D4E226738EADB8CE4F984EEA5DE6991947DC46912C5EEEC72.bin index ef1caa155360534f60706e063e0c8b7e64b0aadc..01a199b6805a81272141528355f56ab1a16a7295 100644 GIT binary patch delta 1470 zcmV;v1ws1ALC8U{K@}iA9^u1L)4TSmpkbiK*&J|N*OtS+Pqym4L zm7J04X$Yf)b|>CA!^qyIb84kc+5bahYBdSZ^kk~3F4!(n`^imwTksr6=eYxuKgobn zHZG;YFPz$Gpj-#(z0vO11f)S5Kf@@TjmUK(pV@!aOjA@CUL^6{k?*r68I=N2Q)1v#sDY;C0JXIV{%y2|R2KHr*@X z3{vPvfibfn?}m&rOHyj`yY#!zxwX0~7QW5%y8oPncb`=@UWMjqc`%BgMZG4D;xDQ+e4P*=}EJMUzoIf5V7W3IV76RO5mIsMHYU zl2?*kJL&J#m*HjlE6NVG>}TZJ`67_NVUe|XT|YNwjNrkD671~j3Eyj+M67GQV3wJy zt(4x5Qm7w@yTK@(oa*nFMcgK&2S-t9*KU!n5;@~7#~{40jJF^WlTiN%q|&xDeJ@Gb z=qd3G2Sy*wfA<5qu>=f=|Af4Apd~DAW>W({+EF+k>ZH(tK_-X`-MW@UQ)OZkt0)G@ z>h{w^oP|n^aEu{)lBist_raeK^?=H6Z5RkMchlQ)%c@OgS1W!&2Dg2xP!(R4Oj|_Z zYt35$kmZFaeF~l(X&LMCGJl`{u4Wb4sfhDTMc6vhf8C=_W6C1uHIFeGUCAW2w9 z4vW?pej#gdwH(lVr* zztvM7Z7pzp1Y-@8c^Ef&LiY8#;DT{z6o9LDI=ZjBp$EtXCyS~vB7kts>AYe`COdN0PFqizcJgbtfmHgaiJu&yP_KORK&vEg7Or5qXFm~m}Ft;JLvkwRIYz&a!J%*(*)0e`kMdt|_L~7K#}($J1zm4I5Z*>K0yOi$vO{ zA;^%&71BHed-!)Z6So-=1CC{Rny!unce z@ujyh8AiS)dCVfp}C0S8Kr4IK%8)T%bnNSt&av(d1F8NUI}A zZ^gFNERU>zz}hIH^^GPXi7m_D6z0ph`l!)~(kh`UHAum%^U-@lQR(y)gH`91v|HPc YOD^Lm%+WlXeEpm0HAZsq0h5d%JXi19@&Et; delta 1470 zcmV;v1ws1ALC8U{K@}jI-5%xqj(nZZI%8v(ZmJLw36v50mX<6f!pO#a5eVp$VHH7P zvUn$wp;(S0rtzi?H5_-n*yat|F)jF=Y&YcHWSGHuOv@883mX` zxdK^KUDc6cC2o=KJMDKS)vQ_}{O@elSP;WCX_Y~VD~3)u)tvNYK6DXoW$mwe6g`3- z>NWuF99qDk>V@!aOjA@CUL^6{k?*r68I=N2F2{G`yM)T!Zq*S14&L*a+_u0N(<%=U zB4zL`-~K5(i&A<1+B8v$|Ivx6Bkl5@+ESXWd4Y z-D0RLt^gi*FMwL3Tq|}4ENc{zdbkyBQJTCRfmS9u5|avOSgKKVEl+Iwdn+KTN4 z@CEemZs%A5>Qv(%`$2jMmcCmbtLQS%Da28+JVPT~226!}$q*B1Q=6UM%c%49wa93R zmoQN>@(roce@_Ir5ou~__grDmN8joZODf)Ef$WEw{exbv40ZD$gEIVE2y(7$O-rTR zumuEO59M%-zOCu?vIEh?4S#dv70lor7vW~s>RAb!* zgUCWAA(1?~nJ5El#|M4Cc>`xoW@z%~+3~egSNq)dTg7R1hal293B8j)sbc`&v?ndP zCp0tBf-AzFS^s0D>>oBZrLTdlu(1$)u!;GW)?6i$?Eq~GuBPTx`mckEk3hY$=E$Y*mkIj9Kx@8H*D5|+(kC`f}jJLrt1*CrLr z1i#5t$x!{&)A6!LQ|9aOkgfc5z#bTzKN%Jke*#pmCn=+G46L(L?J|)QWnlgGR;v~_ zH+p(FiMVG;8L_)IZI!V=(LPnComH2;vFjfvAJnwJ(DiF}?DV<4IvD^I%>I7l$)jm? znG>6#`{3ZQV&FU8Af70*-IFvE+IgtHwp17?Idzw23L@ih-)*Kb`&FIaik6E%I7_;i ze^~nqtCqmu+(pbt;n>5cNxz3+?*A9I-bqD7Q4p9yim@bFtpSe{p3cC0sh+`XuPX5< zID1|&zTFKTq%av>0Bbv~_m@_-Ju}<|KSX?*RTlH>D9m4k#k_S^qBz?d(xcc>WIENy zis_f~2-QOL)vH?uqc^a*K}=|p&kjb2e@<@%{mMBmCi5v|RXnDzfC&XtIt6?MILRPt zu5wG?^Fdlx__ss}29_y#by%+X$(97gm6w&*z>R4ii}_@uN06hb#?8)+j?@g172w36 zeYA;bX~E|;ucXIZ$r?|_yYU YdRTd99cdkp9@!N`$pqB|1e1&)Jk?^*)&Kwi diff --git a/test_fixtures/masp_proofs/59CC89A38C2D211F8765F502B6753FB3BE606A5729D43A6EA8F79007D34F6C60.bin b/test_fixtures/masp_proofs/59CC89A38C2D211F8765F502B6753FB3BE606A5729D43A6EA8F79007D34F6C60.bin index 18d1c0c99e4a01dbb08eb8a098bbce380b1f9448..31fc8824ae587f914f9edf35a37f97771c66cc41 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6>vxeRbZh3R^FGOy%Rmuz<mrT%U-Gc)( zP{G+p=uHfrewnQ@R>T-Tn3Xb3kOWG=qF%;0f9M0d_^erYanV*Xy^aT%4v4V*7^H6*67Q^d zO*8ajP8PTmPPl_!q-Q*7O^AEbPOX=6(`AWM3K3j-PpyRMi~CE`hX@{Xo~<7Lfu3E9 zI|hqLT{Nyj0Rm}sizb$OpwRt$B@KdB{8bgf7E)_}&~Lb+%+r{UaQ_tvzh@Ck0!Igv G;RhUYmyNIh delta 308 zcmV-40n7gV5B(3YoC6?F%}%7F^u^t{!2m&ZPgw3R$?4B*Ey2JUNnG}kxckBic;qqcQu zcc=vO(@9^l7iC4$et%E|8;{|55e8JN0q}!jdWgEQHCJ1z~jaG4WtGLi>Xb{VI(%yubyZFAgMLlV;P{j0aYk~L4)~t z=YhD|NzC?n>M+NE25tHv8kK4&|Iog8&M7;ykj@>OHY<)&p+U7z#SLc&mj^T0x>q&J zb`ijR?$Bl&39T59$oW2Bhne?xJe_UxRQqzfwJs~k`dU)7*jP`G}-b`caX zSFoAJ9jvEQPgKrAQCidC+4_3@Qmw0?DL>L9`E}4uggF?D{0q44z2};6yIL$+?zvM4<>$?9F-8bdxlq!$q<*p4e4|z z+0j`wUC52dq5eSL9p->f_nc|ReweAQf4(T#nl=Mb}4 zYO;c~3DBC0gED_I-{PX-_{z>3;fe9Aia1|MI95BI5LE_$y73|+Iim&i#yljEU0i24 z1Npm{QDIcUwSQCX0zMG5OrOfz=Ts8?-DJ0Ta^+4>zYdTw8p0-*qt G;RhTPZkSsD diff --git a/test_fixtures/masp_proofs/7A240D86DB78C8E1478FB0857D16BE737B7C747CD18D3B832DEC3C9DDCF3DBF8.bin b/test_fixtures/masp_proofs/7A240D86DB78C8E1478FB0857D16BE737B7C747CD18D3B832DEC3C9DDCF3DBF8.bin index 681b074d16b20282cfd7c46cdfd4ed9d05407bbf..dc1aee3d37b9d19463cf9790d58f042582366a04 100644 GIT binary patch delta 926 zcmV;P17ZB1CZ8s-U}I-%JR~ zwETR5hsxEng=llzhrW|#b{UdfEpB~ehRN5Rjuc1Su*k^gqYR1!>ScYjrr2?{%NTCx!sr$>w7S@#u^WxMb0B}ufOB2`KiWqVsqq2Kz7}4& z)#GOZ3T{IvrnuY91AGGTxZ)8ld&6%VJhuK&$Pqr2Tpc+k8a|?IDyX-a@Q+5E_E)dTOMixD30sXVgLC%y-Gzr=8JWD4{zBE{r6`@%}t zW>%cgm_kuZ*2SbwJ>@(5$pj?7tKIjWEb_jciWo|5)qm7*j6)D1@<_W($aEDdNeQSu3FR_fx>bX+qY2iC zAClFhPbhLForR*-e?eZ9aG%RGkzaH~P#?+~B4l`1wp z0g(_Wk(~&W8xSCWvg)P|^v#TB6$I??$;AEiavu@y)kAYhn!&6{cdN~YR!|(|)AY=7 z(2mDKeiL5_t}_}o6xFU#$g(oc18#i}2Ei8Dmvmb)Cl?Mj80QXY9Z9V!?MIMAr+6B% zn}S@86YTwjivHP)s9RCGIOSr0KEA{lL(%d#Ypoij4gh?A1N-jZTp{j)4f)Z29Mw+P z`nPql50Rm?PeR=YbLow+F*pQ6qCh+u`KCMFo~2;cvRNjs)YZ#)9P9oefv6<)^cC0T zP`cGVcDsV3{~8jM|=a(ZuGAuiryrbNV(hTD-3Jr&08x`BU#A z`c?Qzzx=v?ZU?E)+%qMJx>A0bz%3`zlDTMkQIm$qaFl8}$t40C=XZXzP)|u&^`|<( zEr-><(6N≫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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/849D9E73D858B17BBB5856FAC2DBE3DA9201B7C90E74A7B6C2B9B7320F006872.bin b/test_fixtures/masp_proofs/849D9E73D858B17BBB5856FAC2DBE3DA9201B7C90E74A7B6C2B9B7320F006872.bin index 50ecbdd347ed5f93840382cd744ac5951d5b669c..678a20c50bfd600e2e7518a190af6bf74636aa5e 100644 GIT binary patch delta 1153 zcmV-{1b+MZG5ImDG7casqg1+msfsPo7PA?PSu@Hs7%NYr=KBlJ0_bnR%C@SLQVu~u z&84v9AJc6=iaQ{v6v+C?C@f#6XH)_g!Eh>yKZGYk0_*mahK+Pj!JKM^vQ7kXdGp1I{`mdZy-L(L9!P-{~L{v3%?^Q5S11Myw0azd>Ko%!6_retxoX>(t zMI@IgPH2+w4-6&K8GV?a*N`1L^{7b|5)TZuol_c}0|Ai`D3P5AlMNL>f3mKM_$BZ$ zPr-i$$V?+K?CF*P2ep^M3efSoG>U|MhG#E1k(etLrjt9Bhnd( ztUb_L#s&wK0)_rVXKU5Zf1M_obKl|@${xxC8-ek*8D^54P%O;As(>gMLkI`Co*B%K zow{rF&}khirA6R&9;6QwP~(UoL)IiuF>8I-nPgexrim8Fckjl*n1)-lMA@HuTpEME z39=*AzeNSl54Zxav>W?Rh=dCrDVO*Alx2x_a2Hs$A#YJ^;*`AXe~|;EBSY3l#qL$a zVku4l(0(c=yj(nk_m|35Cgb4*?J93DR*4_rLB{aL!S za7?X$VmAazgVpK)J3&&fYYECwcFfn6r%GInxDwwIbd%h_f7K}Ae7*GWhJDbsnchSy z78I^;qHLE?0+0f*o3z#EWfS|YXbu%^0pl7C+Qge@HwOQk%v<*T_L5K`uIa(OQQVUHeiT{X3hVwAd+cx#xO*FO&9kPsxP(Z)F|1c>gxC=>$DM)HPj|cT)eH1t zMm$RBt%hvAVBrbyK&(R`4STzFM~xB`0=9t2EwdR|!U2&GD3P5AlMNL>e}l6=meJ4x zzLF3m`>-wf+N4q`I${KmlR8G7PkKNru2yMHcpmMmmk?DJ4h(PBJ%UTTW{rs6u=a}1 z4<0sjQo8YwVlBcr9}7@c6VZGN_a7c)2hSMRuqhUNPS;S~LKJq$7eW@B=dpC`DN2)P zDTC*t31NmsPgT$}1|t5Ue^BkH$vIsWryt)9CpA~(VB)#fGIcT6(;8g)2;dXPRIC4rEoj8S#%&~cbDRug|OtC_3eA44F9Pex(?u{1Jgxl#uD z{s*E|UB@aPek;)c{P!tFWSHVEvxO+++&)^fZu_E>d;e(3N`HN^f9MIIh6~@_G(xE; z)Jt>S5xN#^`*o7b1$mJ%E6q;!Le@*SrQ>Dhh!hdbfuH*(a_LyN%4LNu+IX!_n2Rve z6O{HBK(AdJBUIaY*aaAx0h&+5le zanj>Ao}l}k2AlTZe=blH%V+L2TE{?p6j;q~WnLArtZ$A^oAtsh%`=&}P0gCKadQ-j zUTE9|L)5#ce?|L1^^ND7)5yO#?TvDpbc`qyp?Q>%hV{C7xXj>fpES>vZvJk-UFOTf-d zIRmAw$1X}11m#)8?yM9UDT^=g2)u0-YPB6av`^Uz$|6rO@%W=jlBQZ)2H^j~lpgBMh9z+qquZ>pGP*sNQ zz1JY?;-ne)$b~aR?Ch<|auy2|i^$L-l$*LTCo>gie|isKTd1I=gV3j_z&u9PM;~(}ffjAC|hi8pMPNMkto=Wy530{4? ToQw&J2LT9?^di3jlg$_`7mzUA diff --git a/test_fixtures/masp_proofs/AF6B3A470013460A05E8A522EC0DF6893C1C09CF3101C402BFE1465005639F14.bin b/test_fixtures/masp_proofs/AF6B3A470013460A05E8A522EC0DF6893C1C09CF3101C402BFE1465005639F14.bin index 6c9a57a93a2110f597d22a7b0e8fcab9cf665ba4..65a58651bf7ceeb33cf7ccb9d84c8780ac02c527 100644 GIT binary patch delta 2424 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 G;RhTYX_jaJ delta 308 zcmV-40n7gV5B(3YoC6?CL!Y=gPrYxoJlw3PKJR-I-$vZ3*fc= zI&!2}U_r61#G8J4K!C+QFOc^FEipX1jCu`eP6gcx>wxE69bPJJdcbZ9o&g)Q9ww9) zL8v_n1rJYpD`Ser6-BsI7d#U#nOql;f7U~BZD+2bD9l|j((@zSXL5)1`P5iKpc6?W ze(NPIgExT+3?i6_Eda=9&==8K)p-`@4?Ud2$dfLyHtAI4Y)pEJAS0yH| zS%fZ$gN&sSU3yUYTP^*Ub=T??TBlpde?p+jIN{|YSvC#_<#L$J_lk~BE!(Na?;7Uv zXg?$8d-wL`#qIWKoCsENIN~-qEy>bFf3edM5}rMpS;(0GXoa?Jz9r`NaP|y;iCR^O z6Yb0;)fpHRj}?=b(d6ext)g;I$oaV_i)iuBDaPFC$UTmW_tcqd7wTHi=`1tr0&5AA G;RhVwj-YD* delta 308 zcmV-40n7gV5B(3YoC6?DR@zybJ91ObN&+V?K@R#WHO#p2ML-*Q(`r+3T1aBEyaOcz zf35yQqOCSnK3$3urnqxF7S}odIm-1Zh~=`?uNt<8KgrnckM{Z2G3Hau;oRWSqp^b@ z)UYnko~2lq;>e%;gB=!qgC0oI+JJpKJCOu?ajReCFsE#}7(iH|1XkvG_6FDIC`Nqt z(=T*z)W>rC0Q%xtB34a80*i7InGS#|eF2Y8kY%!q_m*f3|vini>mCo>XwY`j2u$`yu7(ajTI0J>` zC4Y~dy3GmdbEcCNZy23JTo&w^RRB1t>G-GJRJ$7?t5`}nWUxaVO864%bl2F%0vZ65 G;RhT>%$Csr diff --git a/test_fixtures/masp_proofs/B6BF8444CE901DD0D10F1C8BA46B143F55D67FD17124ECAE16FAD6286D804362.bin b/test_fixtures/masp_proofs/B6BF8444CE901DD0D10F1C8BA46B143F55D67FD17124ECAE16FAD6286D804362.bin new file mode 100644 index 0000000000000000000000000000000000000000..da509d1cadfc701891f9cb3eaa0f750dd9fd6374 GIT binary patch literal 4679 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 delta 1797 zcmV+g2m1K=PWeu-78oE@VpmmD#%EE4=WtoH#!k4mX?=GDUCjY{VLrhT%gjlWHW)!+ zd3fm48|O0);{Fi7&dzB&CV*~S2tsH^=BZ5t>*<3Xufy**@=FJ6>^i`a7{fO5cd4xX zDXM6wwDq28v@s@c1FT9Uji}Hvy{36pLatlA{)$jw?oUh_#LyjR7A~scDzn%aqym3$ z_zgXAzGqu(@n1i6fMUd1#JC_ro>K7z8;muZKSN*1%(A^S~;e+#4z zOk^XpVGxKlq0(@G{SFg%Ek(x{M7)Fk69_%BTr*nnmr9N5rWp1 zvGhD+h_etJPjzZ4hivzo(nkZq6Zr*lYG4&M%JCU^d_&H@spz!{z_~(^qd|*{=6Lh7 z49W5z%m zErsJf5&w8y3)bW1HJcD-G4Q}9v>wroR7s3zb!=hHCjW{pk zbEY7%z<@*rsDJ9uc%sK;IV5VgRog0R^|{;A+qTw;?w(GSvdOI1KyMHtd=JYMKjUoQ~o)by6IR)%_ z^_E(lBI!PwkR^{tRrR%#vU3P+>+3P<>6SBHgao7uJXUbs&KzlFZzwQ$L|s@q3a2*} zphH~FTRay{hAqYt;Jk(ov@cb8Ku~(G=SZP(a!fBx?QLBRHlGs-tRz;vt2plI{3ju^ zEg8*|DSt-K?$ec+AT?V9CYAN^H3=t718r{P+uoaVR1+!i%LTtel_UE*K`YOX1 z;+`f-;B)n)ABSezWpygY_5_}z2fq;V5W0v<;p_*0ih93)JL~Q*KxsrNP}y$-bs~nJ z2&bb9@(C7&wo(wE>|GG;AKvOfP0JymzKiVoCx3P+kHn0wlfG4FNUZcI#1vHvO8!^W zhAbJ=d}7=`WNgP4l`*p&SCFQ0pUDMpX$XCv+G66^>jW76=SjmK1w6&}u>T>@hCZ6k z$t19$LKkM*|KLXgUxjOCcq8*w14~3rJ+(`x!hHJ8GJ=6q+or7YlWcr?lqf2;l~Qw9 z%zu^N`5~?2ldw7KU+i4f;>enWXKdMq+-lvtW#S8nD4~78`;YN>vIBUxBvZS&7GdX% z=fwMgpNKa9&C_3rz9SbfuqYle3VpVY7o0DkSMqi-W{b`HRF&J}YzUa4y(-Eoh{7@R zZ(nkHbuttwXKjF-sjRVI7x{fi^p%;W0DrS1Qf|tfEF_~vs#R)SkH2mF%6Ar3Fnc(e zT&}E|^3l}yaM7PT@is8%r~7-Xf$h`syql1@#;%jlW0bhKBF}1b4x^K_?zc`@6s%8~ zksW&yw_HZXTM@rgj?fb@brw}&22wur1|b$IDMhgzg=G(z(~oH5rnOWL_-cE=&wr1! zwyq2VZr-qB7rkVgd09&yUJcH|^?B2#63>htnJ|OsQ6YB2?KmfAcyJ7fS>IcOPdB!r zEdTZKnyXF{wTI22q7cMMdpn?l8iGH|BnhII{9=SdKtlC_11lI~q5U@+&(N-oKBmKf nwD9^i?lxl7zVoQxJR@eG&QG$yBMMCybC!y_ea9&VlQkzqzuIxr diff --git a/test_fixtures/masp_proofs/BEDD60F57C8F73C0266B1DFF869384EF0421F46F7732EE62196DEB73ECB4C225.bin b/test_fixtures/masp_proofs/BEDD60F57C8F73C0266B1DFF869384EF0421F46F7732EE62196DEB73ECB4C225.bin index 86758ab1c20419fb819a55e0c73d8c09ce78e16f..c3b3c0a571671f865a829a097710d6e45d868b73 100644 GIT binary patch delta 1474 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 OkqoX{p&U?Y1p)xc725v* literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/C614F20521BADE7CE91F2399B81E2DCE33145F68A217FD50B065966646F59116.bin b/test_fixtures/masp_proofs/C614F20521BADE7CE91F2399B81E2DCE33145F68A217FD50B065966646F59116.bin index d83c46f49a3012e806cd728ab439f1e89f51fff7..526753fb9baff32b33f2b9bfb88db04e5f832f22 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6^KfGI#7l|g{6RvElK1Fst9Z8|>fIClF9Q;y_5wd*_c z;0FZ4o!@x@e_EXM(rhu>a(W@0@cd-{f1Di#s^&zn%gw?6z^XA`8V;6O9wT*+=I!U6 zHLqV_`GAOEOSNyYsMf{fkFdW1jNH00{FHwQzfo`84op!Mi}L zMEp;Km G;RhUz%#|eo delta 308 zcmV-40n7gV5B(3YoC6?bI`x1~c`{Q42s~%Zo1nQdT-{FKz5j%?xgUCE;PcS4yaOcz ze}I7pJt}*P>Xb>`>{nLQf7sbrDI|k0&PaiI#j=72SEPd-X^A6TzGd1M zTVLK7Z=KIJXe}c3QGYB+gJS=2YXh+>i%T|2Ye?7onRc&X7%KCiLnD_LLlj0j`1>K3E|Q5qQBaVJG-|4{}_Mipz_ zR8V?jsQ9!Lp8@aYJe@+Eun>cH` z)I)M&OvrlvL(<7dib>9}Oskf*vVi&2YOefn$`k7<#BvU~kZK z#Pk;J-asbIddZ+9`#HJx=@p=smw<+M%M?-7gQ>H)BI8RPBI^+vyQqFmB{+8ae>OzK zJT6c2y5!~2#HId*jGT(+L#pGMm$`8Y>d1cUf;H!*)6!jRkHO5Et^m_88f)7zFH0ZG zG8#y1Ge7tc;5TMAgZf%^iI2af8`kTgZf~D&d0UA1FTiOYN?(CeJ{LfnhI3iznWC4} z@G@ECZb+w$ORJDn;(=3)ZgsFxe}Vy*Un+I0mZ7Ng<8cf9Xpk! zlnmAmAvPUTvCNI(;Q#9DH_Bj;Q!bzX-#wAZuSkOli!l)_l^&cB{}^)lSA|{Ki5*JR zj@4^gCixTiAXafvH6JqsQs~$M8Y)Axm4p))P9wzVlqq44!81HXKnC!|f4C=th+%3- zDSuHgBpORq-)g3swYW_xwBu0xKuus-^>jFVGEH)G9w0~%5T@QqDy3Zi{hY!MX&xoT zUMT4?ifohTk}dKLX;ltQFb0Q9L(}6Kf~?YyqBUbiN4z`zl<=7B3y-pzUKzuq3-TG3 zIELS2wR3#{E2XM|rh5}xcD4R{BJV}Zk z6%(u;tXXDLG-zxW%Yk*D-ksr?tjL73@ZrRcxl=-fS?!Nk=j6jJWf*&)J>Y%X&a`wO zC|V;3K*_FqbmF3aLv_?WM>WxLpZ4 zoVm%=rFW<+uliP-Qgdq#czXZC>ipYQ$jxDM0Kw|7cWM!3I|CR44(*aqw3-#3M#p)@ z8@S%d0hTGJT9_-nq5KItcv8XdH`ItM*JfXi9HZH%QJNL)f2z>z!Cny>4u_%BWH?}_ z`pi>)=VuSG0cB-6YB!nd$qP}D8Jmv305bl&_bll#*S+Lj8e=)a4=}Z1pZv$d6y8Ar z`9V{ZeTMR%d>IX!fY%p`prZUxnEp&-*zl+S$@NlOf-7z;yVqF^#R~7w#UF?^<7NXQ z5RVDLNIq7%NPHx{P)0UJpJTTrYMRE@(U@FgPJ+lhq52^uuJOVl%bz85S{9<}VSwl& kMF#)kv&xyRb8F8|G`;4}z;DyTt*1fO$2L{{36qZ=G~VE_^#A|> delta 1378 zcmV-o1)ciCJ;Ob)6cZq^r1_|FBgK_1S8I7;x8tz+V&H$T=+EC~T||53*Rg?1w2GfWUMlJMbo(!PMl znNN8gZ2PJkpeeS$0(p}@!K3E|QNh2=s>$AGp*Z!2=SCYG z5sF$a>m%9-wF69)<9rCaO5(KY`hluv@RLX4ytAbH;0e=BzqNs_i%@uyWG4}9=A`{b+YaqekX!y zwB0S3F%%<|$MH_c9yq?82MsChCY0l2$w?nn3h5=As)!%1G~toN(qJ#GU$B#Le@_Ww z6-01vKp!r#mp!++EZKrd%E|1UJH>@x@A0KOI9E99;3(8;Ae%JYTM)Fh3tyGfey+QLe>@wLWvFw) z?@3dXyn;qY$W8Fl&;T#0{U*ef4lL_4N8#uSAr3q zZ9MG-s0Fq{EsEE(+Ch9bZO9&ZP;yR?I;Fd1m_|V5u@G$E^`~_t8!NRevtl`k2_dPz zTmVNR;&gk2LV}uKtKI{K-@6*N2pa$zW=$9oyz4%9mKptvz(oWoi`bhTqr6`D)H>;h zRSS4T&+dS$z9|&{e@kXJ;+-_QKE785lbUu8Jt29@g=93QpVwi{blir!m7+elQUAD@ z>vBS+v#X&z=)|yLG&RLgUJYX|xOWr;E<;jPo=bAE-WZ{h`gucxRDth~92$iK<-?Nw z;6@H(4@ak%1!6MOjB~FwKOND=-V4VyW}_5@kIbISR_Tv`e~pJ7k3<4Um2$s#v7;FK zv(0AS;XZ%Z&~h>18ihOQ`Y9zhaskjh0DG)UK8d#(O#`F{a>g8ONXgAEz1;}J8gD8c zq-<1K!Wf_y&y!u=&G=)HSxJd>rs0mQU1AjIoKN%~PrG?lt(rxUL%WQ6)+fA*{TWy~ zPFNpw`#Z=*NQ49wh_J)i(ZLhRbJ;^2K9MzgB*f-SC(5d8cqly8r{h@Bx^I5%Nprx_P{-P z@A!UW)z+Ezp`bVFwjCB_s8h4{45R{4rvD%Pz3~CaDm>Q?U?~{)H3}kiy*VCSj*3*B z`dQq}vyiyR~%9o&WlxnJj?1EvY^4JjXLYC^<4t3caeN_5}m z0g(_Wk(~&W8xSCWm`GWuhFXLr{S|(NwpX3G>vGVydL}nC-%`W!3Sw35i6X9Tm8HA! z??0$4+(b=swEjQyle(7xRo7`8ERU*t2~JR;>zzr-mfEth@2-~)1XFx67*aA3?y!5U zEN|L=5HDs(Bh{Avt`$>WjIOVk)R(}b>tDxvp?GCk(1C1!@ATj%>-uZ9n>0o0IVi!F z*sH700YC4B^R2;NVs!ldZ6J!A;!<+zgAha->{W5kE}^- zlA~1Stv$7W>IAqV>OqwhLxEhwJ(FiIiJaS+{E^iQ8p2@QerlULF3fuCA==w*Z2{;5 zw650Ss|2K672%KcGT06GTdKl!IsEG0*<<(=ICM!+m0|#0u_el^HOg@fuoeWD0>Wd& z43Ze(q`e4*XJ-uIB;U#JG*1WjgZQz3c4t$dSF4+>lJC#lfhj5h@;>*1pax!d@zjD^N$lePZ21unew5ns=7n2Yuw5;ySAA_ zOPj%ejt`uhhdh`}CeHzD51AaS?;=>(S8J%Nxc@u?VY%xnUpIgY27a|4LYe#gAc1sL zHuJ@yF(;!4E+>v_0l0t2T{xKhyr6s-8Fc zX9END?Qqu0zp2`^t=mj~>dqLBoe!*X8d~aXcL*)+Sz@)PW2(G+{HJMb8cpb zd$U(gQA2B9GFpbiO4OYs@c&>^eeu|kmeM-mrBdip)foET znGae;WB#tM9N(_96J^oPXdY7ZSqDY61-U3yhGA4`=B#&gWW4encY5DIv`}z{>~pZ z6}9vCK#if!6JB(?mFYXokI^p^SNHkEp4k3HtWd{xC$>lz>N6R>L>+m8yD&XJQ@Q{n zh*4N$kHo_esUD|DfsP|D)-THY(!NR9@ekg_wZv9&S0F4(GYod~L9y(;0h9X@Br$Kw A<^TWy diff --git a/test_fixtures/masp_proofs/D39FEE41A59DA80C4DBCAFC36E7B62D6F3F03E1332D2B25890911CE8375D1280.bin b/test_fixtures/masp_proofs/D39FEE41A59DA80C4DBCAFC36E7B62D6F3F03E1332D2B25890911CE8375D1280.bin new file mode 100644 index 0000000000000000000000000000000000000000..225fcb8ab7de33df91e9dad4f24d3fca2e59347b GIT binary patch literal 6393 zcmeI0bx>T}mWS!aX{6C$2?q#HAh-qyPSD^Mf;Pc5xLau4A%WloC&3zbcXziWGz1b{ z!`#ff_tm_as>#g!J9kx`+Ur#9vwwT-I`yr!*WTSf4CN04{qbb^S6J=NXF47)+Lp~E ze`(Q#4U<)Vm4C#A)C1^8RKtr*e$7NdX&x%M<&ud>GaS*p+UU`pCVPce527j+eFj&) zu5__(eX_z*jnBoD+QGXjZZXJ40@fE$;@tZ~>whEi52-&kcEaWv2+drrM^vZcFW41L z`Ca_}NbBeYePD+?O<7HSZuQTYme}2CsMy6ZyUN-#(2y7nceWvgd%H0l=!% z<&g8f0cb$@jw0~Gkh?|odN2OS^!JsHA1k@)clba#>17?dpETDA$<{SY0)?B3R;It-edoz>z?HoHxl3aWjXD5S@jUHE6Ac6;oIa6V8LY?`j z$1Po@QQEbuT-`v5p0eSBnuMoPHRC}E6v*CJiJVe*4w`C1{Y4k~Ck70PL$nq~qI^#Hgl{VO)R zSnZoH2AAE1=LCFfg@X24Dn8njrbT>Rc`!hsbN=vnx4j@2A(1c3AE8I+n}T~>X*dOf`{8M^1`Np0i?<%<|GwN|_b zrUe=VJqPOL>}-V86Gelwy?QJ5KxfUVRF)EpZY24>#kzp7b&vH^g|7oGffQS%4uu|& zMTZV$6N+xK97?K=b_5vvkM6%|+?6-v3wMBVkmh8xFi3tej zQ@$$csoh{Ov87hIeulChm4ETs2$my<=Ofq0NSa>7u%wnICh;iz?mqA@g#9OK|Eu$B9{6`yBft4G>-;(VF6n$l z{a2v}vfR*nZ&R^U(b`tEErxn&pmpD8Z#BZ`iy4F%$F=~ z=Xp{{#La1!({W@(MG2g82lmL0P_wBOsM0AN4=^p@_Y$thsP;(O7)ZLFtup{QVlMAV z(_+i1^SS-Ye{k?g-7M|qaKG6bzIpiVv2wN)z!0NaVl-=OS*0-QpYS+G^W<)uBf{;f zP`TVq5YO389+1u6q~Fwa&4&;kTUIubHT}Gj3;9A9=u7Td5I4#h7*^`%A!cw~ z#g5NWfKnsJ52>~Syzgk^SvZ)E2jh)@2Q=L?u79uVN|wHw56+~gln0J!@F>{f$OOmV z)amTYe{?PK5+G$?{hbcD%pWhaB7eF~Q?UNcmNM>zpMTndZz2923b~rRH+u#B*`ERa zJ^cSX0q`GT<1iI6et3Pi`|AXLC0rEH?|#q!_LA2aZ!yX@j_M{3F;6)V;hDGKtBK*p zSSn@$bDZr7;c%SRmV9q3hgBG+_T}a@eO9Z^a(|{^_ztQh9haGsb(J!c$wAN3B!Bs3mE|#+iY()Gbi!s0sRF8h9Prl7iR*S z?w1tVbyfzJA)mKftJ)ybCg$&)P}02ReZl4Y8y5`&mPkl|0H)uv!zLSW4Uw@U zOYhbbjiBGst4~|np;9^HgzmlFB=2breQ^|;#psK91%5_hC6WS{;xCi5gwo~*>c>E zbwyc^OuPppWm>;R)!&KYx+_v{Bd7jS$cmt9y^dT=N{09lEH{pEx`EGE=ot(IkQwHU zn^|$sJ(81^)#=UjC1y_!<(9gFqym^MMK}E0c zZPapHv5UJsbF9Z`-xeNWJlJu>8KFy+n6eWUW&1`UV7hlnWx~yn2~yI05h~cjl_LmA z>4;o1QAWDq=7q9{3q@!%&)x<1)hy@J5A1NC-z$QpQQA|ffu+4wbLi!(WaZTI6Gzph zrx&kHrZMD)SAz#2{0*vm;r<8JXg6~Vz4*$^EEH?_M^c0f;}QPEk82P(*-kNfm}{I( zW=y?HGBYAvan7OC3aJl3tO_Kz_u8#p+H9^ACi23u`!_mrkQ)Lt)8_n{UqqSYE8+Dp ze{}_BhKQS*%*^L0jDr10=2IZT+e=(B!*2t^?jW5ub$%f^C7NbB3)tzWFCcV=-Vs%n@|RH z!4u4lN|~kr^HId)CLbN;(7ME!&+sdalb6&^+AN#MHMP$_s`s!*hq_oc{L7gWsn!CR zh8|{kAhLKK5g6drC3}32>C(wZv+DNK@ii{;Hq~FSA+}ubM{+<>kY2YU+NZoBO6wiCs~D? z4HQXeQR6fOf7)Y$^3tghmA>fL#DMaUm-U2*6FtsjU*KsG?c3!ILm!lVTXqsfzzO}7 zqB0Xn`{c_RIy>+mJ6nE3U&q|7ag zXdAp}h>U+oe(=1R^d6B|YtQq3A1YQmByZIOq%l*nq-B$4udHQw!%N@pzJsPNhv zN%HLs{^^3ijgNa`%Zj66p$4|tAA(x-(?{*S2Qwv83P{9sJf4Ha@SrT4&f(orC!mxdZ=#^K4jHT3 zI?K}Bc@lvEs?@>ffv0p+h|HxHRfrMvB@FI<(1yLhEPBCPMDLdMLDgIfg=y_^@M}{N zCRqiv3g?CJ2zRMi_QIX%6DQgnUSGomn1hRk;M)B8g9EXNYc=G#$7{OqeM;*=d|_63 zeRyI&7eB3+skzB|c;IeRv8N|Wx$IfNo6{HP42+~@8-!^&nIj@qFlZd?!MZhW$JYch zv=Fdqc2d06?m+h>IFa_FP{t36^%km2@$R)b2^t`5b#9DpKsSSBjDJWG9O?M}`4NN0 zLgiqX10kZ``(YHD%z||@$MZX=;{Q0${Z$+Mu7CNvHe}WCE_7{9=b@QIkAi7m`nc3A z6`6@YgBt3a0kg1F@bdNQEd0iai8dx^E`wjhWY`3jhBnN&Zn=4$>N#UQ?i#-h(LQ5&q> z8eP^*XCk9Cqj+ucL|dBYY#nJmAem6YzJI<5S*Lpu5anI0Bd0gg%f5Je%`hCxxFoE^ zj)D5lC%#pPTRFE>O4)=cvna2$+`Zn1qx(F{DApwg$JL&UV`e*BtnlZBo`asc4DLdc zD;mx)o_2{bVV9S42PEc(i8~L}>JRHf?$25speFEZ4o??qm2^f@)@3Oq2BE}_+K+@e zeMcjA8`NI73PJqzI8XyCotXw3o@1pag(OlMPap8tDMfm0xRzHdHd~m_o6olrrRkqy zar%R#IA#{&qnFvUG(nQS2uDIKBT`A>>~;GVabC(eBBY92U`Ot6(3oxHc#5PNBt& zw`<|qsP}2zgyDVAQ==5_g&xgXJeANvo4LK}XNzt>_Unv;^_Aes2|Pqwht5HjX!lW>QRd?C!W6p0$n zWMI|qnTYFM`6QxcZIL#b%)8Gv`9(J7QAHXl;Y@|ta-QvJ5057vKI|6paT^ikGhdF` zne$< za?KF?z^9)-05)H7n5a6yK3~em&UsI2SC9v1Hs0t4foqtDs}+7X1|~4KWv$C43)p|_ z9-w%xSmYpUGAW~Hk9!3=dio@llm9WfQCH{f0^t!0f!vlL67F7pX%%UGiyqzzev49w z2^wN+_*U-U9N176nZ%ig`H9vwD%;>O`(|#*d|n{&&2ipWj7J)sPI3JO=Ai%Br25bP KU+;gllKu@8+~%$T literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/E1D883F9C9E7FD5C51D39AE1809BC3BBACE79DF98801EB8154EA1904597854A1.bin b/test_fixtures/masp_proofs/E1D883F9C9E7FD5C51D39AE1809BC3BBACE79DF98801EB8154EA1904597854A1.bin index b6ab8d50e05688560075dda36c690264ab9d94c9..88df400e5e02d4d68e7349427443ac95733a48f9 100644 GIT binary patch delta 919 zcmV;I18DrmB*!GMxCkJ)BK+Q=$S>=P^B%|>{eyP%4Gn+22?9X!VV;98usW4F=IE%45R{4r+2fzaB}ko#Wx!W`X--=nU0MR^2k!AF=P%V zcDg)neh>g2B@o%F?1mucobk|hy&@upRWc|9JS}S-`jvs?j%;>5X6$>@2HQ%>MqKF8 z0Fe|;xvX&5$iCoxwTTodouId4fJXEj{XW3J3*}m+>DP0*xs)AeO6$@^-?2fIn2Lvw$W4r-KVd?#y{2Bl34y{fL{`Fxh)Bes4;atvCV{gf2_bA z>(O@j`1=PL2A@IdufvPQrGp_%Lkg2fE$+BtR*GcmiU;|TT(x)Lapro=1K7rWO_%_~ zu@A?n7VqTKN`gFxC@k97b)f)zvm$D&AXmC0pr}U08=XQ0ZS|MZVK7U&kHg6UPY>U@ z3`W#Oe1C>m>6Le0-b&dK#)w3VMO{bo6*dDN_%0>dy!2tg=`>YjK}vW~K3tL=`RRJq ttEu7~uWu99CEwEFr=Um?IIYYv^J-biF9?irHPu1KgU}rAU&0dmR+E$WYu+3K4*fGjQA1F0nd$6zv)Ntc0I~98x5FG*A@B=VH5$ye-kl&G2}i%N2yUq7*h3e>r9v>j~a{- zWvv9`Kv4-C$YvM0%=}#?G$X}27v3&?e!`q`_BP0Sa`Xqx#JYb#{ud0f>AI}EEU@QB znlPWHC4BeP+W^a~qLbXs(%mJz&H)FNk48%ZL?1TWcZyy-fe8bs+-7x^y+JyhS+zTp ze_IH&H(>EK!A|4?u4&u_Sh9Pw(nrfFpCh5jyrIms?zuE-#--)Q0qZEZ52k--U{}zB zbGY?>Q>3fi38)A|!h|pTFCxL``d}4Z+|Q}%fWNjsw33=QgW|B;Qu60Qe*r&sjKaK*m}cXYU)3e-BH?fz zhBEi)SvzU#E05Ds^edDH@`WsfXWWFCMw)(1|E@`Jhyt_k=l2`=CIpis5+vG?zZn1k diff --git a/test_fixtures/masp_proofs/D1F174D8596E8C1DA892DDC23D322056C14747EAC3FB1625F0A86957E00ED109.bin b/test_fixtures/masp_proofs/E750A2B670666F8788E71B3F685E298FEBBEA9975D764A6A9E2F98E10810859D.bin similarity index 63% rename from test_fixtures/masp_proofs/D1F174D8596E8C1DA892DDC23D322056C14747EAC3FB1625F0A86957E00ED109.bin rename to test_fixtures/masp_proofs/E750A2B670666F8788E71B3F685E298FEBBEA9975D764A6A9E2F98E10810859D.bin index f459f6dea66ef36a1bf2917fa2d836e6c349aaf5..f3e3c17005d600a21994b48e349410437f96da22 100644 GIT binary patch delta 1506 zcmai!`8yK~0LO>OvC&-Hq_!}Hp<$F;LNw=`l?gR1XL5xMB}^9e!DW6OmR2(1~Ht20Zp zyoR2-aT!-w0ny2!w6)b%2}Xg5<@5FY5JJ>?F*sFR0Z8o=bwT_ty78D;v+!>VLYq{C zhNuvslZ~DdM#7eP3l$$LbK-&X+UEY2pRh(vdUNcy)vr|M@ve{`C=G3CjO$k$4t(G( z&*NxYXAZ&Cw&J~?`c8n0l)%x{vgR6fNJ_<0>E4ceYs76eM$da(Ke7q6wd=%bANaw= zeR!jS{&~UX)=vW5_XN2=AxmtCm9(C`4_U?H-ZA13B539shr4a>MOH|texa3!7p`;8G~NIrgh}H&j5!8a@{@cqAixbP$|6iSq{qd) zP+Pdm%#OH?W~6SXHlZ#$PbigJ@h!MX4dDVLg3-JF8UMjwBWLu-=gn607ZLb==U1uz zdv|uBKeUvVC0M+xwu!zoiYCDfvnS*i;f?oX{&lL_t9#CSu>2|f(U*zp){-#swworo zX6kDDZ{Di&6f7NHx*xdi$u>D@XQ)SN(E)0-gK#kWS9z2~&akyIJH|R9vtDv!g-hPf z?{&D-jH+JH6AS`qy^yd&rkLdQ6=T5v51T{-K8$pFEPDUC)ubx>k6ur}GU3hJ%^IIO zv=4^0ugPIS2XV)%iSH7OCJ-Z1pR>-}EmNSq`t_AO7&}63&SE*-W4EKz^n|h_9O=!B zR+sZ^3_Ls1X!6j-%Eo&u1k@$11_`Cq&|sp=ZqT#wq!s0E7j`^-GA=Q*Z^AQSeDeTSm z;Ne(v{W8Y;0e`V&4Wi&1_1NxAqFQ^VLE3uRPcCuz+6iM`o^R$$$9?V3?6Ach3v0Zh zG8t^q>=iR54KA_-COK``SY<9wQjoLVLx~Zg!U{Ze2HiLD)A+eQoerjPnn-@+;ng`l zs4|-zg|e@EckHNm78u_fA5-1Xw0mm}5_y&3SOn88!PKc6& z)(%K>F(FOB)5H)bAYTpQ>+8-93-=AnV)gMB!Did`1_9r! zQ`GsBJGFPGlx^nxCzDg03Qry3|7}gj-02%^`TjCo{gGINR?XA{(>O+5bZ$pvkJgA_ ze#|^IR{n6dibeV^n)Lk4zVvZ%orH4vJvjiF<{Hr@3N8b#8XUZlyVT5s8R~H9NFl)B^X7?nHKvxVe zD;w_^kZ72hf-c!d2*)a6G7Am1Bh_Y>r2=uM7t5uJsD*aMlHKMbzzo$fK-4g9ee?4{ z?Zj$-W-${WmC_?QN>q4Pn-!`{Vxk4!j|_pcmhJ{66hgG$#h__c3?DyFPM859*hdXP N)Gc{6agkqV{tx6o)T;mh delta 1513 zcmai!dpHvc0L9H?aXpfGtuk+`;pPz&7t?lyi#&H_guKn8$fI%%<5HT`V)KZ+GGb_E zAw^!9aZQN4F4ly+N?2a^e&6ly+wY(A=Q-#5&UeaSWiZ|4!~fv>4uJR9<3<-sHIKeo z*5_(uif46X+dVLz-LX#BQH@G8cDS$GuAcH+srlkfN!nAL@*(Rj8F>R|t1vo&92eI{ z;AoQQ!fmNv>N;q00Hh$&fX8;z?7J&%g3G)Vv~4GVAUiLd+EBJlAimL zwVxp9QgtKSt3plq(K|KRO`rPl2?w$nLOcCXK?y*t2Py&tiLF8yr5_p7jDU3hAI3{W za_TyWasU(!Edu99L=LB?p=Fiiw$bhO3bzKbIb=<_0YmXf;QrUNb?+9B_{D>?l9@uP zZQgpySTjXqfc}G#R(B8^ zYn^2>Y&_$}iR#Dg+oo|wBFIRKKX@gBs5Kht=)avTJF%vN=34>cjF^gK%iH{zW9*nE=`iTPkP?!cS83^uW*J|E9 z>!yuA4$O6Q{~&7#9kp$Zt!~0$E;jT1|EzJw4*1@o5buI^zP&#<`?V8wd+QNoXmuwutq9T zH95B78Ez~Tirg+s&n-aEU|Rj*;8rUs`1mVx!tA%Qov4yuQX0m3<+)|{Aqd|V7S0wo zN|0l2j=XHD(=}pA!=r)OmG9f$3OA7`ncl72J6}@5CyOf*Y;n}!^cLm8UN188dK4GE;A{z_K3xq` zokmZDCrx*`ia2BS-9|up>!d&_*esR<_%$XAv2yY}BN=*t00|@)<2tQ~d&TdM zbm&cT%~x@zqy=isw)zJ?=q>{51Hmm9eFQn zoFB?`U!~*=%66%)MjBshO8(n~j2b0yU&pFTgtdrC*nf0oy_zTLg#=qWzYIF~l&95J z>R+FAIm6x%Fx9(`o6@PQH^>V2 z1TN`?AX(WT+}bb>!N4%*CFL|u7A9J^JuAjv;7Gp2L}sDAnbhyM_BVS*dvfaXAi^2u zyKjqw~Eworf*RTqEpIy{{SjJ0{UhJoC_IHy52KC#tLNw+ywW*e4aW)jP7NLDw%4I5` T|0e*kM(Bhj;QN>Jf7gEiPfOlP diff --git a/test_fixtures/masp_proofs/EA7A88B1429EFFF0AE7167F6FBEF52D368B771AD525817E722EA3E12B0A96971.bin b/test_fixtures/masp_proofs/EA7A88B1429EFFF0AE7167F6FBEF52D368B771AD525817E722EA3E12B0A96971.bin index 7695d29496711e756e0726dc9bb3e6812d5b9955..4ff441e5c6842e2b10961cd45d32e7c4dba496ec 100644 GIT binary patch delta 1356 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 OWmpyg*uMdjwjC_RgPFMi diff --git a/test_fixtures/masp_proofs/EF7D15FBFB9CC557CC8F9D4D18F7858007C4DA521F8E3BF250A46E9342178EEB.bin b/test_fixtures/masp_proofs/EF7D15FBFB9CC557CC8F9D4D18F7858007C4DA521F8E3BF250A46E9342178EEB.bin index ee5646add2fef586edea8b836a6b5843838d51f1..477c4a73d3460e684891c0c014f3f79594596aad 100644 GIT binary patch delta 1061 zcmV+=1ls$YESxN`T?-(n#2YFH1`pEF5RZkv(6O^3~rYVWhO*@PQ0u8MqA66#BOuId$#$MRI~pJ^a3C==)FPGtw#QEl;S|$khF=zK9M5n+FR993$02b4`(m4 z6Axtrf2PyI!%f^q&MVSM8bKS8c@+g(BjqTltYCIWeO5dlQNb8J?z8=~UJ}d0U{R0_ z47pkWpk$b@u9KKPm9^l2h>ftDbv>91YCLhKU=jiOvDajrmuXhbz=%o;hwNM)`$;A#rq(tBr@{j?6(P4a#y7kt zW;289mfL>H6Vk!-9VibKEQ+0s?bIv3AatMcBg6iN z+IusMBJS8D1m5Z5BuJ3Y%45f4r^6s2r6s)liG(uB_4-X(Sch>cC_LtRs`x6|&!1 zfehP#V7Xn@+>Nshx3LMxb-8RDvV%4&Qt%c()bqTZJ;-ivgiTeC_(M? zJ{U9&5h?qA)ML>FUa)u^ig5(@J83nbR6+{nLs|eWcxQ+48KouW2r)Qhe~%CbT&V;W zCY#;ND3EgnhUef0JV9ZOQYTiLtErmJD;z{W<}oE`J#i zA7u29i=dGoLGe1ZaOORwGhZV3(4l#^Bb|v}{BP!7d2d-@pzdwcwllT=Rp_}n8 delta 1061 zcmV+=1ls$YESxN`T?-)Aak08o`{Z+(e3>Sm&yv6tHhVzI0xZHU-Q>=3DoGqgs;f)Pw*h{F zkqsgVMYemZ-EL}|S+oBO^a3E%JvxDF-{QVHA#GuccWX;q5ZvkCyr35eimqvlw>O)! z6Axtrf3=)0n{QyS7k`6wW84|o04O#asyiTv zz>_3*e~s~yRpD0ZvqKy`rE+EGSkpTz5*(CLF5Q0znMJj=vW@x?sL%2qqCkA$eirFP z*$eBbHu%5?qKsL(5o*iV+hGTtcKLo;--jw>e-R*Qpv=>|dF$1s&a}8(!>gG5_>5n5 zva$d%SVwE2$c!r{7Fa58D}Y#NuSZ0D#&m%l$`Q5%0~j$Ju)^D97~ zAMc)3l5e0U?;bm{J9@)JA~K)d)H>Ezdz%#T0Ct_Bo8j)JU%fj*9ke9pgnGvrFr>fh zf3EBj}NEVB`{y@WW9&-v>oJ6i3LhwF{ zpK+7Hx7*9!I*KvXL@&^LOz;|t{fiBy2rM(u!<481)nQd=jJ0z}gNq3ZkTf z{^)CO&R*;m=QM9jBmZd+H&(al`oN#j|(@2o|W7VY3Hi1#F+!bkqVE+!0zoq71+Q8yxRz?0u80Q0qc&s!oXe|1s+rab}s{U>xw^72cu-`z}V&ullT=RNFfv7 diff --git a/test_fixtures/masp_proofs/F4F0D829373DDA78336CF39EBA3356453E412F862D949ABE9671C24A3903909E.bin b/test_fixtures/masp_proofs/F4F0D829373DDA78336CF39EBA3356453E412F862D949ABE9671C24A3903909E.bin index 77bf2689797d5f9eb972b0faae98d212fc3ae8b4..9b234f0f762187410b9602adc4f2976e17c8b3cc 100644 GIT binary patch delta 308 zcmV-40n7gV5B(3YoC6@UqFsv=yRF+5e`=mtyF{)D?4MbHm;RiT5>nS9<3`G}yaOcz zf1^s@&|b88-z~<(c5<|`jcRt@AFkUY;NB|rV#E334g^K08Kl<-HS1g=@H^y#X0c4d z;YkCrkZnLmQw>LmqhP!lx7c!RakWMoWlp|7N_Wdtxg5glTG036p;o%99a5kZbc9e|4T@ah;3sn*l^Kwn`4_7sBX8}`lup3K zH~uXO*UmM8OCq7&xc|lIoB}cT+b-S{J0M+5ZTy^=PP;n{kko*YDA*+@3GP-D0&oJ8 G;RhV`X_rv| delta 308 zcmV-40n7gV5B(3YoC6>Qfr!<^nw&f+n`iI~A2z9{rrrT@b0=J73Bf@=CYcGdyaOcz ze~V%fK;iuJS}3GkG5LM9l$HrrS;mM@WW?GCDz!`d5m4A7*{%#NT|nS`K| za7{2>C%9{U^>Hiwn3vd&qjOeJJxm2*<-}-yd96mnDawB7C5SFi)vW3nKn-OJ4ffY@ zh7LZDufU6q*&L<@lpZ<4+TEX&M}gu`e;84&$;hHio14BdvxNmrZY!gxudzyAP7HCe zyOHuG!m^R?Z~~k+!(>xm1TFg$cK>$dA+Fz_&GvY756!A+Q}w!n2Hm-Lvj5^miL54W z?d~7S(F@~hY;|o#(MuBdIZ@}k=5)tEsWZv|4ai$)iJ0uf@C0^aOmIa>sLo?i6=}OAFhxyaOcz zf1-ofiGxYcNW0Hn&8dWcIeJR>YuxRV zAJB_7MRXe5jfTcJmyOFT8ACC^MDF_`CdkrNu{Xr*hIq>}5gXNU;9sF}5D$S8V?T^P zsb#2bI+{|{Kz&!=^=WHAYS#Ro`JYBmevGVln&L4$#E*H=>XT3LemDa&}gT5t;h zPffZ+@$RQs<74na{3BeWYHfV?SST@a6ubeRg*z-fekYUNC>B5!A{yQcBZ7Mp0F^{n zL`EInL=XM@(K)!iWT>crgx@bpK*fL1BT`rgrxxliRd;b)kCg&RQea^vdD`pX0#5;x G;RhT&<&f|I delta 308 zcmV-40n7gV5B(3YoC6@w%3jtMFDQC88hM@1wn(cRGy(958aP1Z;9;hC^T@KZyaOcz zf1#i4djSubhcR{62-%OlN13>ngBvJ+Eybn|;f$;fPZfj2x<2!eb#ZOTR&ywCZI)(~ zvJNPLDH~faSNX8Tb7U8+K9i8;%^gA|$ZDUaU!PZ(zby>f3((n#f)v?Ff0@sj zi}~T&r3c197_K%Hr4AKaBC+KBM5MDmf6Npfh;;xvnYdG(-oPq8P@R~_%h)#3u=hQzSz?jLAJl?Ez)|enb0PB1h za{yZZ3=0JNmOR+kr=|S{v0eOp^Wj$0lOR91w~s19B{@joPW3rre(~S-KR<;40;3C) G;RhVA-;=HY