From 73ee43066f441b18c62de4bfba9f2acea1d79628 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Wed, 4 May 2022 12:40:23 -0600 Subject: [PATCH 01/77] port a select subset of the changes from mixed transactions for candidate 1.2 (#1909) * port a select subset of the changes from mixed transactions for candidate 1.2 The changes ported here are: * Rename `token_id` to `fee_token_id` in `TxPrefix`. This avoids a breaking change between this and 1.3 in the hashes. * Make `TransactionBuilder::new` take a fee amount instead of a fee token id This also changes te memo builder trait, so that it will be compatible with the burn redemption memo builder which we hope to port next. This also makes `TransactionBuilder` possibly return an error. * Adapt all clients and sdks for `TransactionBuilder::new` changes. * Adapt all tests for this change * Bring the `Amount::new` function which makes the test code nicer. * small change to `TransactionBuilder::get_fee` per Remoun --- android-bindings/src/bindings.rs | 8 +- api/proto/external.proto | 4 +- api/src/convert/tx.rs | 8 +- api/src/convert/tx_prefix.rs | 4 +- consensus/enclave/impl/src/lib.rs | 6 +- consensus/service/src/validators.rs | 48 +++-- fog/distribution/src/main.rs | 16 +- fog/sample-paykit/src/client.rs | 6 +- libmobilecoin/src/transaction.rs | 14 +- mobilecoind/src/payments.rs | 15 +- mobilecoind/src/service.rs | 19 +- transaction/core/src/amount/mod.rs | 7 + transaction/core/src/tx.rs | 13 +- transaction/core/src/validation/validate.rs | 4 +- transaction/core/test-utils/src/lib.rs | 7 +- transaction/std/src/memo_builder/mod.rs | 14 +- .../std/src/memo_builder/rth_memo_builder.rs | 22 ++- transaction/std/src/transaction_builder.rs | 183 +++++++++++------- 18 files changed, 236 insertions(+), 162 deletions(-) diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index f4b66470e9..eca402f6e0 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -48,7 +48,7 @@ use mc_transaction_core::{ ring_signature::KeyImage, tokens::Mob, tx::{Tx, TxOut, TxOutConfirmationNumber, TxOutMembershipProof}, - BlockVersion, CompressedCommitment, MaskedAmount, Token, + Amount, BlockVersion, CompressedCommitment, MaskedAmount, Token, }; use mc_transaction_std::{ @@ -1602,13 +1602,13 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_init_1jni( env.take_rust_field(memo_builder_box, RUST_OBJ_FIELD)?; // FIXME #1595: The token id should be a parameter and not hard coded to Mob // here - let token_id = Mob::ID; + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let tx_builder = TransactionBuilder::new_with_box( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder_box, - ); + )?; Ok(env.set_rust_field(obj, RUST_OBJ_FIELD, tx_builder)?) }) diff --git a/api/proto/external.proto b/api/proto/external.proto index 990057b0be..4f6be024d2 100644 --- a/api/proto/external.proto +++ b/api/proto/external.proto @@ -242,8 +242,8 @@ message TxPrefix { // The block index at which this transaction is no longer valid. uint64 tombstone_block = 4; - // Token id for this transaction - fixed64 token_id = 5; + // Token id for the fee for this transaction + fixed64 fee_token_id = 5; } message RingMLSAG { diff --git a/api/src/convert/tx.rs b/api/src/convert/tx.rs index 488f548a88..2490907e74 100644 --- a/api/src/convert/tx.rs +++ b/api/src/convert/tx.rs @@ -34,7 +34,7 @@ mod tests { onetime_keys::recover_onetime_private_key, tokens::Mob, tx::{Tx, TxOut, TxOutMembershipProof}, - BlockVersion, Token, + Amount, BlockVersion, Token, }; use mc_transaction_core_test_utils::MockFogResolver; use mc_transaction_std::{EmptyMemoBuilder, InputCredentials, TransactionBuilder}; @@ -70,12 +70,14 @@ mod tests { ) }; + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); let ring: Vec = minted_outputs.clone(); let public_key = RistrettoPublic::try_from(&minted_outputs[0].public_key).unwrap(); diff --git a/api/src/convert/tx_prefix.rs b/api/src/convert/tx_prefix.rs index 2d6a4e0f44..0815686e2a 100644 --- a/api/src/convert/tx_prefix.rs +++ b/api/src/convert/tx_prefix.rs @@ -18,7 +18,7 @@ impl From<&tx::TxPrefix> for external::TxPrefix { tx_prefix.set_fee(source.fee); - tx_prefix.set_token_id(source.token_id); + tx_prefix.set_fee_token_id(source.fee_token_id); tx_prefix.set_tombstone_block(source.tombstone_block); @@ -47,7 +47,7 @@ impl TryFrom<&external::TxPrefix> for tx::TxPrefix { inputs, outputs, fee: source.get_fee(), - token_id: source.get_token_id(), + fee_token_id: source.get_fee_token_id(), tombstone_block: source.get_tombstone_block(), }; Ok(tx_prefix) diff --git a/consensus/enclave/impl/src/lib.rs b/consensus/enclave/impl/src/lib.rs index 1975702b90..4719d0dc93 100644 --- a/consensus/enclave/impl/src/lib.rs +++ b/consensus/enclave/impl/src/lib.rs @@ -236,7 +236,7 @@ impl SgxConsensusEnclave { // We need to make sure all transactions are valid. We also ensure they all // point at the same root membership element. for (tx, proofs) in transactions_with_proofs.iter() { - let token_id = TokenId::from(tx.prefix.token_id); + let token_id = TokenId::from(tx.prefix.fee_token_id); let minimum_fee = ct_min_fees .get(&token_id) @@ -685,7 +685,7 @@ impl ConsensusEnclave for SgxConsensusEnclave { .decrypt_bytes(locally_encrypted_tx.0)?; let tx: Tx = mc_util_serial::decode(&decrypted_bytes)?; - let token_id = TokenId::from(tx.prefix.token_id); + let token_id = TokenId::from(tx.prefix.fee_token_id); // Validate. let mut csprng = McRng::default(); @@ -782,7 +782,7 @@ impl ConsensusEnclave for SgxConsensusEnclave { // Compute the total fees for each known token id, for tx's in this block. let mut total_fees: CtTokenMap = ct_min_fee_map.keys().cloned().collect(); for tx in transactions.iter() { - let token_id = TokenId::from(tx.prefix.token_id); + let token_id = TokenId::from(tx.prefix.fee_token_id); total_fees.add(&token_id, tx.prefix.fee as u128); } diff --git a/consensus/service/src/validators.rs b/consensus/service/src/validators.rs index 77eabf9686..7b8556149f 100644 --- a/consensus/service/src/validators.rs +++ b/consensus/service/src/validators.rs @@ -576,12 +576,14 @@ mod combine_tests { ) .unwrap(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.add_input(input_credentials); transaction_builder.set_fee(0).unwrap(); transaction_builder @@ -634,12 +636,14 @@ mod combine_tests { // Step 2: Create a transaction that sends the full value of `tx_out` to // `recipient_account`. + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); // Create InputCredentials to spend the TxOut. let onetime_private_key = recover_onetime_private_key( @@ -735,12 +739,14 @@ mod combine_tests { ) .unwrap(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.add_input(input_credentials); transaction_builder.set_fee(0).unwrap(); transaction_builder @@ -772,12 +778,14 @@ mod combine_tests { ) .unwrap(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.add_input(input_credentials); transaction_builder.set_fee(0).unwrap(); transaction_builder @@ -835,12 +843,14 @@ mod combine_tests { ) .unwrap(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.add_input(input_credentials); transaction_builder.set_fee(0).unwrap(); transaction_builder @@ -928,12 +938,14 @@ mod combine_tests { ) .unwrap(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.add_input(input_credentials); transaction_builder.set_fee(0).unwrap(); transaction_builder @@ -966,12 +978,14 @@ mod combine_tests { ) .unwrap(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.add_input(input_credentials); transaction_builder.set_fee(0).unwrap(); transaction_builder @@ -1030,12 +1044,14 @@ mod combine_tests { ) .unwrap(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( block_version, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.add_input(input_credentials); transaction_builder.set_fee(0).unwrap(); transaction_builder diff --git a/fog/distribution/src/main.rs b/fog/distribution/src/main.rs index 5d3424e757..02c348fb40 100755 --- a/fog/distribution/src/main.rs +++ b/fog/distribution/src/main.rs @@ -712,20 +712,18 @@ fn build_tx( let block_version = BlockVersion::try_from(BLOCK_VERSION.load(Ordering::SeqCst)) .expect("Unsupported block version"); - // Use token id for first spendable tx out - let token_id = spendable_txouts.first().unwrap().amount.token_id; + // FIXME: This needs to be the fee for the current token, not MOB. + // However, bootstrapping non MOB tokens is not supported right now. + let fee_amount = Amount::new(MOB_FEE.load(Ordering::SeqCst), Mob::ID); // Create tx_builder. let mut tx_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver, EmptyMemoBuilder::default(), - ); - - // FIXME: This needs to be the fee for the current token, not MOB. - // However, bootstrapping non MOB tokens is not supported right now. - tx_builder.set_fee(MOB_FEE.load(Ordering::SeqCst)).unwrap(); + ) + .unwrap(); // Unzip each vec of tuples into a tuple of vecs. let mut rings_and_proofs: Vec<(Vec, Vec)> = rings @@ -804,7 +802,7 @@ fn build_tx( // Add ouputs for (i, (utxo, _proof)) in utxos_with_proofs.iter().enumerate() { - if utxo.amount.token_id == token_id { + if utxo.amount.token_id == Mob::ID { let mut value = utxo.amount.value; // Use the first input to pay for the fee. if i == 0 { diff --git a/fog/sample-paykit/src/client.rs b/fog/sample-paykit/src/client.rs index 2b6ab151fd..d915839d36 100644 --- a/fog/sample-paykit/src/client.rs +++ b/fog/sample-paykit/src/client.rs @@ -606,14 +606,14 @@ fn build_transaction_helper( memo_builder.set_sender_credential(SenderMemoCredential::from(source_account_key)); memo_builder.enable_destination_memo(); - TransactionBuilder::new(block_version, amount.token_id, fog_resolver, memo_builder) + let fee_amount = Amount::new(fee, amount.token_id); + TransactionBuilder::new(block_version, fee_amount, fog_resolver, memo_builder)? }; - tx_builder.set_fee(fee)?; let input_amount = inputs .iter() .fold(0, |acc, (txo, _)| acc + txo.amount.value); - let fee = tx_builder.get_fee(); + let fee = tx_builder.get_fee().value; if (amount.value + fee) > input_amount { return Err(Error::InsufficientFunds); } diff --git a/libmobilecoin/src/transaction.rs b/libmobilecoin/src/transaction.rs index 75e1fb2228..747aaf4a7d 100644 --- a/libmobilecoin/src/transaction.rs +++ b/libmobilecoin/src/transaction.rs @@ -19,7 +19,7 @@ use mc_transaction_core::{ ring_signature::KeyImage, tokens::Mob, tx::{TxOut, TxOutConfirmationNumber, TxOutMembershipProof}, - BlockVersion, CompressedCommitment, EncryptedMemo, MaskedAmount, Token, + Amount, BlockVersion, CompressedCommitment, EncryptedMemo, MaskedAmount, Token, }; use mc_transaction_std::{ @@ -373,19 +373,17 @@ pub extern "C" fn mc_transaction_builder_create( // version that fog ledger told us about, or that we got from ledger-db //let block_version = BlockVersion::ZERO; - // TODO #1596: Support token id other than Mob - let token_id = Mob::ID; + // TODO #1596: Support token id other than Mob (but not in this release) + let fee_amount = Amount::new(fee, Mob::ID); let mut transaction_builder = TransactionBuilder::new_with_box( block_version, - token_id, + fee_amount, fog_resolver, memo_builder_box, - ); + ) + .expect("failure not expected"); - transaction_builder - .set_fee(fee) - .expect("failure not expected"); transaction_builder.set_tombstone_block(tombstone_block); Some(transaction_builder) }) diff --git a/mobilecoind/src/payments.rs b/mobilecoind/src/payments.rs index 5e0d6ea46f..6424c3fd50 100644 --- a/mobilecoind/src/payments.rs +++ b/mobilecoind/src/payments.rs @@ -21,7 +21,7 @@ use mc_transaction_core::{ onetime_keys::recover_onetime_private_key, ring_signature::KeyImage, tx::{Tx, TxOut, TxOutConfirmationNumber, TxOutMembershipProof}, - BlockIndex, BlockVersion, TokenId, + Amount, BlockIndex, BlockVersion, TokenId, }; use mc_transaction_std::{ ChangeDestination, EmptyMemoBuilder, InputCredentials, TransactionBuilder, @@ -869,17 +869,16 @@ impl, Vec)> = rings @@ -980,7 +979,7 @@ impl input_value { return Err(Error::InsufficientFunds); } - let change = input_value - total_value - tx_builder.get_fee(); + let change = input_value - total_value - tx_builder.get_fee().value; // If we do, add an output for that as well. // TODO: Should the exchange write destination memos? diff --git a/mobilecoind/src/service.rs b/mobilecoind/src/service.rs index 9d5e97f9ef..1b38e7ea5b 100644 --- a/mobilecoind/src/service.rs +++ b/mobilecoind/src/service.rs @@ -2915,12 +2915,15 @@ mod test { // Insert into database. let monitor_id = mobilecoind_db.add_monitor(&data).unwrap(); + + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( BLOCK_VERSION, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); let (tx_out, tx_confirmation) = transaction_builder .add_output(10, &receiver.subaddress(0), &mut rng) .unwrap(); @@ -5228,12 +5231,14 @@ mod test { let root_id = RootIdentity::from(&root_entropy); let account_key = AccountKey::from(&root_id); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( BLOCK_VERSION, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); let (tx_out, _tx_confirmation) = transaction_builder .add_output( 10, @@ -5340,12 +5345,14 @@ mod test { let key = mnemonic.derive_slip10_key(0); let account_key = AccountKey::from(key); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); let mut transaction_builder = TransactionBuilder::new( BLOCK_VERSION, - Mob::ID, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); let (tx_out, _tx_confirmation) = transaction_builder .add_output( 10, diff --git a/transaction/core/src/amount/mod.rs b/transaction/core/src/amount/mod.rs index 9e4aa453ef..acf4a6bc3c 100644 --- a/transaction/core/src/amount/mod.rs +++ b/transaction/core/src/amount/mod.rs @@ -41,6 +41,13 @@ pub struct Amount { pub token_id: TokenId, } +impl Amount { + /// Create a new amount + pub fn new(value: u64, token_id: TokenId) -> Self { + Self { value, token_id } + } +} + /// A commitment to an amount of MobileCoin or a related token, as it appears on /// the blockchain. This is a "blinded" commitment, and only the sender and /// receiver know the value and token id. diff --git a/transaction/core/src/tx.rs b/transaction/core/src/tx.rs index 60cfb64912..140e0d31bb 100644 --- a/transaction/core/src/tx.rs +++ b/transaction/core/src/tx.rs @@ -166,7 +166,7 @@ pub struct TxPrefix { /// Token id for this transaction #[prost(fixed64, tag = "5")] - pub token_id: u64, + pub fee_token_id: u64, } impl TxPrefix { @@ -181,15 +181,14 @@ impl TxPrefix { pub fn new( inputs: Vec, outputs: Vec, - fee: u64, - token_id: u64, + fee: Amount, tombstone_block: u64, ) -> TxPrefix { TxPrefix { inputs, outputs, - fee, - token_id, + fee: fee.value, + fee_token_id: *fee.token_id, tombstone_block, } } @@ -649,7 +648,7 @@ mod tests { inputs: vec![tx_in], outputs: vec![tx_out], fee: Mob::MINIMUM_FEE, - token_id: *Mob::ID, + fee_token_id: *Mob::ID, tombstone_block: 23, }; @@ -712,7 +711,7 @@ mod tests { inputs: vec![tx_in], outputs: vec![tx_out], fee: Mob::MINIMUM_FEE, - token_id: *Mob::ID, + fee_token_id: *Mob::ID, tombstone_block: 23, }; diff --git a/transaction/core/src/validation/validate.rs b/transaction/core/src/validation/validate.rs index 0e74d16eb3..38c449813d 100644 --- a/transaction/core/src/validation/validate.rs +++ b/transaction/core/src/validation/validate.rs @@ -310,7 +310,7 @@ pub fn validate_signature( &rings, &output_commitments, tx.prefix.fee, - tx.prefix.token_id, + tx.prefix.fee_token_id, rng, ) .map_err(TransactionValidationError::InvalidTransactionSignature) @@ -1169,7 +1169,7 @@ mod tests { for _ in 0..3 { let (mut tx, _ledger) = create_test_tx(BlockVersion::TWO); - tx.prefix.token_id += 1; + tx.prefix.fee_token_id += 1; match validate_signature(BlockVersion::TWO, &tx, &mut rng) { Err(TransactionValidationError::InvalidTransactionSignature(_e)) => {} // Expected. diff --git a/transaction/core/test-utils/src/lib.rs b/transaction/core/test-utils/src/lib.rs index f40f074e8f..d6f8279775 100644 --- a/transaction/core/test-utils/src/lib.rs +++ b/transaction/core/test-utils/src/lib.rs @@ -149,12 +149,15 @@ pub fn create_transaction_with_amount_and_comparer< ) -> Tx { let (sender_amount, _) = tx_out.view_key_match(sender.view_private_key()).unwrap(); + let fee_amount = Amount::new(fee, sender_amount.token_id); + let mut transaction_builder = TransactionBuilder::new( block_version, - sender_amount.token_id, + fee_amount, MockFogResolver::default(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); // The first transaction in the origin block should contain enough outputs to // use as mixins. diff --git a/transaction/std/src/memo_builder/mod.rs b/transaction/std/src/memo_builder/mod.rs index 0b65ba0894..64f09bb8a6 100644 --- a/transaction/std/src/memo_builder/mod.rs +++ b/transaction/std/src/memo_builder/mod.rs @@ -7,7 +7,7 @@ use super::{memo, ChangeDestination}; use core::fmt::Debug; use mc_account_keys::PublicAddress; -use mc_transaction_core::{MemoContext, MemoPayload, NewMemoError}; +use mc_transaction_core::{Amount, MemoContext, MemoPayload, NewMemoError}; mod rth_memo_builder; pub use rth_memo_builder::RTHMemoBuilder; @@ -30,12 +30,12 @@ pub trait MemoBuilder: Debug { /// and gets a chance to report an error, if the fee is too large, or if it /// is being changed too late /// in the process, and memos that are already written would be invalid. - fn set_fee(&mut self, value: u64) -> Result<(), NewMemoError>; + fn set_fee(&mut self, amount: Amount) -> Result<(), NewMemoError>; /// Build a memo for a normal output (to another party). fn make_memo_for_output( &mut self, - value: u64, + amount: Amount, recipient: &PublicAddress, memo_context: MemoContext, ) -> Result; @@ -43,7 +43,7 @@ pub trait MemoBuilder: Debug { /// Build a memo for a change output (to ourselves). fn make_memo_for_change_output( &mut self, - value: u64, + amount: Amount, change_destination: &ChangeDestination, memo_context: MemoContext, ) -> Result; @@ -55,13 +55,13 @@ pub trait MemoBuilder: Debug { pub struct EmptyMemoBuilder; impl MemoBuilder for EmptyMemoBuilder { - fn set_fee(&mut self, _fee: u64) -> Result<(), NewMemoError> { + fn set_fee(&mut self, _amount: Amount) -> Result<(), NewMemoError> { Ok(()) } fn make_memo_for_output( &mut self, - _value: u64, + _amount: Amount, _recipient: &PublicAddress, _memo_context: MemoContext, ) -> Result { @@ -70,7 +70,7 @@ impl MemoBuilder for EmptyMemoBuilder { fn make_memo_for_change_output( &mut self, - _value: u64, + _amount: Amount, _change_destination: &ChangeDestination, _memo_context: MemoContext, ) -> Result { diff --git a/transaction/std/src/memo_builder/rth_memo_builder.rs b/transaction/std/src/memo_builder/rth_memo_builder.rs index df5a978bd7..cf9500c011 100644 --- a/transaction/std/src/memo_builder/rth_memo_builder.rs +++ b/transaction/std/src/memo_builder/rth_memo_builder.rs @@ -14,7 +14,7 @@ use super::{ }; use crate::ChangeDestination; use mc_account_keys::{PublicAddress, ShortAddressHash}; -use mc_transaction_core::{tokens::Mob, MemoContext, MemoPayload, NewMemoError, Token}; +use mc_transaction_core::{tokens::Mob, Amount, MemoContext, MemoPayload, NewMemoError, Token}; /// This memo builder attaches 0x0100 Authenticated Sender Memos to normal /// outputs, and 0x0200 Destination Memos to change outputs. @@ -67,7 +67,7 @@ pub struct RTHMemoBuilder { // Tracks the number of recipients so far num_recipients: u8, // Tracks the fee - fee: u64, + fee: Amount, } impl Default for RTHMemoBuilder { @@ -80,7 +80,7 @@ impl Default for RTHMemoBuilder { last_recipient: Default::default(), total_outlay: 0, num_recipients: 0, - fee: Mob::MINIMUM_FEE, + fee: Amount::new(Mob::MINIMUM_FEE, Mob::ID), } } } @@ -132,7 +132,7 @@ impl RTHMemoBuilder { impl MemoBuilder for RTHMemoBuilder { /// Set the fee - fn set_fee(&mut self, fee: u64) -> Result<(), NewMemoError> { + fn set_fee(&mut self, fee: Amount) -> Result<(), NewMemoError> { if self.wrote_destination_memo { return Err(NewMemoError::FeeAfterChange); } @@ -143,7 +143,7 @@ impl MemoBuilder for RTHMemoBuilder { /// Build a memo for a normal output (to another party). fn make_memo_for_output( &mut self, - value: u64, + amount: Amount, recipient: &PublicAddress, memo_context: MemoContext, ) -> Result { @@ -152,7 +152,7 @@ impl MemoBuilder for RTHMemoBuilder { } self.total_outlay = self .total_outlay - .checked_add(value) + .checked_add(amount.value) .ok_or(NewMemoError::LimitsExceeded("total_outlay"))?; self.num_recipients = self .num_recipients @@ -185,7 +185,7 @@ impl MemoBuilder for RTHMemoBuilder { /// Build a memo for a change output (to ourselves). fn make_memo_for_change_output( &mut self, - _value: u64, + _value: Amount, _change_destination: &ChangeDestination, _memo_context: MemoContext, ) -> Result { @@ -197,9 +197,13 @@ impl MemoBuilder for RTHMemoBuilder { } self.total_outlay = self .total_outlay - .checked_add(self.fee) + .checked_add(self.fee.value) .ok_or(NewMemoError::LimitsExceeded("total_outlay"))?; - match DestinationMemo::new(self.last_recipient.clone(), self.total_outlay, self.fee) { + match DestinationMemo::new( + self.last_recipient.clone(), + self.total_outlay, + self.fee.value, + ) { Ok(mut d_memo) => { self.wrote_destination_memo = true; d_memo.set_num_recipients(self.num_recipients); diff --git a/transaction/std/src/transaction_builder.rs b/transaction/std/src/transaction_builder.rs index 1ef006634b..72ba7f5c0d 100644 --- a/transaction/std/src/transaction_builder.rs +++ b/transaction/std/src/transaction_builder.rs @@ -18,7 +18,6 @@ use mc_transaction_core::{ tokens::Mob, tx::{Tx, TxIn, TxOut, TxOutConfirmationNumber, TxPrefix}, Amount, BlockVersion, CompressedCommitment, MemoContext, MemoPayload, NewMemoError, Token, - TokenId, }; use mc_util_from_random::FromRandom; use rand_core::{CryptoRng, RngCore}; @@ -59,9 +58,7 @@ pub struct TransactionBuilder { /// expires, and can no longer be added to the blockchain tombstone_block: u64, /// The fee paid in connection to this transaction - fee: u64, - /// The token id for this transaction - token_id: TokenId, + fee: Amount, /// The source of validated fog pubkeys used for this transaction fog_resolver: FPR, /// The limit on the tombstone block value imposed pubkey_expiry values in @@ -87,16 +84,11 @@ impl TransactionBuilder { /// transaction pub fn new( block_version: BlockVersion, - token_id: TokenId, + fee: Amount, fog_resolver: FPR, memo_builder: MB, - ) -> Self { - TransactionBuilder::new_with_box( - block_version, - token_id, - fog_resolver, - Box::new(memo_builder), - ) + ) -> Result { + TransactionBuilder::new_with_box(block_version, fee, fog_resolver, Box::new(memo_builder)) } /// Initializes a new TransactionBuilder, using a Box @@ -109,21 +101,21 @@ impl TransactionBuilder { /// transaction pub fn new_with_box( block_version: BlockVersion, - token_id: TokenId, + fee: Amount, fog_resolver: FPR, - memo_builder: Box, - ) -> Self { - TransactionBuilder { + mut memo_builder: Box, + ) -> Result { + memo_builder.set_fee(fee)?; + Ok(TransactionBuilder { block_version, input_credentials: Vec::new(), outputs_and_shared_secrets: Vec::new(), tombstone_block: u64::max_value(), - fee: Mob::MINIMUM_FEE, - token_id, + fee, fog_resolver, fog_tombstone_block_limit: u64::max_value(), memo_builder: Some(memo_builder), - } + }) } /// Add an Input to the transaction. @@ -159,13 +151,19 @@ impl TransactionBuilder { .take() .expect("memo builder is missing, this is a logic error"); let block_version = self.block_version; + let token_id = self.fee.token_id; let result = self.add_output_with_fog_hint_address( value, recipient, recipient, |memo_ctxt| { if block_version.e_memo_feature_is_supported() { - Some(mb.make_memo_for_output(value, recipient, memo_ctxt)).transpose() + Some(mb.make_memo_for_output( + Amount::new(value, token_id), + recipient, + memo_ctxt, + )) + .transpose() } else { Ok(None) } @@ -218,14 +216,19 @@ impl TransactionBuilder { .take() .expect("memo builder is missing, this is a logic error"); let block_version = self.block_version; + let token_id = self.fee.token_id; let result = self.add_output_with_fog_hint_address( value, &change_destination.change_subaddress, &change_destination.primary_address, |memo_ctxt| { if block_version.e_memo_feature_is_supported() { - Some(mb.make_memo_for_change_output(value, change_destination, memo_ctxt)) - .transpose() + Some(mb.make_memo_for_change_output( + Amount::new(value, token_id), + change_destination, + memo_ctxt, + )) + .transpose() } else { Ok(None) } @@ -266,7 +269,7 @@ impl TransactionBuilder { let (hint, pubkey_expiry) = create_fog_hint(fog_hint_address, &self.fog_resolver, rng)?; let amount = Amount { value, - token_id: self.token_id, + token_id: self.fee.token_id, }; let (tx_out, shared_secret) = create_output_with_fog_hint(self.block_version, amount, recipient, hint, memo_fn, rng)?; @@ -299,11 +302,13 @@ impl TransactionBuilder { self.tombstone_block = min(self.fog_tombstone_block_limit, self.tombstone_block); } - /// Sets the transaction fee. + /// Sets the transaction fee value. /// /// # Arguments - /// * `fee` - Transaction fee, in picoMOB. + /// * `fee` - Transaction fee, in picoMOB, or smallest representable units. pub fn set_fee(&mut self, fee: u64) -> Result<(), TxBuilderError> { + // It is not allowed to change the fee token id after construction + let fee = Amount::new(fee, self.fee.token_id); // Set the fee in memo builder first, so that it can signal an error // before we set self.fee, and don't have to roll back. self.memo_builder @@ -314,8 +319,8 @@ impl TransactionBuilder { Ok(()) } - /// Gets the transaction fee. - pub fn get_fee(&self) -> u64 { + /// Gets the transaction fee amount + pub fn get_fee(&self) -> Amount { self.fee } @@ -359,7 +364,9 @@ impl TransactionBuilder { )); } - if !self.block_version.masked_token_id_feature_is_supported() && self.token_id != Mob::ID { + if !self.block_version.masked_token_id_feature_is_supported() + && self.fee.token_id != Mob::ID + { return Err(TxBuilderError::FeatureNotSupportedAtBlockVersion( *self.block_version, "nonzero token id", @@ -412,13 +419,7 @@ impl TransactionBuilder { let (outputs, _shared_serets): (Vec, Vec<_>) = self.outputs_and_shared_secrets.into_iter().unzip(); - let tx_prefix = TxPrefix::new( - inputs, - outputs, - self.fee, - *self.token_id, - self.tombstone_block, - ); + let tx_prefix = TxPrefix::new(inputs, outputs, self.fee, self.tombstone_block); let mut rings: Vec> = Vec::new(); for input in &tx_prefix.inputs { @@ -446,9 +447,9 @@ impl TransactionBuilder { &input_credential.view_private_key, ); let (amount, blinding) = masked_amount.get_value(&shared_secret)?; - if amount.token_id != self.token_id { + if amount.token_id != self.fee.token_id { return Err(TxBuilderError::WrongTokenType( - self.token_id, + self.fee.token_id, amount.token_id, )); } @@ -463,8 +464,8 @@ impl TransactionBuilder { &real_input_indices, &input_secrets, &output_values_and_blindings, - self.fee, - *self.token_id, + self.fee.value, + *self.fee.token_id, rng, )?; @@ -707,12 +708,14 @@ pub mod transaction_builder_tests { fog_resolver: FPR, rng: &mut RNG, ) -> Result { + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); let input_value = 1000; let output_value = 10; @@ -776,8 +779,14 @@ pub mod transaction_builder_tests { let membership_proofs = input_credentials.membership_proofs.clone(); let key_image = KeyImage::from(&input_credentials.onetime_private_key); - let mut transaction_builder = - TransactionBuilder::new(block_version, token_id, fpr, EmptyMemoBuilder::default()); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); + let mut transaction_builder = TransactionBuilder::new( + block_version, + fee_amount, + fpr, + EmptyMemoBuilder::default(), + ) + .unwrap(); transaction_builder.add_input(input_credentials); let (_txout, confirmation) = transaction_builder @@ -853,12 +862,14 @@ pub mod transaction_builder_tests { let membership_proofs = input_credentials.membership_proofs.clone(); let key_image = KeyImage::from(&input_credentials.onetime_private_key); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver, EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.add_input(input_credentials); let (_txout, confirmation) = transaction_builder @@ -943,12 +954,14 @@ pub mod transaction_builder_tests { }, }); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); let input_credentials = get_input_credentials(block_version, amount, &sender, &fog_resolver, &mut rng); @@ -1018,12 +1031,14 @@ pub mod transaction_builder_tests { }); { + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); @@ -1048,12 +1063,14 @@ pub mod transaction_builder_tests { } { + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(500); @@ -1107,12 +1124,14 @@ pub mod transaction_builder_tests { }); { + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), EmptyMemoBuilder::default(), - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); @@ -1283,12 +1302,14 @@ pub mod transaction_builder_tests { memo_builder.set_sender_credential(SenderMemoCredential::from(&sender)); memo_builder.enable_destination_memo(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder, - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); @@ -1439,12 +1460,14 @@ pub mod transaction_builder_tests { memo_builder.set_sender_credential(SenderMemoCredential::from(&sender)); memo_builder.enable_destination_memo(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder, - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); transaction_builder.set_fee(Mob::MINIMUM_FEE * 4).unwrap(); @@ -1597,12 +1620,14 @@ pub mod transaction_builder_tests { memo_builder.enable_destination_memo(); memo_builder.set_payment_request_id(42); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder, - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); @@ -1754,12 +1779,14 @@ pub mod transaction_builder_tests { memo_builder.set_sender_credential(SenderMemoCredential::from(&sender)); memo_builder.set_payment_request_id(47); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder, - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); @@ -1899,12 +1926,14 @@ pub mod transaction_builder_tests { memo_builder.enable_destination_memo(); memo_builder.set_payment_request_id(47); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder, - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); @@ -2069,12 +2098,14 @@ pub mod transaction_builder_tests { memo_builder.set_sender_credential(SenderMemoCredential::from(&charlie)); memo_builder.enable_destination_memo(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder, - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); @@ -2256,12 +2287,14 @@ pub mod transaction_builder_tests { memo_builder.set_sender_credential(SenderMemoCredential::from(&sender)); memo_builder.enable_destination_memo(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder, - ); + ) + .unwrap(); transaction_builder.set_tombstone_block(2000); @@ -2359,8 +2392,14 @@ pub mod transaction_builder_tests { ) .unwrap(); - let mut transaction_builder = - TransactionBuilder::new(block_version, token_id, fpr, EmptyMemoBuilder::default()); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); + let mut transaction_builder = TransactionBuilder::new( + block_version, + fee_amount, + fpr, + EmptyMemoBuilder::default(), + ) + .unwrap(); transaction_builder.add_input(input_credentials); let wrong_value = 999; @@ -2518,12 +2557,14 @@ pub mod transaction_builder_tests { memo_builder.set_sender_credential(SenderMemoCredential::from(&sender)); memo_builder.enable_destination_memo(); + let fee_amount = Amount::new(Mob::MINIMUM_FEE, token_id); let mut transaction_builder = TransactionBuilder::new( block_version, - token_id, + fee_amount, fog_resolver.clone(), memo_builder, - ); + ) + .unwrap(); let input_credentials = get_input_credentials( block_version, From 05778141193a27fa86bdc336a593a3a3939df57f Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Wed, 4 May 2022 14:15:51 -0600 Subject: [PATCH 02/77] Port to candidate 1.2 (#1911) * Cherry-pick Initial take on implementing Burn Redemption Memo (#1862) There was no real conflict except that in the tests for the new memo builder, the tests had to change the .add_output and .add_change_output APIs are different. * Update Change Subaddress Index (#1880) Set Change Subaddress Index to u64::MAX - 1 * Cherry-pick of API for generating burn txs in mobilecoind (#1872) This conflict was resolved: ``` diff --cc mobilecoind/src/payments.rs index 6424c3fd,c3b6f0ed..00000000 --- a/mobilecoind/src/payments.rs +++ b/mobilecoind/src/payments.rs @@@ -867,18 -876,17 +876,32 @@@ impl = + opt_memo_builder.unwrap_or_else(|| Box::new(EmptyMemoBuilder::default())); + + let fee_amount = Amount::new(fee, token_id); + let mut tx_builder = + TransactionBuilder::new_with_box(block_version, fee_amount, fog_resolver, memo_builder) + .map_err(|err| { + Error::TxBuild(format!("Error creating transaction builder: {}", err)) + })?; ++>>>>>>> d991eee7... API for generating burn txs in mobilecoind (#1872) // Unzip each vec of tuples into a tuple of vecs. let mut rings_and_proofs: Vec<(Vec, Vec)> = rings ``` * fix typo (#1883) * remove a test that is inapplicable now from the burn redemption memo PR * fix a test that I reconciled conflict incorrectly for * Cherry-pick Fix/slip10errors (#1893) There was a very small conflict which I resolved Co-authored-by: Eran Rundstein Co-authored-by: Bernie Dolan Co-authored-by: wjuan-mob --- Cargo.lock | 7 + android-bindings/src/bindings.rs | 10 +- .../src/cached_tx_data/memo_handler.rs | 8 + mobilecoind-json/src/data_types.rs | 2 +- mobilecoind/api/proto/mobilecoind_api.proto | 44 +++ mobilecoind/src/payments.rs | 30 +- mobilecoind/src/service.rs | 291 ++++++++++++++++- mobilecoind/strategies/accounts.py | 4 +- transaction/core/src/tx_error.rs | 8 + transaction/std/Cargo.toml | 1 + transaction/std/src/lib.rs | 8 +- transaction/std/src/memo/burn_redemption.rs | 57 ++++ transaction/std/src/memo/mod.rs | 22 ++ .../burn_redemption_memo_builder.rs | 145 +++++++++ transaction/std/src/memo_builder/mod.rs | 3 + transaction/std/src/transaction_builder.rs | 303 +++++++++++++++++- util/keyfile/src/bin/keygen_main.rs | 4 +- util/keyfile/src/bin/sample_keys_main.rs | 6 +- util/keyfile/src/config.rs | 4 +- util/keyfile/src/keygen.rs | 24 +- util/keyfile/src/lib.rs | 8 +- 21 files changed, 935 insertions(+), 54 deletions(-) create mode 100644 transaction/std/src/memo/burn_redemption.rs create mode 100644 transaction/std/src/memo_builder/burn_redemption_memo_builder.rs diff --git a/Cargo.lock b/Cargo.lock index fc9f5b6c80..e87a3b19eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,6 +141,12 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + [[package]] name = "async-channel" version = "1.6.1" @@ -5151,6 +5157,7 @@ dependencies = [ name = "mc-transaction-std" version = "1.3.0-pre0" dependencies = [ + "assert_matches", "cfg-if 1.0.0", "curve25519-dalek", "displaydoc", diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index eca402f6e0..d43256d4e9 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -21,7 +21,7 @@ use jni::{ }; use mc_account_keys::{ AccountKey, PublicAddress, RootEntropy, RootIdentity, ShortAddressHash, - CHANGE_SUBADDRESS_INDEX, DEFAULT_SUBADDRESS_INDEX, + CHANGE_SUBADDRESS_INDEX, DEFAULT_SUBADDRESS_INDEX, INVALID_SUBADDRESS_INDEX, }; use mc_account_keys_slip10::Slip10KeyGenerator; use mc_api::printable::PrintableWrapper; @@ -1396,8 +1396,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOut_compute_1key_1image( &tx_out_target_key, &tx_pub_key, ); - let spsk_to_index: BTreeMap = (DEFAULT_SUBADDRESS_INDEX - ..=CHANGE_SUBADDRESS_INDEX) + let spsk_to_index: BTreeMap = (0..=DEFAULT_SUBADDRESS_INDEX) + .chain(CHANGE_SUBADDRESS_INDEX..INVALID_SUBADDRESS_INDEX) .map(|index| (*account_key.subaddress(index).spend_public_key(), index)) .collect(); let subaddress_index = spsk_to_index @@ -1851,8 +1851,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_Util_recover_1onetime_1private_ &tx_target_key, &tx_pub_key, ); - let spsk_to_index: BTreeMap = (DEFAULT_SUBADDRESS_INDEX - ..=CHANGE_SUBADDRESS_INDEX) + let spsk_to_index: BTreeMap = (0..=DEFAULT_SUBADDRESS_INDEX) + .chain(CHANGE_SUBADDRESS_INDEX..INVALID_SUBADDRESS_INDEX) .map(|index| (*account_key.subaddress(index).spend_public_key(), index)) .collect(); let subaddress_index = spsk_to_index diff --git a/fog/sample-paykit/src/cached_tx_data/memo_handler.rs b/fog/sample-paykit/src/cached_tx_data/memo_handler.rs index 4ff5944fb0..c86fe2d72c 100644 --- a/fog/sample-paykit/src/cached_tx_data/memo_handler.rs +++ b/fog/sample-paykit/src/cached_tx_data/memo_handler.rs @@ -63,6 +63,14 @@ impl MemoHandler { log::trace!(self.logger, "Obtained a memo: {:?}", memo_type); match memo_type.clone() { MemoType::Unused(_) => Ok(None), + MemoType::BurnRedemption(_) => { + // TODO: For now we are not validating anything with burn redemption memos. + // Right now the memo data is unstructured, so there's nothing + // to verify there. In theory we should only find this type of + // memo on a the burn account, which cannot be used with the sample paykit since + // the spend key is unknown. + Ok(Some(memo_type)) + } MemoType::AuthenticatedSender(memo) => { if let Some(addr) = self.contacts.get(&memo.sender_address_hash()) { if bool::from(memo.validate( diff --git a/mobilecoind-json/src/data_types.rs b/mobilecoind-json/src/data_types.rs index 3b55beae09..2805d7c6d6 100644 --- a/mobilecoind-json/src/data_types.rs +++ b/mobilecoind-json/src/data_types.rs @@ -420,7 +420,7 @@ impl From<&mc_mobilecoind_api::ReceiverTxReceipt> for JsonReceiverTxReceipt { tx_public_key: hex::encode(&src.get_tx_public_key().get_data()), tx_out_hash: hex::encode(&src.get_tx_out_hash()), tombstone: src.get_tombstone(), - confirmation_number: hex::encode(&src.get_tx_out_hash()), + confirmation_number: hex::encode(&src.get_confirmation_number()), } } } diff --git a/mobilecoind/api/proto/mobilecoind_api.proto b/mobilecoind/api/proto/mobilecoind_api.proto index 4807d5dbdb..aee8bc4b70 100644 --- a/mobilecoind/api/proto/mobilecoind_api.proto +++ b/mobilecoind/api/proto/mobilecoind_api.proto @@ -44,6 +44,7 @@ service MobilecoindAPI { rpc GenerateOptimizationTx (GenerateOptimizationTxRequest) returns (GenerateOptimizationTxResponse) {} rpc GenerateTransferCodeTx (GenerateTransferCodeTxRequest) returns (GenerateTransferCodeTxResponse) {} rpc GenerateTxFromTxOutList (GenerateTxFromTxOutListRequest) returns (GenerateTxFromTxOutListResponse) {} + rpc GenerateBurnRedemptionTx (GenerateBurnRedemptionTxRequest) returns (GenerateBurnRedemptionTxResponse) {} rpc SubmitTx (SubmitTxRequest) returns (SubmitTxResponse) {} // Databases @@ -563,6 +564,49 @@ message GenerateTxFromTxOutListResponse { TxProposal tx_proposal = 1; } +// Generate a burn redemption transaction proposal object. +// Notes: +// - Sum of inputs needs to be greater than or equal to the burn amount and fee. +// - The set of inputs to use would be chosen automatically by mobilecoind. +// - The fee field could be set to zero, in which case mobilecoind would try and choose a fee. +message GenerateBurnRedemptionTxRequest { + // Monitor id sending the funds. + bytes sender_monitor_id = 1; + + // Subaddress to return change to. + uint64 change_subaddress = 2; + + // List of UnspentTxOuts to be spent by the transaction. + // All UnspentTxOuts must belong to the same sender_monitor_id. + // mobilecoind would choose a subset of these inputs to construct the transaction. + // Total input amount must be >= burn amount + fee. + repeated UnspentTxOut input_list = 3; + + // Amount to be burnt. This excludes change and fee. + uint64 burn_amount = 4; + + // Fee (setting to 0 causes mobilecoind to choose a value). + // The value used can be checked (but not changed) in tx_proposal.tx.prefix.fee + uint64 fee = 5; + + // Tombstone block (setting to 0 causes mobilecoind to choose a value). + // The value used can be checked (but not changed) in tx_proposal.tx.prefix.tombstone_block + uint64 tombstone = 6; + + // Token id to use for the transaction. + uint64 token_id = 7; + + // Optional 64 bytes of data to include in the burn redemption memo that is attached to the burn TxOut. + // If not provided zeros will be used. + bytes redemption_memo = 8; + + // Enable RTH destination memo. + bool enable_destination_memo = 9; +} +message GenerateBurnRedemptionTxResponse { + TxProposal tx_proposal = 1; +} + // Submits a transaction to the network. message SubmitTxRequest { TxProposal tx_proposal = 1; diff --git a/mobilecoind/src/payments.rs b/mobilecoind/src/payments.rs index 6424c3fd50..cee5b5681d 100644 --- a/mobilecoind/src/payments.rs +++ b/mobilecoind/src/payments.rs @@ -24,7 +24,7 @@ use mc_transaction_core::{ Amount, BlockIndex, BlockVersion, TokenId, }; use mc_transaction_std::{ - ChangeDestination, EmptyMemoBuilder, InputCredentials, TransactionBuilder, + ChangeDestination, EmptyMemoBuilder, InputCredentials, MemoBuilder, TransactionBuilder, }; use mc_util_uri::FogUri; use rand::Rng; @@ -221,6 +221,8 @@ impl>, ) -> Result { let logger = self.logger.new(o!("sender_monitor_id" => sender_monitor_id.to_string(), "outlays" => format!("{:?}", outlays))); log::trace!(logger, "Building pending transaction..."); @@ -325,6 +328,7 @@ impl Result + Send + Sync>, + opt_memo_builder: Option>, rng: &mut (impl RngCore + CryptoRng), logger: &Logger, ) -> Result { @@ -867,18 +876,17 @@ impl = + opt_memo_builder.unwrap_or_else(|| Box::new(EmptyMemoBuilder::default())); let fee_amount = Amount::new(fee, token_id); - - // Create tx_builder. - let mut tx_builder = TransactionBuilder::new( - block_version, - fee_amount, - fog_resolver, - EmptyMemoBuilder::default(), - ) - .map_err(|err| Error::TxBuild(format!("Error cretaing TransactionBuilder: {}", err)))?; + let mut tx_builder = + TransactionBuilder::new_with_box(block_version, fee_amount, fog_resolver, memo_builder) + .map_err(|err| { + Error::TxBuild(format!("Error creating transaction builder: {}", err)) + })?; // Unzip each vec of tuples into a tuple of vecs. let mut rings_and_proofs: Vec<(Vec, Vec)> = rings diff --git a/mobilecoind/src/service.rs b/mobilecoind/src/service.rs index 1b38e7ea5b..dbdf79ccfa 100644 --- a/mobilecoind/src/service.rs +++ b/mobilecoind/src/service.rs @@ -16,7 +16,9 @@ use crate::{ }; use bip39::{Language, Mnemonic, MnemonicType}; use grpcio::{EnvBuilder, RpcContext, RpcStatus, RpcStatusCode, ServerBuilder, UnarySink}; -use mc_account_keys::{AccountKey, PublicAddress, RootIdentity, DEFAULT_SUBADDRESS_INDEX}; +use mc_account_keys::{ + burn_address, AccountKey, PublicAddress, RootIdentity, DEFAULT_SUBADDRESS_INDEX, +}; use mc_account_keys_slip10::Slip10KeyGenerator; use mc_common::{ logger::{log, Logger}, @@ -38,6 +40,7 @@ use mc_transaction_core::{ tx::{TxOut, TxOutConfirmationNumber, TxOutMembershipProof}, TokenId, }; +use mc_transaction_std::{BurnRedemptionMemo, BurnRedemptionMemoBuilder}; use mc_util_from_random::FromRandom; use mc_util_grpc::{ rpc_internal_error, rpc_invalid_arg_error, rpc_logger, send_result, AdminService, @@ -46,7 +49,7 @@ use mc_util_grpc::{ use mc_watcher::watcher_db::WatcherDB; use protobuf::{ProtobufEnum, RepeatedField}; use std::{ - convert::TryFrom, + convert::{TryFrom, TryInto}, sync::{Arc, Mutex, RwLock}, }; @@ -880,6 +883,7 @@ impl Result { + // Get sender monitor id from request. + let sender_monitor_id = MonitorId::try_from(&request.sender_monitor_id) + .map_err(|err| rpc_internal_error("monitor_id.try_from.bytes", err, &self.logger))?; + + // Get monitor data for this monitor. + let sender_monitor_data = self + .mobilecoind_db + .get_monitor_data(&sender_monitor_id) + .map_err(|err| { + rpc_internal_error("mobilecoind_db.get_monitor_data", err, &self.logger) + })?; + + // Check that change_subaddress is covered by this monitor. + if !sender_monitor_data + .subaddress_indexes() + .contains(&request.change_subaddress) + { + return Err(RpcStatus::with_message( + RpcStatusCode::INVALID_ARGUMENT, + "change_subaddress".into(), + )); + } + + // Get the list of potential inputs passed to. + let input_list: Vec = request + .get_input_list() + .iter() + .enumerate() + .map(|(i, proto_utxo)| { + // Proto -> Rust struct conversion. + let utxo = UnspentTxOut::try_from(proto_utxo).map_err(|err| { + rpc_internal_error(format!("unspent_tx_out[{}].try_from", i), err, &self.logger) + })?; + + // Verify token id matches. + if utxo.token_id != request.token_id { + return Err(RpcStatus::with_message( + RpcStatusCode::INVALID_ARGUMENT, + format!("input_list[{}].token_id", i), + )); + } + + // Verify this output belongs to the monitor. + let subaddress_id = self + .mobilecoind_db + .get_subaddress_id_by_utxo_id(&UtxoId::from(&utxo)) + .map_err(|err| { + rpc_internal_error( + "mobilecoind_db.get_subaddress_id_by_utxo_id", + err, + &self.logger, + ) + })?; + + if subaddress_id.monitor_id != sender_monitor_id { + return Err(RpcStatus::with_message( + RpcStatusCode::INVALID_ARGUMENT, + format!("input_list[{}].monitor_id", i), + )); + } + + // Success. + Ok(utxo) + }) + .collect::, RpcStatus>>()?; + + // Generate the list of outlays. + let outlays = vec![Outlay { + value: request.get_burn_amount(), + receiver: burn_address(), + }]; + + // Create memo builder. + let mut memo_data = request.get_redemption_memo().to_vec(); + if memo_data.is_empty() { + memo_data.resize(BurnRedemptionMemo::MEMO_DATA_LEN, 0); + } + let memo_data_array = memo_data.try_into().map_err(|_err| { + RpcStatus::with_message(RpcStatusCode::INVALID_ARGUMENT, "redemption_memo".into()) + })?; + + let mut memo_builder = BurnRedemptionMemoBuilder::new(memo_data_array); + if request.enable_destination_memo { + memo_builder.enable_destination_memo(); + } + + // Attempt to construct a transaction. + let tx_proposal = self + .transactions_manager + .build_transaction( + &sender_monitor_id, + TokenId::from(request.token_id), + request.change_subaddress, + &input_list, + &outlays, + request.fee, + request.tombstone, + Some(Box::new(memo_builder)), + ) + .map_err(|err| { + rpc_internal_error("transactions_manager.build_transaction", err, &self.logger) + })?; + + // Success. + let mut response = mc_mobilecoind_api::GenerateBurnRedemptionTxResponse::new(); + response.set_tx_proposal((&tx_proposal).into()); + Ok(response) + } + fn generate_transfer_code_tx_impl( &mut self, request: mc_mobilecoind_api::GenerateTransferCodeTxRequest, @@ -1735,6 +1852,7 @@ impl>(); + assert!(!utxos.is_empty()); + + // Prepare request + let mut request = mc_mobilecoind_api::GenerateBurnRedemptionTxRequest::new(); + request.set_sender_monitor_id(monitor_id.to_vec()); + request.set_change_subaddress(0); + request.set_input_list(utxos); + request.set_burn_amount(100_000); + request.set_fee(200_000); + request.set_token_id(*token_id2); + request.set_redemption_memo(vec![5u8; BurnRedemptionMemo::MEMO_DATA_LEN]); + request.set_enable_destination_memo(true); + + // Test the happy flow. + { + let response = client.generate_burn_redemption_tx(&request).unwrap(); + + // Sanity test the response. + let tx_proposal = response.get_tx_proposal(); + let tx = Tx::try_from(tx_proposal.get_tx()).unwrap(); + + // Two outputs - change and burn + assert_eq!(tx.prefix.outputs.len(), 2); + + // Validate the change output. + let (change_tx_out, change_amount) = tx + .prefix + .outputs + .iter() + .find_map(|tx_out| { + tx_out + .view_key_match(sender.view_private_key()) + .map(|(amount, _commitment)| (tx_out.clone(), amount)) + .ok() + }) + .expect("Didn't find sender's change output"); + + assert_eq!(change_amount.value, 1_000_000_000_000 - 100_000 - 200_000); + + let ss = get_tx_out_shared_secret( + sender.view_private_key(), + &RistrettoPublic::try_from(&change_tx_out.public_key).unwrap(), + ); + let memo = change_tx_out.e_memo.unwrap().decrypt(&ss); + match MemoType::try_from(&memo).expect("Couldn't decrypt memo") { + MemoType::Destination(memo) => { + assert_eq!( + memo.get_address_hash(), + &ShortAddressHash::from(&burn_address()), + "lookup based on address hash failed" + ); + assert_eq!(memo.get_num_recipients(), 1); + assert_eq!(memo.get_fee(), 200_000); + assert_eq!( + memo.get_total_outlay(), + 300_000, + "outlay should be amount sent to recipient + fee" + ); + } + _ => { + panic!("unexpected memo type") + } + } + + // Validate the burn output. + let (burn_tx_out, burn_amount) = tx + .prefix + .outputs + .iter() + .find_map(|tx_out| { + tx_out + .view_key_match(&burn_address_view_private()) + .map(|(amount, _commitment)| (tx_out.clone(), amount)) + .ok() + }) + .expect("Didn't find burn output"); + + assert_eq!(burn_amount.value, 100_000); + + let ss = get_tx_out_shared_secret( + &burn_address_view_private(), + &RistrettoPublic::try_from(&burn_tx_out.public_key).unwrap(), + ); + let memo = burn_tx_out.e_memo.unwrap().decrypt(&ss); + assert_matches!(MemoType::try_from(&memo).expect("Couldn't decrypt memo"), MemoType::BurnRedemption(memo) if memo.memo_data() == &[5u8; 64]); + } + + // Invalid memo data length results in an error. + { + let mut request = request.clone(); + request.set_redemption_memo(vec![5u8; BurnRedemptionMemo::MEMO_DATA_LEN + 1]); + assert!(client.generate_burn_redemption_tx(&request).is_err()); + } + + // Trying to burn more than we have results in an error. + { + let mut request = request.clone(); + request.set_burn_amount(1_000_000_000_000 - request.get_fee() + 1); + assert!(client.generate_burn_redemption_tx(&request).is_err()); + } + } + #[test_with_logger] fn test_get_block_index_by_tx_pub_key(logger: Logger) { let mut rng: StdRng = SeedableRng::from_seed([23u8; 32]); diff --git a/mobilecoind/strategies/accounts.py b/mobilecoind/strategies/accounts.py index fc2baf7525..39e72b4075 100644 --- a/mobilecoind/strategies/accounts.py +++ b/mobilecoind/strategies/accounts.py @@ -41,8 +41,8 @@ def connect(host, port): def register_account(key_data, stub) -> AccountData: # Generate an account key from this root entropy - resp = stub.GetAccountKeyFromRootEntropy( - mobilecoind_api_pb2.GetAccountKeyFromMnemonic( + resp = stub.GetAccountKeyFromMnemonic( + mobilecoind_api_pb2.GetAccountKeyFromMnemonicRequest( mnemonic=key_data['mnemonic'])) account_key = resp.account_key diff --git a/transaction/core/src/tx_error.rs b/transaction/core/src/tx_error.rs index e6bf28bed5..29e5c0162c 100644 --- a/transaction/core/src/tx_error.rs +++ b/transaction/core/src/tx_error.rs @@ -65,6 +65,14 @@ pub enum NewMemoError { OutputsAfterChange, /// Changing the fee after the change output is not supported FeeAfterChange, + /// Invalid recipient address + InvalidRecipient, + /// Multiple outputs are not supported + MultipleOutputs, + /// Missing output + MissingOutput, + /// Mixed Token Ids are not supported in these memos + MixedTokenIds, /// Other: {0} Other(String), } diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index 168a4ef48b..f5c73edf00 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -34,6 +34,7 @@ curve25519-dalek = { version = "4.0.0-pre.2", default-features = false, features curve25519-dalek = { version = "4.0.0-pre.2", default-features = false, features = ["nightly", "u64_backend"] } [dev-dependencies] +assert_matches = "1.5" maplit = "1.0" yaml-rust = "0.4" diff --git a/transaction/std/src/lib.rs b/transaction/std/src/lib.rs index 483be9dae9..3575712115 100644 --- a/transaction/std/src/lib.rs +++ b/transaction/std/src/lib.rs @@ -18,11 +18,11 @@ pub use change_destination::ChangeDestination; pub use error::TxBuilderError; pub use input_credentials::InputCredentials; pub use memo::{ - AuthenticatedSenderMemo, AuthenticatedSenderWithPaymentRequestIdMemo, DestinationMemo, - DestinationMemoError, MemoDecodingError, MemoType, RegisteredMemoType, SenderMemoCredential, - UnusedMemo, + AuthenticatedSenderMemo, AuthenticatedSenderWithPaymentRequestIdMemo, BurnRedemptionMemo, + DestinationMemo, DestinationMemoError, MemoDecodingError, MemoType, RegisteredMemoType, + SenderMemoCredential, UnusedMemo, }; -pub use memo_builder::{EmptyMemoBuilder, MemoBuilder, RTHMemoBuilder}; +pub use memo_builder::{BurnRedemptionMemoBuilder, EmptyMemoBuilder, MemoBuilder, RTHMemoBuilder}; pub use transaction_builder::{DefaultTxOutputsOrdering, TransactionBuilder, TxOutputsOrdering}; // Re-export this to help the exported macros work diff --git a/transaction/std/src/memo/burn_redemption.rs b/transaction/std/src/memo/burn_redemption.rs new file mode 100644 index 0000000000..41f358f75b --- /dev/null +++ b/transaction/std/src/memo/burn_redemption.rs @@ -0,0 +1,57 @@ +// Copyright (c) 2022 The MobileCoin Foundation + +//! Object for 0x0001 Burn Redemption memo type +//! +//! TODO: Link to MCIP +//! This was proposed for standardization in mobilecoinfoundation/mcips/pull/TBD + +use super::RegisteredMemoType; +use crate::impl_memo_type_conversions; + +/// A memo that the sender writes to associate a burn of an assert on the +/// MobileCoin blockchain with a redemption of another asset on a different +/// blockchain. The main intended use-case for this is burning of tokens that +/// are correlated with redemption of some other asset on a different +/// blockchain. +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub struct BurnRedemptionMemo { + /// The memo data. + /// The contents of the memo depend on the token being burnt, and as such do + /// not have a strict schema. + memo_data: [u8; Self::MEMO_DATA_LEN], +} + +impl RegisteredMemoType for BurnRedemptionMemo { + const MEMO_TYPE_BYTES: [u8; 2] = [0x00, 0x01]; +} + +impl BurnRedemptionMemo { + /// The length of the custom memo data. + pub const MEMO_DATA_LEN: usize = 64; + + /// Create a new BurnRedemptionMemo. + pub fn new(memo_data: [u8; Self::MEMO_DATA_LEN]) -> Self { + BurnRedemptionMemo { memo_data } + } + + /// Get the memo data + pub fn memo_data(&self) -> &[u8; Self::MEMO_DATA_LEN] { + &self.memo_data + } +} + +impl From<&[u8; Self::MEMO_DATA_LEN]> for BurnRedemptionMemo { + fn from(src: &[u8; Self::MEMO_DATA_LEN]) -> Self { + let mut memo_data = [0u8; Self::MEMO_DATA_LEN]; + memo_data.copy_from_slice(src); + Self { memo_data } + } +} + +impl From for [u8; BurnRedemptionMemo::MEMO_DATA_LEN] { + fn from(src: BurnRedemptionMemo) -> [u8; BurnRedemptionMemo::MEMO_DATA_LEN] { + src.memo_data + } +} + +impl_memo_type_conversions! { BurnRedemptionMemo } diff --git a/transaction/std/src/memo/mod.rs b/transaction/std/src/memo/mod.rs index 6c151ad54c..03a4bb9011 100644 --- a/transaction/std/src/memo/mod.rs +++ b/transaction/std/src/memo/mod.rs @@ -30,6 +30,15 @@ //! implement a new `MemoBuilder`. See the `memo_builder` module for examples. //! Or, if you don't want to use the `TransactionBuilder`, you can call //! `TxOut::new_with_memo` directly. +//! +//! The following memo types are natively supported by this module: +//! | Memo type bytes | Name | +//! | ----------- | ----------- | +//! | 0x0000 | Unused | +//! | 0x0001 | Burn Redemption Memo | +//! | 0x0100 | Authenticated Sender Memo | +//! | 0x0101 | Authenticated Sender With Payment Request Id Memo | +//! | 0x0200 | Destination Memo | use crate::impl_memo_enum; use core::{convert::TryFrom, fmt::Debug}; @@ -38,6 +47,7 @@ use displaydoc::Display; mod authenticated_common; mod authenticated_sender; mod authenticated_sender_with_payment_request_id; +mod burn_redemption; mod credential; mod destination; mod macros; @@ -46,6 +56,7 @@ mod unused; pub use authenticated_common::compute_category1_hmac; pub use authenticated_sender::AuthenticatedSenderMemo; pub use authenticated_sender_with_payment_request_id::AuthenticatedSenderWithPaymentRequestIdMemo; +pub use burn_redemption::BurnRedemptionMemo; pub use credential::SenderMemoCredential; pub use destination::{DestinationMemo, DestinationMemoError}; pub use unused::UnusedMemo; @@ -73,6 +84,7 @@ pub enum MemoDecodingError { impl_memo_enum! { MemoType, Unused(UnusedMemo), + BurnRedemption(BurnRedemptionMemo), AuthenticatedSender(AuthenticatedSenderMemo), AuthenticatedSenderWithPaymentRequestId(AuthenticatedSenderWithPaymentRequestIdMemo), Destination(DestinationMemo), @@ -160,6 +172,16 @@ mod tests { } }, } + + let memo6 = BurnRedemptionMemo::new([2; 64]); + match MemoType::try_from(&MemoPayload::from(memo6.clone())).unwrap() { + MemoType::BurnRedemption(memo) => { + assert_eq!(memo6, memo); + } + _ => { + panic!("unexpected deserialization"); + } + } } #[test] diff --git a/transaction/std/src/memo_builder/burn_redemption_memo_builder.rs b/transaction/std/src/memo_builder/burn_redemption_memo_builder.rs new file mode 100644 index 0000000000..ef0be213d5 --- /dev/null +++ b/transaction/std/src/memo_builder/burn_redemption_memo_builder.rs @@ -0,0 +1,145 @@ +// Copyright (c) 2022 The MobileCoin Foundation + +//! Defines the BurnRedemptionMemoBuilder. +//! This MemoBuilder policy implements Burn Redemption tracking using memos, as +//! envisioned in MCIP #TODO. + +use super::{ + memo::{BurnRedemptionMemo, DestinationMemo, DestinationMemoError, UnusedMemo}, + MemoBuilder, +}; +use crate::ChangeDestination; +use mc_account_keys::{burn_address, PublicAddress, ShortAddressHash}; +use mc_transaction_core::{tokens::Mob, Amount, MemoContext, MemoPayload, NewMemoError, Token}; + +/// This memo builder attaches 0x0001 Burn Redemption Memos to an output going +/// to the designated burn address, and 0x0200 Destination Memos to change +/// outputs. Only a single non-change output is allowed, and it must go to the +/// designated burn address. +/// +/// Usage: +/// You should usually use this like: +/// +/// let memo_data = [1; BurnRedemptionMemo::MEMO_DATA_LEN]; +/// let mut mb = BurnRedemptionMemoBuilder::new(memo_data); +/// mb.enable_destination_memo(); +/// +/// Then use it to construct a transaction builder. +/// +/// A memo builder configured this way will use 0x0001 Burn Redemption Memo +/// on the burn output and 0x0200 Destination Memo on the change output. +/// +/// If mb.enable_destination_memo() is not called 0x0000 Unused will appear on +/// change output, instead of 0x0200 Destination Memo. +/// +/// When invoking the transaction builder, the change output must be created +/// last. If the burn output is created after the change output, an error will +/// occur. +/// +/// If more than one burn output is created, an error will be returned. +#[derive(Clone, Debug)] +pub struct BurnRedemptionMemoBuilder { + // The memo data we will attach to the burn output. + memo_data: [u8; BurnRedemptionMemo::MEMO_DATA_LEN], + // Whether destination memos are enabled. + destination_memo_enabled: bool, + // Tracks if we already wrote a destination memo, for error reporting + wrote_destination_memo: bool, + // Tracks the amount being burned + burn_amount: Option, + // Tracks the fee + fee: Amount, +} + +impl BurnRedemptionMemoBuilder { + /// Construct a new BurnRedemptionMemoBuilder. + pub fn new(memo_data: [u8; BurnRedemptionMemo::MEMO_DATA_LEN]) -> Self { + Self { + memo_data, + destination_memo_enabled: false, + wrote_destination_memo: false, + burn_amount: None, + fee: Amount::new(Mob::MINIMUM_FEE, Mob::ID), + } + } + /// Enable destination memos + pub fn enable_destination_memo(&mut self) { + self.destination_memo_enabled = true; + } + + /// Disable destination memos + pub fn disable_destination_memo(&mut self) { + self.destination_memo_enabled = false; + } +} + +impl MemoBuilder for BurnRedemptionMemoBuilder { + /// Set the fee + fn set_fee(&mut self, fee: Amount) -> Result<(), NewMemoError> { + if self.wrote_destination_memo { + return Err(NewMemoError::FeeAfterChange); + } + self.fee = fee; + Ok(()) + } + + /// Build a memo for the burn output. + fn make_memo_for_output( + &mut self, + amount: Amount, + recipient: &PublicAddress, + _memo_context: MemoContext, + ) -> Result { + if *recipient != burn_address() { + return Err(NewMemoError::InvalidRecipient); + } + if self.burn_amount.is_some() { + return Err(NewMemoError::MultipleOutputs); + } + if self.wrote_destination_memo { + return Err(NewMemoError::OutputsAfterChange); + } + self.burn_amount = Some(amount); + Ok(BurnRedemptionMemo::new(self.memo_data).into()) + } + + /// Build a memo for a change output (to ourselves). + fn make_memo_for_change_output( + &mut self, + change_amount: Amount, + _change_destination: &ChangeDestination, + _memo_context: MemoContext, + ) -> Result { + if !self.destination_memo_enabled { + return Ok(UnusedMemo {}.into()); + } + if self.wrote_destination_memo { + return Err(NewMemoError::MultipleChangeOutputs); + } + let burn_amount = self.burn_amount.ok_or(NewMemoError::MissingOutput)?; + if burn_amount.token_id != self.fee.token_id + || burn_amount.token_id != change_amount.token_id + { + return Err(NewMemoError::MixedTokenIds); + } + + let total_outlay = burn_amount + .value + .checked_add(self.fee.value) + .ok_or(NewMemoError::LimitsExceeded("total_outlay"))?; + match DestinationMemo::new( + ShortAddressHash::from(&burn_address()), + total_outlay, + self.fee.value, + ) { + Ok(mut d_memo) => { + self.wrote_destination_memo = true; + d_memo.set_num_recipients(1); + Ok(d_memo.into()) + } + Err(err) => match err { + DestinationMemoError::FeeTooLarge => Err(NewMemoError::LimitsExceeded("fee")), + }, + } + } +} diff --git a/transaction/std/src/memo_builder/mod.rs b/transaction/std/src/memo_builder/mod.rs index 64f09bb8a6..e914147cd3 100644 --- a/transaction/std/src/memo_builder/mod.rs +++ b/transaction/std/src/memo_builder/mod.rs @@ -9,7 +9,10 @@ use core::fmt::Debug; use mc_account_keys::PublicAddress; use mc_transaction_core::{Amount, MemoContext, MemoPayload, NewMemoError}; +mod burn_redemption_memo_builder; mod rth_memo_builder; + +pub use burn_redemption_memo_builder::BurnRedemptionMemoBuilder; pub use rth_memo_builder::RTHMemoBuilder; /// The MemoBuilder trait defines the API that the transaction builder uses diff --git a/transaction/std/src/transaction_builder.rs b/transaction/std/src/transaction_builder.rs index 72ba7f5c0d..15fc2e06ed 100644 --- a/transaction/std/src/transaction_builder.rs +++ b/transaction/std/src/transaction_builder.rs @@ -540,7 +540,10 @@ fn create_fog_hint( #[cfg(test)] pub mod transaction_builder_tests { use super::*; - use crate::{EmptyMemoBuilder, MemoType, RTHMemoBuilder, SenderMemoCredential}; + use crate::{ + BurnRedemptionMemoBuilder, EmptyMemoBuilder, MemoType, RTHMemoBuilder, SenderMemoCredential, + }; + use assert_matches::assert_matches; use maplit::btreemap; use mc_account_keys::{ burn_address, burn_address_view_private, AccountKey, ShortAddressHash, @@ -555,7 +558,7 @@ pub mod transaction_builder_tests { subaddress_matches_tx_out, tx::TxOutMembershipProof, validation::{validate_signature, validate_tx_out}, - TokenId, + NewTxError, TokenId, }; use rand::{rngs::StdRng, SeedableRng}; use std::convert::TryFrom; @@ -2631,4 +2634,300 @@ pub mod transaction_builder_tests { .is_err()); } } + + #[test] + // Transaction builder with Burn Redemption memo builder + fn test_transaction_builder_burn_redemption_memos() { + let mut rng: StdRng = SeedableRng::from_seed([1u8; 32]); + let block_version = BlockVersion::MAX; + let token_id = TokenId::from(5); + let fog_resolver = MockFogResolver::default(); + let sender = AccountKey::random(&mut rng); + let change_destination = ChangeDestination::from(&sender); + + // Adding an output that is not to the burn address is not allowed. + { + let memo_builder = BurnRedemptionMemoBuilder::new([2u8; 64]); + + let mut transaction_builder = TransactionBuilder::new( + block_version, + Amount::new(10, token_id), + fog_resolver.clone(), + memo_builder, + ) + .unwrap(); + + let recipient = AccountKey::random(&mut rng); + let result = + transaction_builder.add_output(100, &recipient.default_subaddress(), &mut rng); + assert_matches!( + result, + Err(TxBuilderError::NewTx(NewTxError::Memo( + NewMemoError::InvalidRecipient + ))) + ); + } + + // Adding two burn outputs is not allowed. + { + let memo_builder = BurnRedemptionMemoBuilder::new([2u8; 64]); + + let mut transaction_builder = TransactionBuilder::new( + block_version, + Amount::new(10, token_id), + fog_resolver.clone(), + memo_builder, + ) + .unwrap(); + + transaction_builder + .add_output(100, &burn_address(), &mut rng) + .unwrap(); + + let result = transaction_builder.add_output(100, &burn_address(), &mut rng); + assert_matches!( + result, + Err(TxBuilderError::NewTx(NewTxError::Memo( + NewMemoError::MultipleOutputs + ))) + ); + } + + // Adding a change output before a burn output is not allowed. + { + let mut memo_builder = BurnRedemptionMemoBuilder::new([2u8; 64]); + memo_builder.enable_destination_memo(); + + let mut transaction_builder = TransactionBuilder::new( + block_version, + Amount::new(10, token_id), + fog_resolver.clone(), + memo_builder, + ) + .unwrap(); + + let result = transaction_builder.add_change_output(10, &change_destination, &mut rng); + + assert_matches!( + result, + Err(TxBuilderError::NewTx(NewTxError::Memo( + NewMemoError::MissingOutput + ))) + ); + } + + // Setting fee after change output has been written is not allowed. + { + let mut memo_builder = BurnRedemptionMemoBuilder::new([3u8; 64]); + memo_builder.enable_destination_memo(); + + let mut transaction_builder = TransactionBuilder::new( + block_version, + Amount::new(10, token_id), + fog_resolver.clone(), + memo_builder, + ) + .unwrap(); + + transaction_builder.set_fee(3).unwrap(); + + let input_credentials = get_input_credentials( + block_version, + Amount::new(113, token_id), + &AccountKey::random(&mut rng), + &fog_resolver, + &mut rng, + ); + transaction_builder.add_input(input_credentials); + + let (_burn_tx_out, _confirmation) = transaction_builder + .add_output(100, &burn_address(), &mut rng) + .unwrap(); + + transaction_builder + .add_change_output(10, &change_destination, &mut rng) + .unwrap(); + + let result = transaction_builder.set_fee(1235); + assert_matches!( + result, + Err(TxBuilderError::Memo(NewMemoError::FeeAfterChange)) + ); + } + + // Change in a different token is not allowed. + // Note: We cannot test for the mixed tokens because mixed transactions + // are not supported at all in the TransactionBuilder API in 1.2 branch. + + // Happy flow without change + { + let mut memo_builder = BurnRedemptionMemoBuilder::new([2u8; 64]); + memo_builder.enable_destination_memo(); + + let mut transaction_builder = TransactionBuilder::new( + block_version, + Amount::new(10, token_id), + fog_resolver.clone(), + memo_builder, + ) + .unwrap(); + + transaction_builder.set_fee(3).unwrap(); + + let input_credentials = get_input_credentials( + block_version, + Amount::new(113, token_id), + &AccountKey::random(&mut rng), + &fog_resolver, + &mut rng, + ); + transaction_builder.add_input(input_credentials); + + let (burn_output, _confirmation) = transaction_builder + .add_output(110, &burn_address(), &mut rng) + .unwrap(); + + let tx = transaction_builder.build(&mut rng).expect("build tx"); + + assert_eq!(tx.prefix.outputs.len(), 1); + assert_eq!(burn_output, tx.prefix.outputs[0]); + + // Test that view key matching works with the burn tx out with burn address view + // key + let (amount, _) = burn_output + .view_key_match(&burn_address_view_private()) + .unwrap(); + assert_eq!(amount, Amount::new(110, token_id)); + + // Burn output should have a burn redemption memo + let ss = get_tx_out_shared_secret( + &burn_address_view_private(), + &RistrettoPublic::try_from(&burn_output.public_key).unwrap(), + ); + let memo = burn_output.e_memo.unwrap().decrypt(&ss); + match MemoType::try_from(&memo).expect("Couldn't decrypt memo") { + MemoType::BurnRedemption(memo) => { + assert_eq!(memo.memo_data(), &[2u8; 64],); + } + _ => { + panic!("unexpected memo type") + } + } + } + + // Happy flow with change + { + let mut memo_builder = BurnRedemptionMemoBuilder::new([3u8; 64]); + memo_builder.enable_destination_memo(); + + let mut transaction_builder = TransactionBuilder::new( + block_version, + Amount::new(10, token_id), + fog_resolver.clone(), + memo_builder, + ) + .unwrap(); + + transaction_builder.set_fee(3).unwrap(); + + let input_credentials = get_input_credentials( + block_version, + Amount::new(113, token_id), + &AccountKey::random(&mut rng), + &fog_resolver, + &mut rng, + ); + transaction_builder.add_input(input_credentials); + + let (burn_tx_out, _confirmation) = transaction_builder + .add_output(100, &burn_address(), &mut rng) + .unwrap(); + + transaction_builder + .add_change_output(10, &change_destination, &mut rng) + .unwrap(); + + let tx = transaction_builder.build(&mut rng).expect("build tx"); + + assert_eq!(tx.prefix.outputs.len(), 2); + + let burn_output = tx + .prefix + .outputs + .iter() + .find(|tx_out| tx_out.public_key == burn_tx_out.public_key) + .expect("Didn't find recipient's output"); + let change_output = tx + .prefix + .outputs + .iter() + .find(|tx_out| { + subaddress_matches_tx_out(&sender, CHANGE_SUBADDRESS_INDEX, tx_out).unwrap() + }) + .expect("Didn't find sender's output"); + + // Test that view key matching works with the burn tx out with burn address view + // key + let (amount, _) = burn_output + .view_key_match(&burn_address_view_private()) + .unwrap(); + assert_eq!(amount, Amount::new(100, token_id)); + + assert!(change_output + .view_key_match(&burn_address_view_private()) + .is_err()); + + // Test that view key matching works with the change tx out with sender's view + // key + let (amount, _) = change_output + .view_key_match(sender.view_private_key()) + .unwrap(); + assert_eq!(amount, Amount::new(10, token_id)); + + assert!(burn_output + .view_key_match(sender.view_private_key()) + .is_err()); + + // Burn output should have a burn redemption memo + let ss = get_tx_out_shared_secret( + &burn_address_view_private(), + &RistrettoPublic::try_from(&burn_output.public_key).unwrap(), + ); + let memo = burn_output.e_memo.unwrap().decrypt(&ss); + match MemoType::try_from(&memo).expect("Couldn't decrypt memo") { + MemoType::BurnRedemption(memo) => { + assert_eq!(memo.memo_data(), &[3u8; 64],); + } + _ => { + panic!("unexpected memo type") + } + } + + // Change output should have a destination memo + let ss = get_tx_out_shared_secret( + sender.view_private_key(), + &RistrettoPublic::try_from(&change_output.public_key).unwrap(), + ); + let memo = change_output.e_memo.unwrap().decrypt(&ss); + match MemoType::try_from(&memo).expect("Couldn't decrypt memo") { + MemoType::Destination(memo) => { + assert_eq!( + memo.get_address_hash(), + &ShortAddressHash::from(&burn_address()), + "lookup based on address hash failed" + ); + assert_eq!(memo.get_num_recipients(), 1); + assert_eq!(memo.get_fee(), 3); + assert_eq!( + memo.get_total_outlay(), + 103, + "outlay should be amount sent to recipient + fee" + ); + } + _ => { + panic!("unexpected memo type") + } + } + } + } } diff --git a/util/keyfile/src/bin/keygen_main.rs b/util/keyfile/src/bin/keygen_main.rs index 597208bc91..c511ce56fa 100644 --- a/util/keyfile/src/bin/keygen_main.rs +++ b/util/keyfile/src/bin/keygen_main.rs @@ -27,7 +27,7 @@ fn main() { .clone() .unwrap_or_else(|| std::env::current_dir().unwrap()); let fog_report_url = config.general.fog_report_url.as_deref(); - let fog_report_id = config.general.fog_report_id.as_deref(); + let fog_report_id = config.general.fog_report_id; let fog_authority_spki = config .general .fog_authority_spki @@ -50,7 +50,7 @@ fn main() { &mnemonic, 0, fog_report_url, - fog_report_id, + &fog_report_id, fog_authority_spki, ) .expect("Could not write keyfile"); diff --git a/util/keyfile/src/bin/sample_keys_main.rs b/util/keyfile/src/bin/sample_keys_main.rs index 3c4aed584a..e7cadf0cf9 100644 --- a/util/keyfile/src/bin/sample_keys_main.rs +++ b/util/keyfile/src/bin/sample_keys_main.rs @@ -34,17 +34,13 @@ fn main() { panic!("Fog report url was passed, so fog is enabled, but no fog authority spki was provided. This is needed for the fog authority signature scheme. Use --fog-authority-root to pass a .pem file or --fog-authority-spki to pass base64 encoded bytes specifying this.") } - if config.general.fog_report_url.is_some() && config.general.fog_report_id.is_none() { - panic!("Fog report url was passed, so fog is enabled, but no fog report id was provided. This is needed for the fog authority signature scheme. Use --fog_report_id to pass an id string specifying this.") - } - println!("Writing {} keys to {:?}", config.num, path); mc_util_keyfile::keygen::write_default_keyfiles( path, config.num, config.general.fog_report_url.as_deref(), - config.general.fog_report_id.as_deref(), + &config.general.fog_report_id, spki.as_deref(), config.general.seed, ) diff --git a/util/keyfile/src/config.rs b/util/keyfile/src/config.rs index 3777a6d73e..9936c82ea5 100644 --- a/util/keyfile/src/config.rs +++ b/util/keyfile/src/config.rs @@ -14,8 +14,8 @@ pub struct Config { pub fog_report_url: Option, /// Fog Report ID - #[clap(long, env = "MC_FOG_REPORT_ID")] - pub fog_report_id: Option, + #[clap(long, env = "MC_FOG_REPORT_ID", default_value = "")] + pub fog_report_id: String, /// Fog Authority subjectPublicKeyInfo, loaded from a PEM root certificate #[clap(long, parse(try_from_str = load_spki_from_pemfile), env = "MC_FOG_AUTHORITY_ROOT")] diff --git a/util/keyfile/src/keygen.rs b/util/keyfile/src/keygen.rs index 0c5a4080fc..d958301320 100644 --- a/util/keyfile/src/keygen.rs +++ b/util/keyfile/src/keygen.rs @@ -28,14 +28,14 @@ pub fn write_keyfiles>( mnemonic: &Mnemonic, account_index: u32, fog_report_url: Option<&str>, - fog_report_id: Option<&str>, + fog_report_id: &str, fog_authority_spki: Option<&[u8]>, ) -> Result<(), Error> { let slip10key = mnemonic.clone().derive_slip10_key(account_index); - let acct_key = match (fog_report_url, fog_report_id, fog_authority_spki) { - (None, None, None) => AccountKey::try_from(slip10key) + let acct_key = match (fog_report_url, fog_authority_spki) { + (None, None) => AccountKey::try_from(slip10key) .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err.to_string()))?, - (Some(fog_report_url), Some(fog_report_id), Some(fog_authority_spki)) => { + (Some(fog_report_url), Some(fog_authority_spki)) => { slip10key.try_into_account_key(fog_report_url, fog_report_id, fog_authority_spki)? } _ => return Err(Error::MissingFogDetails), @@ -69,7 +69,7 @@ pub fn write_default_keyfiles>( path: P, num_accounts: usize, fog_report_url: Option<&str>, - fog_report_id: Option<&str>, + fog_report_id: &str, fog_authority_spki: Option<&[u8]>, seed: [u8; 32], ) -> Result<(), Error> { @@ -220,8 +220,8 @@ mod test { &dir1, 10, Some(fqdn), - Some(fog_report_id), - Some(&fog_authority_spki), + fog_report_id, + Some(fog_authority_spki), DEFAULT_SEED, ) .expect("Error writing default keyfiles to dir1"); @@ -229,8 +229,8 @@ mod test { &dir2, 10, Some(fqdn), - Some(fog_report_id), - Some(&fog_authority_spki), + fog_report_id, + Some(fog_authority_spki), DEFAULT_SEED, ) .expect("Error writing default keyfiles to dir2"); @@ -245,9 +245,9 @@ mod test { let dir1 = tempfile::tempdir().expect("Could not create temporary dir1"); let dir2 = tempfile::tempdir().expect("Could not create temporary dir2"); - write_default_keyfiles(&dir1, 10, None, None, None, DEFAULT_SEED) + write_default_keyfiles(&dir1, 10, None, "", None, DEFAULT_SEED) .expect("Could not write keyfiles to dir1"); - write_default_keyfiles(&dir2, 10, None, None, None, DEFAULT_SEED) + write_default_keyfiles(&dir2, 10, None, "", None, DEFAULT_SEED) .expect("Could not write keyfiles to dir2"); assert_default_pubfiles_eq(&dir1, &dir2); @@ -270,7 +270,7 @@ mod test { let dir1 = tempfile::tempdir().expect("Could not create temporary dir1"); - write_default_keyfiles(&dir1, 10, None, None, None, DEFAULT_SEED) + write_default_keyfiles(&dir1, 10, None, "", None, DEFAULT_SEED) .expect("Could not write example keyfiles"); let mut actual = read_default_keyfiles(&dir1) diff --git a/util/keyfile/src/lib.rs b/util/keyfile/src/lib.rs index 8bc253a633..6e6f5217a1 100644 --- a/util/keyfile/src/lib.rs +++ b/util/keyfile/src/lib.rs @@ -28,14 +28,14 @@ pub fn write_keyfile>( mnemonic: &Mnemonic, account_index: u32, fog_report_url: Option<&str>, - fog_report_id: Option<&str>, + fog_report_id: &str, fog_authority_spki: Option<&[u8]>, ) -> Result<(), Error> { let json = UncheckedMnemonicAccount { mnemonic: Some(mnemonic.clone().into_phrase()), account_index: Some(account_index), fog_report_url: fog_report_url.map(ToOwned::to_owned), - fog_report_id: fog_report_id.map(ToOwned::to_owned), + fog_report_id: Some(fog_report_id.to_owned()), fog_authority_spki: fog_authority_spki.map(ToOwned::to_owned), }; Ok(serde_json::to_writer(File::create(path)?, &json)?) @@ -141,7 +141,7 @@ mod testing { let dir = tempfile::tempdir().expect("Could not create temp dir"); let mnemonic = Mnemonic::new(MnemonicType::Words24, Language::English); let path = dir.path().join("no_fog"); - write_keyfile(&path, &mnemonic, 0, None, None, None).expect("Could not write keyfile"); + write_keyfile(&path, &mnemonic, 0, None, "", None).expect("Could not write keyfile"); let expected = AccountKey::from(mnemonic.derive_slip10_key(0)); let actual = read_keyfile(&path).expect("Could not read keyfile"); assert_eq!(expected, actual); @@ -170,7 +170,7 @@ mod testing { &mnemonic, 0, Some(fog_report_url), - Some(fog_report_id), + fog_report_id, Some(fog_authority_spki), ) .expect("Could not write keyfile"); From 3e45b7e2f6eba087433b489bfaad92d168cd3c5f Mon Sep 17 00:00:00 2001 From: Bernie Dolan Date: Sat, 7 May 2022 20:45:50 -0400 Subject: [PATCH 03/77] Amount -> MaskedAmount (#1941) * Amount -> MaskedAmount * Lint * Lint --- android-bindings/makefile | 1 + android-bindings/src/bindings.rs | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/android-bindings/makefile b/android-bindings/makefile index 1b6f60a1c6..b01c3b7aba 100644 --- a/android-bindings/makefile +++ b/android-bindings/makefile @@ -99,6 +99,7 @@ copy_artifacts: cp -f ../api/proto/external.proto build/proto/ cp -f ../consensus/api/proto/consensus_common.proto build/proto/ cp -f ../consensus/api/proto/consensus_peer.proto build/proto/ + cp -f ../consensus/api/proto/consensus_config.proto build/proto cp -f ../attest/api/proto/attest.proto build/proto/ cp -f ../fog/report/api/proto/report.proto build/proto/ cp -f ../fog/api/proto/view.proto build/proto/ diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index d43256d4e9..e9114c6168 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -306,11 +306,11 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_AttestedClient_decrypt_1payload } /***************************************************************** - * Amount + * MaskedAmount */ #[no_mangle] -pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_init_1jni( +pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_init_1jni( env: JNIEnv, obj: JObject, commitment: jbyteArray, @@ -331,7 +331,7 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_init_1jni( } #[no_mangle] -pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_init_1jni_1with_1secret( +pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_init_1jni_1with_1secret( env: JNIEnv, obj: JObject, tx_out_shared_secret: JObject, @@ -350,7 +350,7 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_init_1jni_1with_1secret( } #[no_mangle] -pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_get_1bytes( +pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_get_1bytes( env: JNIEnv, obj: JObject, ) -> jbyteArray { @@ -366,7 +366,10 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_get_1bytes( } #[no_mangle] -pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_finalize_1jni(env: JNIEnv, obj: JObject) { +pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_finalize_1jni( + env: JNIEnv, + obj: JObject, +) { jni_ffi_call(&env, |env| { let _: MaskedAmount = env.take_rust_field(obj, RUST_OBJ_FIELD)?; Ok(()) @@ -374,7 +377,7 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_finalize_1jni(env: JNIEn } #[no_mangle] -pub unsafe extern "C" fn Java_com_mobilecoin_lib_Amount_unmask_1value( +pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_unmask_1value( env: JNIEnv, obj: JObject, view_key: JObject, @@ -1396,7 +1399,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOut_compute_1key_1image( &tx_out_target_key, &tx_pub_key, ); - let spsk_to_index: BTreeMap = (0..=DEFAULT_SUBADDRESS_INDEX) + let spsk_to_index: BTreeMap = (u64::MIN + ..=DEFAULT_SUBADDRESS_INDEX) .chain(CHANGE_SUBADDRESS_INDEX..INVALID_SUBADDRESS_INDEX) .map(|index| (*account_key.subaddress(index).spend_public_key(), index)) .collect(); @@ -1851,7 +1855,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_Util_recover_1onetime_1private_ &tx_target_key, &tx_pub_key, ); - let spsk_to_index: BTreeMap = (0..=DEFAULT_SUBADDRESS_INDEX) + let spsk_to_index: BTreeMap = (u64::MIN + ..=DEFAULT_SUBADDRESS_INDEX) .chain(CHANGE_SUBADDRESS_INDEX..INVALID_SUBADDRESS_INDEX) .map(|index| (*account_key.subaddress(index).spend_public_key(), index)) .collect(); From 88c6222eee85ff22615ff8760f44b7f878dfd302 Mon Sep 17 00:00:00 2001 From: Bernie Dolan Date: Mon, 9 May 2022 23:16:47 -0400 Subject: [PATCH 04/77] unmask_value -> unmask_amount (#1952) * unmask_value -> unmask_value Changed unmask_value to unmask_amount, returning an Amount class. The Amount class contains both the value and the token ID * Updating Amount constructor signature * Lint * Lint --- android-bindings/src/bindings.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index e9114c6168..98a54b9368 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -377,7 +377,7 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_finalize_1jni( } #[no_mangle] -pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_unmask_1value( +pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_unmask_1amount( env: JNIEnv, obj: JObject, view_key: JObject, @@ -395,14 +395,27 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_unmask_1value( env.get_rust_field(tx_pub_key, RUST_OBJ_FIELD)?; let shared_secret = create_shared_secret(&tx_pub_key, &view_key); let (amount, _) = masked_amount.get_value(&shared_secret)?; + let value = env.new_object( + "java/math/BigInteger", + "(I[B)V", + &[ + jni::objects::JValue::Int(1), + env.byte_array_from_slice(&amount.value.to_be_bytes())? + .into(), + ], + )?; + let token_id = env.new_object( + "com/mobilecoin/lib/UnsignedLong", + "(J)V", + &[jni::objects::JValue::Long(*amount.token_id as i64)], + )?; Ok(env .new_object( - "java/math/BigInteger", - "(I[B)V", // public BigInteger(int signum, byte[] magnitude) + "com/mobilecoin/lib/Amount", + "(Ljava/math/BigInteger;Lcom/mobilecoin/lib/UnsignedLong;)V", &[ - 1.into(), - env.byte_array_from_slice(&amount.value.to_be_bytes())? - .into(), + jni::objects::JValue::Object(value), + jni::objects::JValue::Object(token_id), ], )? .into_inner()) From 3f7f364b90fa506df01b0269902ada62dd4bb10c Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 12 May 2022 20:23:51 -0600 Subject: [PATCH 05/77] Make fee map enforce divisibility by minimum fee. Also check this in enclave impl (#1965) (#1970) * Make fee map enforce divisibility by minimum fee. Also check this in enclave impl * fix previous after cargo fmt * fix imports * fix build * clippy * fix consensus service tests * fix more tests * fix blockchain api tests * fix consensus enclave api tests * fix consensus enclave impl tests * fix more tests --- consensus/enclave/api/src/config.rs | 8 ++-- consensus/enclave/api/src/fee_map.rs | 43 +++++++++++++----- consensus/enclave/impl/src/lib.rs | 11 +++-- consensus/service/config/src/tokens.rs | 44 +++++++++---------- .../service/src/api/blockchain_api_service.rs | 6 +-- tools/local-network/local_network.py | 4 +- 6 files changed, 70 insertions(+), 46 deletions(-) diff --git a/consensus/enclave/api/src/config.rs b/consensus/enclave/api/src/config.rs index d63a6ce463..6e4afac91d 100644 --- a/consensus/enclave/api/src/config.rs +++ b/consensus/enclave/api/src/config.rs @@ -97,21 +97,21 @@ mod test { #[test] fn different_fee_maps_result_in_different_responder_ids() { let config1: BlockchainConfigWithDigest = BlockchainConfig { - fee_map: FeeMap::try_from_iter([(Mob::ID, 1000), (TokenId::from(2), 2000)]).unwrap(), + fee_map: FeeMap::try_from_iter([(Mob::ID, 1024), (TokenId::from(2), 2048)]).unwrap(), governors_map: GovernorsMap::default(), governors_signature: None, block_version: BlockVersion::ZERO, } .into(); let config2: BlockchainConfigWithDigest = BlockchainConfig { - fee_map: FeeMap::try_from_iter([(Mob::ID, 1000), (TokenId::from(2), 300)]).unwrap(), + fee_map: FeeMap::try_from_iter([(Mob::ID, 1024), (TokenId::from(2), 384)]).unwrap(), governors_map: GovernorsMap::default(), governors_signature: None, block_version: BlockVersion::ZERO, } .into(); let config3: BlockchainConfigWithDigest = BlockchainConfig { - fee_map: FeeMap::try_from_iter([(Mob::ID, 1000), (TokenId::from(30), 300)]).unwrap(), + fee_map: FeeMap::try_from_iter([(Mob::ID, 1024), (TokenId::from(30), 384)]).unwrap(), governors_map: GovernorsMap::default(), governors_signature: None, block_version: BlockVersion::ZERO, @@ -147,7 +147,7 @@ mod test { ); let config4: BlockchainConfigWithDigest = BlockchainConfig { - fee_map: FeeMap::try_from_iter([(Mob::ID, 200), (TokenId::from(30), 300)]).unwrap(), + fee_map: FeeMap::try_from_iter([(Mob::ID, 256), (TokenId::from(30), 384)]).unwrap(), governors_map: GovernorsMap::default(), governors_signature: None, block_version: BlockVersion::ONE, diff --git a/consensus/enclave/api/src/fee_map.rs b/consensus/enclave/api/src/fee_map.rs index 512d6b653e..246dc76433 100644 --- a/consensus/enclave/api/src/fee_map.rs +++ b/consensus/enclave/api/src/fee_map.rs @@ -112,7 +112,14 @@ impl FeeMap { .iter() .find(|(_token_id, fee)| (**fee >> SMALLEST_MINIMUM_FEE_LOG2) == 0) { - return Err(Error::InvalidFee(*token_id, *fee)); + return Err(Error::InvalidFeeTooSmall(*token_id, *fee)); + } + + if let Some((token_id, fee)) = minimum_fees + .iter() + .find(|(_token_id, fee)| (**fee % (1 << SMALLEST_MINIMUM_FEE_LOG2)) != 0) + { + return Err(Error::InvalidFeeNotDivisible(*token_id, *fee)); } // Must have a minimum fee for MOB. @@ -140,8 +147,11 @@ impl FeeMap { /// Fee Map error type. #[derive(Clone, Debug, Deserialize, Display, PartialEq, PartialOrd, Serialize)] pub enum Error { - /// Token `{0}` has invalid fee `{1}` - InvalidFee(TokenId, u64), + /// Token `{0}` has invalid fee (too small) `{1}` + InvalidFeeTooSmall(TokenId, u64), + + /// Token `{0}` has invalid fee (not divisible) `{1}` + InvalidFeeNotDivisible(TokenId, u64), /// Token `{0}` is missing from the fee map MissingFee(TokenId), @@ -155,13 +165,13 @@ mod test { /// Valid fee maps ids should be accepted #[test] fn valid_fee_maps_accepted() { - let fee_map1 = FeeMap::try_from_iter([(Mob::ID, 1000), (TokenId::from(2), 20000)]).unwrap(); + let fee_map1 = FeeMap::try_from_iter([(Mob::ID, 1024), (TokenId::from(2), 80000)]).unwrap(); assert!(fee_map1.get_fee_for_token(&Mob::ID).is_some()); - let fee_map2 = FeeMap::try_from_iter([(Mob::ID, 1000), (TokenId::from(2), 3000)]).unwrap(); + let fee_map2 = FeeMap::try_from_iter([(Mob::ID, 1024), (TokenId::from(2), 3072)]).unwrap(); assert!(fee_map2.get_fee_for_token(&Mob::ID).is_some()); - let fee_map3 = FeeMap::try_from_iter([(Mob::ID, 1000), (TokenId::from(30), 3000)]).unwrap(); + let fee_map3 = FeeMap::try_from_iter([(Mob::ID, 1024), (TokenId::from(30), 3072)]).unwrap(); assert!(fee_map3.get_fee_for_token(&Mob::ID).is_some()); } @@ -177,27 +187,38 @@ mod test { ); assert_eq!( - FeeMap::is_valid_map(&BTreeMap::from_iter(vec![(test_token_id, 1000)])), + FeeMap::is_valid_map(&BTreeMap::from_iter(vec![(test_token_id, 1024)])), Err(Error::MissingFee(Mob::ID)), ); // All fees must be >0 assert_eq!( FeeMap::is_valid_map(&BTreeMap::from_iter(vec![(Mob::ID, 0)])), - Err(Error::InvalidFee(Mob::ID, 0)), + Err(Error::InvalidFeeTooSmall(Mob::ID, 0)), ); assert_eq!( FeeMap::is_valid_map(&BTreeMap::from_iter(vec![(Mob::ID, 10)])), - Err(Error::InvalidFee(Mob::ID, 10)), + Err(Error::InvalidFeeTooSmall(Mob::ID, 10)), ); assert_eq!( FeeMap::is_valid_map(&BTreeMap::from_iter(vec![ - (Mob::ID, 1000), + (Mob::ID, 1024), (test_token_id, 0) ])), - Err(Error::InvalidFee(test_token_id, 0)), + Err(Error::InvalidFeeTooSmall(test_token_id, 0)), + ); + + // All fees must be evenly divisible by smallest minimum fee + assert_eq!( + FeeMap::try_from_iter([(Mob::ID, 1023), (TokenId::from(2), 80000)]), + Err(Error::InvalidFeeNotDivisible(Mob::ID, 1023)) + ); + + assert_eq!( + FeeMap::try_from_iter([(Mob::ID, 1024), (TokenId::from(2), 80001)]), + Err(Error::InvalidFeeNotDivisible(TokenId::from(2), 80001)) ); } } diff --git a/consensus/enclave/impl/src/lib.rs b/consensus/enclave/impl/src/lib.rs index 4719d0dc93..8cade02fae 100644 --- a/consensus/enclave/impl/src/lib.rs +++ b/consensus/enclave/impl/src/lib.rs @@ -45,7 +45,7 @@ use mc_common::{ ResponderId, }; use mc_consensus_enclave_api::{ - BlockchainConfig, BlockchainConfigWithDigest, ConsensusEnclave, Error, FeePublicKey, + BlockchainConfig, BlockchainConfigWithDigest, ConsensusEnclave, Error, FeeMap, FeePublicKey, FormBlockInputs, GovernorsVerifier, LocallyEncryptedTx, Result, SealedBlockSigningKey, TxContext, WellFormedEncryptedTx, WellFormedTxContext, SMALLEST_MINIMUM_FEE_LOG2, }; @@ -446,6 +446,9 @@ impl ConsensusEnclave for SgxConsensusEnclave { sealed_key: &Option, blockchain_config: BlockchainConfig, ) -> Result<(SealedBlockSigningKey, Vec)> { + // Check that fee map is actually well formed + FeeMap::is_valid_map(blockchain_config.fee_map.as_ref()).map_err(Error::FeeMap)?; + // Validate governors signature. if !blockchain_config.governors_map.is_empty() { let signature = blockchain_config @@ -1469,9 +1472,9 @@ mod tests { let blockchain_config = BlockchainConfig { block_version, fee_map: FeeMap::try_from_iter([ - (Mob::ID, 1000000), - (token_id1, 1000), - (token_id2, 1000), + (Mob::ID, 2_000_000), + (token_id1, 1024), + (token_id2, 1024), ]) .unwrap(), ..Default::default() diff --git a/consensus/service/config/src/tokens.rs b/consensus/service/config/src/tokens.rs index 38e77b5a99..0e739a9a9c 100644 --- a/consensus/service/config/src/tokens.rs +++ b/consensus/service/config/src/tokens.rs @@ -342,13 +342,13 @@ mod tests { let input_toml: &str = r#" [[tokens]] token_id = 1 - minimum_fee = 123000 + minimum_fee = 128000 "#; let tokens: TokensConfig = toml::from_str(input_toml).expect("failed parsing toml"); let input_json: &str = r#"{ "tokens": [ - { "token_id": 1, "minimum_fee": 123000 } + { "token_id": 1, "minimum_fee": 128000 } ] }"#; let tokens2: TokensConfig = serde_json::from_str(input_json).expect("failed parsing json"); @@ -385,13 +385,13 @@ mod tests { let input_toml: &str = r#" [[tokens]] token_id = 0 - minimum_fee = 123000 + minimum_fee = 128000 "#; let tokens: TokensConfig = toml::from_str(input_toml).expect("failed parsing toml"); let input_json: &str = r#"{ "tokens": [ - { "token_id": 0, "minimum_fee": 123000 } + { "token_id": 0, "minimum_fee": 128000 } ] }"#; let tokens2: TokensConfig = serde_json::from_str(input_json).expect("failed parsing json"); @@ -401,7 +401,7 @@ mod tests { assert!(tokens.validate().is_ok()); assert_eq!( tokens.get_token_config(&Mob::ID).unwrap().minimum_fee, - Some(123000) + Some(128000) ); // A random token id does not exist. @@ -447,18 +447,18 @@ mod tests { let input_toml: &str = r#" [[tokens]] token_id = 0 - minimum_fee = 123000 + minimum_fee = 128000 [[tokens]] token_id = 6 - minimum_fee = 456000 + minimum_fee = 512000 "#; let tokens: TokensConfig = toml::from_str(input_toml).expect("failed parsing toml"); let input_json: &str = r#"{ "tokens": [ - { "token_id": 0, "minimum_fee": 123000 }, - { "token_id": 6, "minimum_fee": 456000 } + { "token_id": 0, "minimum_fee": 128000 }, + { "token_id": 6, "minimum_fee": 512000 } ] }"#; let tokens2: TokensConfig = serde_json::from_str(input_json).expect("failed parsing json"); @@ -472,20 +472,20 @@ mod tests { .get_token_config(&Mob::ID) .unwrap() .minimum_fee_or_default(), - Some(123000) + Some(128000) ); assert_eq!( tokens .get_token_config(&test_token) .unwrap() .minimum_fee_or_default(), - Some(456000) + Some(512000) ); // Fee map looks good. assert_eq!( tokens.fee_map().unwrap(), - FeeMap::try_from_iter(vec![(Mob::ID, 123000), (test_token, 456000)]).unwrap(), + FeeMap::try_from_iter(vec![(Mob::ID, 128000), (test_token, 512000)]).unwrap(), ); // A random token id does not exist. @@ -501,14 +501,14 @@ mod tests { [[tokens]] token_id = 6 - minimum_fee = 456000 + minimum_fee = 512000 "#; let tokens: TokensConfig = toml::from_str(input_toml).expect("failed parsing toml"); let input_json: &str = r#"{ "tokens": [ { "token_id": 0 }, - { "token_id": 6, "minimum_fee": 456000 } + { "token_id": 6, "minimum_fee": 512000 } ] }"#; let tokens2: TokensConfig = serde_json::from_str(input_json).expect("failed parsing json"); @@ -529,13 +529,13 @@ mod tests { .get_token_config(&test_token) .unwrap() .minimum_fee_or_default(), - Some(456000) + Some(512000) ); // Fee map looks good. assert_eq!( tokens.fee_map().unwrap(), - FeeMap::try_from_iter(vec![(Mob::ID, Mob::MINIMUM_FEE), (test_token, 456000)]).unwrap(), + FeeMap::try_from_iter(vec![(Mob::ID, Mob::MINIMUM_FEE), (test_token, 512000)]).unwrap(), ); // A random token id does not exist. @@ -548,7 +548,7 @@ mod tests { let input_toml: &str = r#" [[tokens]] token_id = 0 - minimum_fee = 123000 + minimum_fee = 128000 [[tokens]] token_id = 6 @@ -557,7 +557,7 @@ mod tests { let input_json: &str = r#"{ "tokens": [ - { "token_id": 0, "minimum_fee": 123000 }, + { "token_id": 0, "minimum_fee": 128000 }, { "token_id": 6 } ] }"#; @@ -581,7 +581,7 @@ mod tests { [[tokens]] token_id = 1 - minimum_fee = 123000 + minimum_fee = 128000 allow_any_fee = true "#; let tokens: TokensConfig = toml::from_str(input_toml).expect("failed parsing toml"); @@ -589,7 +589,7 @@ mod tests { let input_json: &str = r#"{ "tokens": [ { "token_id": 0 }, - { "token_id": 1, "minimum_fee": 123000, "allow_any_fee": true } + { "token_id": 1, "minimum_fee": 128000, "allow_any_fee": true } ] }"#; let tokens2: TokensConfig = serde_json::from_str(input_json).expect("failed parsing json"); @@ -872,11 +872,11 @@ mod tests { [[tokens]] token_id = 1 - minimum_fee = 123000 + minimum_fee = 128000 [[tokens]] token_id = 1 - minimum_fee = 123000 + minimum_fee = 128000 "#; let tokens: TokensConfig = toml::from_str(input_toml).expect("failed parsing toml"); diff --git a/consensus/service/src/api/blockchain_api_service.rs b/consensus/service/src/api/blockchain_api_service.rs index df296c612c..92428a6ed7 100644 --- a/consensus/service/src/api/blockchain_api_service.rs +++ b/consensus/service/src/api/blockchain_api_service.rs @@ -223,7 +223,7 @@ mod tests { // `get_last_block_info` should returns the last block. fn test_get_last_block_info(logger: Logger) { let fee_map = - FeeMap::try_from_iter([(Mob::ID, 12345), (TokenId::from(60), 10203040)]).unwrap(); + FeeMap::try_from_iter([(Mob::ID, 4000000000), (TokenId::from(60), 128000)]).unwrap(); let mut ledger_db = create_ledger(); let authenticator = Arc::new(AnonymousAuthenticator::default()); @@ -239,8 +239,8 @@ mod tests { let mut expected_response = LastBlockInfoResponse::new(); expected_response.set_index(block_entities.last().unwrap().index); - expected_response.set_mob_minimum_fee(12345); - expected_response.set_minimum_fees(HashMap::from_iter(vec![(0, 12345), (60, 10203040)])); + expected_response.set_mob_minimum_fee(4000000000); + expected_response.set_minimum_fees(HashMap::from_iter(vec![(0, 4000000000), (60, 128000)])); expected_response.set_network_block_version(*BlockVersion::MAX); assert_eq!( block_entities.last().unwrap().index, diff --git a/tools/local-network/local_network.py b/tools/local-network/local_network.py index abd50591df..183df7e372 100755 --- a/tools/local-network/local_network.py +++ b/tools/local-network/local_network.py @@ -222,7 +222,7 @@ def start(self, network): { "token_id": 0, "minimum_fee": self.minimum_fee }, { "token_id": 1, - "minimum_fee": 1000, + "minimum_fee": 1024, "governors": { "signers": open(os.path.join(MINTING_KEYS_DIR, 'governor1.pub')).read(), "threshold": 1 @@ -230,7 +230,7 @@ def start(self, network): }, { "token_id": 2, - "minimum_fee": 1000, + "minimum_fee": 1024, "governors": { "signers": open(os.path.join(MINTING_KEYS_DIR, 'governor2.pub')).read(), "threshold": 1 From 19f0aeb8625e865f4ce992b7d40427774ba33936 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Mon, 16 May 2022 11:07:41 -0600 Subject: [PATCH 06/77] Mark fee_token_id as `omit_when = 0` (#1978) The fee token id, which is a new field in 1.2, needs to be marked `omit_when = 0`, otherwise there is no way for clients to be compatible with 1.1 and 1.2. This needs to be done whenever we add a numeric field to a proto that is hashed into the blockchain, otherwise the schema evolution strategy for hashing doesn't work. (It really should have been the default for hashing integers, because it's so easy to miss this, but it's probably too late to change that now.) --- transaction/core/src/tx.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/transaction/core/src/tx.rs b/transaction/core/src/tx.rs index 140e0d31bb..b8c41dd0ff 100644 --- a/transaction/core/src/tx.rs +++ b/transaction/core/src/tx.rs @@ -166,6 +166,7 @@ pub struct TxPrefix { /// Token id for this transaction #[prost(fixed64, tag = "5")] + #[digestible(omit_when = 0)] pub fee_token_id: u64, } From e4f41d189d130a69c1065715c3e47ecabfd7abe2 Mon Sep 17 00:00:00 2001 From: Bernie Dolan Date: Mon, 16 May 2022 16:25:30 -0400 Subject: [PATCH 07/77] TransactionBuilder TxOutContext (#1966) * add_output returns TxOutContext * Overloading modified tx builder functions for compatibility * Add TxOutContext to transaction_std lib.rs so its scope is automatically included in its import. Make individual variables in new struct public (may not be optimal fix). Update binding functions in libmobilecoin to use the new context based add_change_output/add_output calls to the transaction builder, and add a new "out" parameter to each of those ffi bindings so the SDK can consume the shared_secret. * add documentation to TxOutContext variables. Change copy out semantics for shared_secret in the add_change and add_ouput ffi binding functions. * Android Bindings TxOutContext TransactionBuilder add_output returns TxOutContext * Removing comments * Lint * Lint * Fixing test * Fixing test * Remove duplicated add_output and add_change_output * Update libmobilecoin/include/transaction.h Co-authored-by: Remoun Metyas * Update libmobilecoin/include/transaction.h Co-authored-by: Remoun Metyas * Struct deconstruction to fix build error * Fixing imports * Deconstructing more structs * Fixing syntax * Fixing tests * Remove references to old new functions * Fixing struct deconstruction * Test fix * Test fixes * Imports * Fixing test imports * Lint Co-authored-by: Alex Voloshyn Co-authored-by: the-real-adammork Co-authored-by: Remoun Metyas --- android-bindings/src/bindings.rs | 76 +++++++++++++++++++--- libmobilecoin/include/transaction.h | 6 +- libmobilecoin/libmobilecoin_cbindgen.h | 2 + libmobilecoin/src/transaction.rs | 28 ++++++-- mobilecoind/src/payments.rs | 9 ++- mobilecoind/src/service.rs | 14 ++-- transaction/std/src/lib.rs | 4 +- transaction/std/src/transaction_builder.rs | 70 ++++++++++++++------ 8 files changed, 164 insertions(+), 45 deletions(-) diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index 98a54b9368..b393a50224 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -54,7 +54,7 @@ use mc_transaction_core::{ use mc_transaction_std::{ AuthenticatedSenderMemo, AuthenticatedSenderWithPaymentRequestIdMemo, ChangeDestination, DestinationMemo, InputCredentials, MemoBuilder, MemoPayload, RTHMemoBuilder, - SenderMemoCredential, TransactionBuilder, + SenderMemoCredential, TransactionBuilder, TxOutContext, }; use mc_util_from_random::FromRandom; @@ -1478,6 +1478,65 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOut_decrypt_1memo_1payload( ) } +/******************************************************************** + * TxOutContext + */ +#[no_mangle] +pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOutContext_get_1tx_1out( + env: JNIEnv, + obj: JObject, +) -> jlong { + jni_ffi_call_or( + || Ok(0), + &env, + |env| { + let tx_out_context: MutexGuard = + env.get_rust_field(obj, RUST_OBJ_FIELD)?; + let tx_out = tx_out_context.tx_out.to_owned(); + let mbox = Box::new(Mutex::new(tx_out)); + let ptr: *mut Mutex = Box::into_raw(mbox); + Ok(ptr as jlong) + }, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOutContext_get_1confirmation_1number( + env: JNIEnv, + obj: JObject, +) -> jbyteArray { + jni_ffi_call_or( + || Ok(JObject::null().into_inner()), + &env, + |env| { + let tx_out_context: MutexGuard = + env.get_rust_field(obj, RUST_OBJ_FIELD)?; + let confirmation_number = &tx_out_context.confirmation; + let bytes = mc_util_serial::encode(confirmation_number); + Ok(env.byte_array_from_slice(&bytes)?) + }, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOutContext_get_1shared_1secret( + env: JNIEnv, + obj: JObject, +) -> jlong { + jni_ffi_call_or( + || Ok(0), + &env, + |env| { + let tx_out_context: MutexGuard = + env.get_rust_field(obj, RUST_OBJ_FIELD)?; + let shared_secret = tx_out_context.shared_secret.to_owned(); + let mbox = Box::new(Mutex::new(shared_secret)); + let ptr: *mut Mutex = Box::into_raw(mbox); + Ok(ptr as jlong) + }, + ) +} + /******************************************************************** * TxOutMembershipProof */ @@ -1713,8 +1772,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_add_1output( env.get_rust_field(recipient, RUST_OBJ_FIELD)?; let mut rng = McRng::default(); - let (tx_out, confirmation_number) = - tx_builder.add_output(value as u64, &recipient, &mut rng)?; + let tx_out_context = tx_builder.add_output(value as u64, &recipient, &mut rng)?; + let confirmation_number = &tx_out_context.confirmation; if !confirmation_number_out.is_null() { let len = env.get_array_length(confirmation_number_out)?; if len as usize >= confirmation_number.to_vec().len() { @@ -1731,8 +1790,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_add_1output( } } - let mbox = Box::new(Mutex::new(tx_out)); - let ptr: *mut Mutex = Box::into_raw(mbox); + let mbox = Box::new(Mutex::new(tx_out_context)); + let ptr: *mut Mutex = Box::into_raw(mbox); Ok(ptr as jlong) }, ) @@ -1760,8 +1819,9 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_add_1change_ ChangeDestination::from(&*source_account_key); let mut rng = McRng::default(); - let (tx_out, confirmation_number) = + let tx_out_context = tx_builder.add_change_output(value, &change_destination, &mut rng)?; + let confirmation_number = &tx_out_context.confirmation; if !confirmation_number_out.is_null() { let len = env.get_array_length(confirmation_number_out)?; if len as usize >= confirmation_number.to_vec().len() { @@ -1778,8 +1838,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_add_1change_ } } - let mbox = Box::new(Mutex::new(tx_out)); - let ptr: *mut Mutex = Box::into_raw(mbox); + let mbox = Box::new(Mutex::new(tx_out_context)); + let ptr: *mut Mutex = Box::into_raw(mbox); Ok(ptr as jlong) }, ) diff --git a/libmobilecoin/include/transaction.h b/libmobilecoin/include/transaction.h index 37b748466e..0c5f2a2810 100644 --- a/libmobilecoin/include/transaction.h +++ b/libmobilecoin/include/transaction.h @@ -216,9 +216,10 @@ McData* MC_NULLABLE mc_transaction_builder_add_output( const McPublicAddress* MC_NONNULL recipient_address, McRngCallback* MC_NULLABLE rng_callback, McMutableBuffer* MC_NONNULL out_tx_out_confirmation_number, + McMutableBuffer* MC_NONNULL out_tx_out_shared_secret, McError* MC_NULLABLE * MC_NULLABLE out_error ) -MC_ATTRIBUTE_NONNULL(1, 3, 6); +MC_ATTRIBUTE_NONNULL(1, 3, 5, 6); /// # Preconditions /// @@ -237,9 +238,10 @@ McData* MC_NULLABLE mc_transaction_builder_add_change_output( uint64_t amount, McRngCallback* MC_NULLABLE rng_callback, McMutableBuffer* MC_NONNULL out_tx_out_confirmation_number, + McMutableBuffer* MC_NONNULL out_tx_out_shared_secret, McError* MC_NULLABLE * MC_NULLABLE out_error ) -MC_ATTRIBUTE_NONNULL(1, 2, 4, 6); +MC_ATTRIBUTE_NONNULL(1, 2, 4, 5, 6); /// # Preconditions /// diff --git a/libmobilecoin/libmobilecoin_cbindgen.h b/libmobilecoin/libmobilecoin_cbindgen.h index a1deb37e5e..67cea067d3 100644 --- a/libmobilecoin/libmobilecoin_cbindgen.h +++ b/libmobilecoin/libmobilecoin_cbindgen.h @@ -785,6 +785,7 @@ FfiOptOwnedPtr mc_transaction_builder_add_output(FfiMutPtr recipient_address, FfiOptMutPtr rng_callback, FfiMutPtr out_tx_out_confirmation_number, + FfiMutPtr out_tx_out_shared_secret, FfiOptMutPtr> out_error); /** @@ -806,6 +807,7 @@ FfiOptOwnedPtr mc_transaction_builder_add_change_output(FfiRefPtr rng_callback, FfiMutPtr out_tx_out_confirmation_number, + FfiMutPtr out_tx_out_shared_secret, FfiOptMutPtr> out_error); /** diff --git a/libmobilecoin/src/transaction.rs b/libmobilecoin/src/transaction.rs index 747aaf4a7d..d6c3779120 100644 --- a/libmobilecoin/src/transaction.rs +++ b/libmobilecoin/src/transaction.rs @@ -481,6 +481,7 @@ pub extern "C" fn mc_transaction_builder_add_output( recipient_address: FfiRefPtr, rng_callback: FfiOptMutPtr, out_tx_out_confirmation_number: FfiMutPtr, + out_tx_out_shared_secret: FfiMutPtr, out_error: FfiOptMutPtr>, ) -> FfiOptOwnedPtr { ffi_boundary_with_error(out_error, || { @@ -496,11 +497,18 @@ pub extern "C" fn mc_transaction_builder_add_output( .as_slice_mut_of_len(TxOutConfirmationNumber::size()) .expect("out_tx_out_confirmation_number length is insufficient"); - let (tx_out, confirmation) = + let tx_out_context = transaction_builder.add_output(amount, &recipient_address, &mut rng)?; - out_tx_out_confirmation_number.copy_from_slice(confirmation.as_ref()); - Ok(mc_util_serial::encode(&tx_out)) + out_tx_out_confirmation_number.copy_from_slice(tx_out_context.confirmation.as_ref()); + + let out_tx_out_shared_secret = out_tx_out_shared_secret + .into_mut() + .as_slice_mut_of_len(RistrettoPublic::size()) + .expect("out_tx_out_shared_secret length is insufficient"); + + out_tx_out_shared_secret.copy_from_slice(&tx_out_context.shared_secret.to_bytes()); + Ok(mc_util_serial::encode(&tx_out_context.tx_out)) }) } @@ -523,6 +531,7 @@ pub extern "C" fn mc_transaction_builder_add_change_output( amount: u64, rng_callback: FfiOptMutPtr, out_tx_out_confirmation_number: FfiMutPtr, + out_tx_out_shared_secret: FfiMutPtr, out_error: FfiOptMutPtr>, ) -> FfiOptOwnedPtr { ffi_boundary_with_error(out_error, || { @@ -539,11 +548,18 @@ pub extern "C" fn mc_transaction_builder_add_change_output( .as_slice_mut_of_len(TxOutConfirmationNumber::size()) .expect("out_tx_out_confirmation_number length is insufficient"); - let (tx_out, confirmation) = + let tx_out_context = transaction_builder.add_change_output(amount, &change_destination, &mut rng)?; - out_tx_out_confirmation_number.copy_from_slice(confirmation.as_ref()); - Ok(mc_util_serial::encode(&tx_out)) + out_tx_out_confirmation_number.copy_from_slice(tx_out_context.confirmation.as_ref()); + + let out_tx_out_shared_secret = out_tx_out_shared_secret + .into_mut() + .as_slice_mut_of_len(RistrettoPublic::size()) + .expect("out_tx_out_shared_secret length is insufficient"); + + out_tx_out_shared_secret.copy_from_slice(&tx_out_context.shared_secret.to_bytes()); + Ok(mc_util_serial::encode(&tx_out_context.tx_out)) }) } diff --git a/mobilecoind/src/payments.rs b/mobilecoind/src/payments.rs index cee5b5681d..f94b4fab8d 100644 --- a/mobilecoind/src/payments.rs +++ b/mobilecoind/src/payments.rs @@ -25,6 +25,7 @@ use mc_transaction_core::{ }; use mc_transaction_std::{ ChangeDestination, EmptyMemoBuilder, InputCredentials, MemoBuilder, TransactionBuilder, + TxOutContext, }; use mc_util_uri::FogUri; use rand::Rng; @@ -970,12 +971,16 @@ impl TransactionBuilder { value: u64, recipient: &PublicAddress, rng: &mut RNG, - ) -> Result<(TxOut, TxOutConfirmationNumber), TxBuilderError> { + ) -> Result { // Taking self.memo_builder here means that we can call functions on &mut self, // and pass them something that has captured the memo builder. // Calling take() on Option is just moving a pointer. @@ -207,7 +222,7 @@ impl TransactionBuilder { value: u64, change_destination: &ChangeDestination, rng: &mut RNG, - ) -> Result<(TxOut, TxOutConfirmationNumber), TxBuilderError> { + ) -> Result { // Taking self.memo_builder here means that we can call functions on &mut self, // and pass them something that has captured the memo builder. // Calling take() on Option is just moving a pointer. @@ -265,7 +280,7 @@ impl TransactionBuilder { fog_hint_address: &PublicAddress, memo_fn: impl FnOnce(MemoContext) -> Result, NewMemoError>, rng: &mut RNG, - ) -> Result<(TxOut, TxOutConfirmationNumber), TxBuilderError> { + ) -> Result { let (hint, pubkey_expiry) = create_fog_hint(fog_hint_address, &self.fog_resolver, rng)?; let amount = Amount { value, @@ -281,7 +296,11 @@ impl TransactionBuilder { let confirmation = TxOutConfirmationNumber::from(&shared_secret); - Ok((tx_out, confirmation)) + Ok(TxOutContext { + tx_out, + confirmation, + shared_secret, + }) } /// Sets the tombstone block, clamping to smallest pubkey expiry value. @@ -792,7 +811,7 @@ pub mod transaction_builder_tests { .unwrap(); transaction_builder.add_input(input_credentials); - let (_txout, confirmation) = transaction_builder + let TxOutContext { confirmation, .. } = transaction_builder .add_output( value - Mob::MINIMUM_FEE, &recipient.default_subaddress(), @@ -875,7 +894,7 @@ pub mod transaction_builder_tests { .unwrap(); transaction_builder.add_input(input_credentials); - let (_txout, confirmation) = transaction_builder + let TxOutContext { confirmation, .. } = transaction_builder .add_output( value - Mob::MINIMUM_FEE, &recipient.default_subaddress(), @@ -970,7 +989,7 @@ pub mod transaction_builder_tests { get_input_credentials(block_version, amount, &sender, &fog_resolver, &mut rng); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + let _tx_out_context = transaction_builder .add_output_with_fog_hint_address( value - Mob::MINIMUM_FEE, &recipient.default_subaddress(), @@ -1049,7 +1068,7 @@ pub mod transaction_builder_tests { get_input_credentials(block_version, amount, &sender, &fog_resolver, &mut rng); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output(value - Mob::MINIMUM_FEE, &recipient_address, &mut rng) .unwrap(); @@ -1081,7 +1100,7 @@ pub mod transaction_builder_tests { get_input_credentials(block_version, amount, &sender, &fog_resolver, &mut rng); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output(value - Mob::MINIMUM_FEE, &recipient_address, &mut rng) .unwrap(); @@ -1147,7 +1166,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -1325,7 +1344,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -1484,7 +1503,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE * 4, &recipient_address, @@ -1643,7 +1662,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -1802,7 +1821,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -1949,7 +1968,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -2121,7 +2140,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &bob_address, @@ -2310,7 +2329,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -2578,7 +2597,10 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (burn_tx_out, _confirmation) = transaction_builder + let TxOutContext { + tx_out: burn_tx_out, + .. + } = transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient, @@ -2740,7 +2762,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_burn_tx_out, _confirmation) = transaction_builder + transaction_builder .add_output(100, &burn_address(), &mut rng) .unwrap(); @@ -2783,7 +2805,10 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (burn_output, _confirmation) = transaction_builder + let TxOutContext { + tx_out: burn_output, + .. + } = transaction_builder .add_output(110, &burn_address(), &mut rng) .unwrap(); @@ -2839,7 +2864,10 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (burn_tx_out, _confirmation) = transaction_builder + let TxOutContext { + tx_out: burn_tx_out, + .. + } = transaction_builder .add_output(100, &burn_address(), &mut rng) .unwrap(); From 65c3076b2c45a06dbef5f213e3983897ecf9403f Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 17 May 2022 17:51:06 -0700 Subject: [PATCH 08/77] Cherry-pick dependency and other changes to candidate-1.2 (#1992) * Update rust-toolchain to nightly-2022-04-29 (#1888) * Update rust-toolchain version * Fix clippy warnings * Write an integration test for mobilecoind-json (#1885) * Write an integration test for mobilecoind-json * sort * enable test * spaces * move wait_for_monitor_to_sync down * DRY * Update mobilecoind/strategies/test_client.py Co-authored-by: Remoun Metyas * Update mobilecoind/strategies/drain-accounts.py Co-authored-by: Remoun Metyas Co-authored-by: Remoun Metyas * Bump libc from 0.2.124 to 0.2.125 (#1887) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.124 to 0.2.125. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.124...0.2.125) --- updated-dependencies: - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump syn from 1.0.91 to 1.0.92 (#1886) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.91 to 1.0.92. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.91...1.0.92) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump serde from 1.0.136 to 1.0.137 in /fog/ledger/enclave/trusted (#1894) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.136 to 1.0.137. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.136...v1.0.137) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump serde from 1.0.136 to 1.0.137 in /fog/view/enclave/trusted (#1895) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.136 to 1.0.137. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.136...v1.0.137) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump serde from 1.0.136 to 1.0.137 in /consensus/enclave/trusted (#1897) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.136 to 1.0.137. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.136...v1.0.137) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump serde from 1.0.136 to 1.0.137 in /fog/ingest/enclave/trusted (#1901) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.136 to 1.0.137. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.136...v1.0.137) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump serde from 1.0.136 to 1.0.137 (#1903) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.136 to 1.0.137. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.136...v1.0.137) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump semver from 1.0.7 to 1.0.9 (#1900) Bumps [semver](https://github.com/dtolnay/semver) from 1.0.7 to 1.0.9. - [Release notes](https://github.com/dtolnay/semver/releases) - [Commits](https://github.com/dtolnay/semver/compare/1.0.7...1.0.9) --- updated-dependencies: - dependency-name: semver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump zeroize from 1.5.4 to 1.5.5 in /fog/view/enclave/trusted (#1896) Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.5.4 to 1.5.5. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/compare/zeroize-v1.5.4...zeroize-v1.5.5) --- updated-dependencies: - dependency-name: zeroize dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump zeroize from 1.5.4 to 1.5.5 in /consensus/enclave/trusted (#1898) Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.5.4 to 1.5.5. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/compare/zeroize-v1.5.4...zeroize-v1.5.5) --- updated-dependencies: - dependency-name: zeroize dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump zeroize from 1.5.4 to 1.5.5 in /fog/ingest/enclave/trusted (#1899) Bumps [zeroize](https://github.com/RustCrypto/utils) from 1.5.4 to 1.5.5. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/compare/zeroize-v1.5.4...zeroize-v1.5.5) --- updated-dependencies: - dependency-name: zeroize dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Dependency updates (Part 1) (#1908) * Update regex in consensus enclave to 1.5.5 * Update crossbeam utils 0.8.5 to 0.8.8 * Update generic-array 0.12.3 to 0.12.4 * Update hyper from 0.12.35 to 0.12.36 * Update hyper 0.14.16 to 0.14.18 * Ran cargo update against protoc, somehow log is back to the right version. * Update log to 0.4.17. * Fix protoc again... * Switch to using our fork of opentelemetry. (#1918) This was needed since we had to upgrade opentelemetry-jaeger's dependency on thrift, which in turn depended on a broken verison of ordered-float. * Upgrade to rocket 0.5.0-rc (#1913) * mobilecoind-json uses new(er) rocket * admin gw uses newer rocket * fog-overseer-server uses newer rocket * Bump clap from 3.1.12 to 3.1.15 (#1904) Bumps [clap](https://github.com/clap-rs/clap) from 3.1.12 to 3.1.15. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v3.1.12...v3.1.15) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * no need for 10 subaddresses, and this also makes the test compatible with the drain_accounts.py script (#1919) * Bump libz-sys from 1.1.5 to 1.1.6 (#1873) Bumps [libz-sys](https://github.com/rust-lang/libz-sys) from 1.1.5 to 1.1.6. - [Release notes](https://github.com/rust-lang/libz-sys/releases) - [Commits](https://github.com/rust-lang/libz-sys/compare/1.1.5...1.1.6) --- updated-dependencies: - dependency-name: libz-sys dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * added extra configuration consensus service serve side. (#1800) * added extra configuration consensus service serve side. * fixed build errors * increased the allowed testime for testing * added one more method to set defaults * fixed compile error * linting issue * Update consensus/service/src/consensus_service.rs Co-authored-by: Remoun Metyas Co-authored-by: Eugene Rata Co-authored-by: Remoun Metyas * Bump zeroize from 1.5.4 to 1.5.5 (#1902) * Bump serde_json from 1.0.79 to 1.0.81 (#1916) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.79 to 1.0.81. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.79...v1.0.81) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump crc from 2.1.0 to 3.0.0 (#1857) * Bump crc from 2.1.0 to 3.0.0 Bumps [crc](https://github.com/mrhooray/crc-rs) from 2.1.0 to 3.0.0. - [Release notes](https://github.com/mrhooray/crc-rs/releases) - [Commits](https://github.com/mrhooray/crc-rs/compare/2.1.0...3.0.0) --- updated-dependencies: - dependency-name: crc dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update lock files Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nick Santana * Upgrade rusoto_s3 from 0.42 to 0.48. (#1912) Simplify type of retry result * Bump prost from 0.10.1 to 0.10.3 (#1930) * Bump prost from 0.10.1 to 0.10.3 Bumps [prost](https://github.com/tokio-rs/prost) from 0.10.1 to 0.10.3. - [Release notes](https://github.com/tokio-rs/prost/releases) - [Commits](https://github.com/tokio-rs/prost/compare/v0.10.1...v0.10.3) --- updated-dependencies: - dependency-name: prost dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Update util/keyfile/Cargo.toml Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Remoun Metyas * allow providing minting trust root public key via a PEM file instead hex bytes (#1951) * allow providing minting trust root public key via a PEM file instead of hex bytes * update lock file * make fog-resolver and ingest-report serializable (#1944) * Feature/attest verifier mc seed bugfix (#1943) * Bump proc-macro2 from 1.0.37 to 1.0.38 (#1938) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.37 to 1.0.38. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.37...1.0.38) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * reverting ledger-dist folder to work dir and work dir now in target dir (#1954) * Bump clap from 3.1.15 to 3.1.18 (#1957) Bumps [clap](https://github.com/clap-rs/clap) from 3.1.15 to 3.1.18. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v3.1.15...v3.1.18) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump syn from 1.0.92 to 1.0.93 (#1956) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.92 to 1.0.93. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.92...1.0.93) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump prost from 0.10.1 to 0.10.3 in /consensus/enclave/trusted (#1927) Bumps [prost](https://github.com/tokio-rs/prost) from 0.10.1 to 0.10.3. - [Release notes](https://github.com/tokio-rs/prost/releases) - [Commits](https://github.com/tokio-rs/prost/compare/v0.10.1...v0.10.3) --- updated-dependencies: - dependency-name: prost dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump prost from 0.10.1 to 0.10.3 in /fog/view/enclave/trusted (#1929) Bumps [prost](https://github.com/tokio-rs/prost) from 0.10.1 to 0.10.3. - [Release notes](https://github.com/tokio-rs/prost/releases) - [Commits](https://github.com/tokio-rs/prost/compare/v0.10.1...v0.10.3) --- updated-dependencies: - dependency-name: prost dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump prost from 0.10.1 to 0.10.3 in /fog/ingest/enclave/trusted (#1926) Bumps [prost](https://github.com/tokio-rs/prost) from 0.10.1 to 0.10.3. - [Release notes](https://github.com/tokio-rs/prost/releases) - [Commits](https://github.com/tokio-rs/prost/compare/v0.10.1...v0.10.3) --- updated-dependencies: - dependency-name: prost dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * MintTx/MintConfigTx tombstone validation bugfixes (#1964) * fix a bug that would cause MintTxs that depend on old MintConfigTxs to fail validation * fix off by one error in mint tx/mint config tx tombstone validation. also add a test for duplicate nonce * lint, fix tests * test boundary condiotion and update comment * Update consensus/service/src/mint_tx_manager/mod.rs Co-authored-by: Nick Santana * Update consensus/service/src/mint_tx_manager/mod.rs Co-authored-by: Nick Santana * make tombstone block check optional by passing an Option for the current block index, as suggested in the PR review Co-authored-by: Nick Santana * mint-client: make the process exitcode reflect transaction status returned from consensus when a transaction is submitted (#1967) * mint-client: make the process exitcode reflect transaction status returned from consensus when a transaction is submitted * add missing import * Update builder_install image (#1968) #1888 updated rust-toolchain without updating builder_install. * Remove bogus DATABASE_URL value * Add postgresql-client explicitly to init_debian.sh * Bump Dockerfile-version * Bump hashbrown from 0.11.2 to 0.12.1 (#1915) * Bump hashbrown from 0.11.2 to 0.12.1 Bumps [hashbrown](https://github.com/rust-lang/hashbrown) from 0.11.2 to 0.12.1. - [Release notes](https://github.com/rust-lang/hashbrown/releases) - [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/hashbrown/compare/v0.11.2...v0.12.1) --- updated-dependencies: - dependency-name: hashbrown dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Updating lock files for enclave crates Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nick Santana * Bump ed25519 from 1.4.1 to 1.5.0 (#1950) * Bump ed25519 from 1.4.1 to 1.5.0 Bumps [ed25519](https://github.com/RustCrypto/signatures) from 1.4.1 to 1.5.0. - [Release notes](https://github.com/RustCrypto/signatures/releases) - [Commits](https://github.com/RustCrypto/signatures/compare/ed25519/v1.4.1...ed25519/v1.5.0) --- updated-dependencies: - dependency-name: ed25519 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update Cargo.lock for enclave crates Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrew Wygle * Add a mint auditor integration test to be used in CD. (#1971) * Write a mint auditor integration test to be used in CD. accept command line args wip off by one debug * update comment * update fee amount * Update mint-auditor/tests/integration_test.py Co-authored-by: Remoun Metyas * Update mint-auditor/tests/integration_test.py Co-authored-by: Remoun Metyas Co-authored-by: Remoun Metyas * Bump syn from 1.0.93 to 1.0.94 (#1976) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.93 to 1.0.94. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.93...1.0.94) --- updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Remoun Metyas Co-authored-by: Eran Rundstein Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Eugen Rata Co-authored-by: Eugene Rata Co-authored-by: Nick Santana Co-authored-by: Brian Corbin Co-authored-by: Andrew Wygle --- .circleci/config.yml | 2 +- Cargo.lock | 2480 +++++++---------- admin-http-gateway/Cargo.toml | 3 +- admin-http-gateway/src/main.rs | 28 +- api/Cargo.toml | 2 +- attest/verifier/build.rs | 4 +- attest/verifier/data/sim/.gitignore | 2 +- common/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 + consensus/enclave/impl/build.rs | 36 +- consensus/enclave/impl/src/lib.rs | 36 +- consensus/enclave/trusted/Cargo.lock | 76 +- consensus/mint-client/Cargo.toml | 1 + consensus/mint-client/src/bin/main.rs | 23 +- consensus/scp/tests/mock_network/mod.rs | 2 +- consensus/service/src/consensus_service.rs | 3 +- consensus/service/src/mint_tx_manager/mod.rs | 258 +- consensus/service/src/validators.rs | 1 + crypto/keys/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- docker/Dockerfile | 1 - docker/Dockerfile-version | 2 +- docker/init_debian.sh | 1 + docker/rust-toolchain | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 40 +- fog/ledger/enclave/trusted/Cargo.lock | 36 +- fog/overseer/server/Cargo.toml | 3 +- fog/overseer/server/src/bin/main.rs | 13 +- fog/overseer/server/src/server.rs | 19 +- .../server/tests/get_ingest_summaries.rs | 17 +- ..._outstanding_key_idle_does_not_have_key.rs | 13 +- .../inactive_outstanding_key_idle_has_key.rs | 13 +- fog/overseer/server/tests/one_active_node.rs | 13 +- .../tests/prometheus_produces_metrics.rs | 17 +- ...t_outstanding_idles_have_different_keys.rs | 13 +- ...key_not_outstanding_idles_have_same_key.rs | 14 +- fog/report/validation/Cargo.toml | 1 + fog/report/validation/src/ingest_report.rs | 3 +- fog/report/validation/src/lib.rs | 3 +- fog/types/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 40 +- jenkins/build-pod.yaml | 2 +- ledger/distribution/Cargo.toml | 5 +- ledger/distribution/src/main.rs | 64 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/src/counters.rs | 2 +- mint-auditor/tests/compile_proto.sh | 19 + mint-auditor/tests/integration_test.py | 270 ++ mobilecoind-json/Cargo.toml | 3 +- mobilecoind-json/src/bin/main.rs | 78 +- mobilecoind-json/tests/integration_test.py | 192 ++ mobilecoind/Cargo.toml | 2 +- mobilecoind/src/utxo_store.rs | 4 +- mobilecoind/strategies/drain-accounts.py | 2 +- mobilecoind/strategies/test_client.py | 2 +- sgx/types/src/types.rs | 21 - tools/local-network/local_network.py | 4 +- transaction/core/Cargo.toml | 2 +- .../core/src/mint/validation/config.rs | 11 +- transaction/core/test-utils/src/mint.rs | 2 +- transaction/std/src/memo/macros.rs | 22 +- util/grpc/src/grpcio_extensions.rs | 20 +- util/keyfile/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 6 +- 64 files changed, 2066 insertions(+), 1902 deletions(-) create mode 100644 mint-auditor/tests/compile_proto.sh create mode 100644 mint-auditor/tests/integration_test.py create mode 100644 mobilecoind-json/tests/integration_test.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 197a52a6cd..d192be9f7e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ version: 2.1 defaults: - builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_26 + builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_27 android-bindings-builder: &android-bindings-builder gcr.io/mobilenode-211420/android-bindings-builder:1_4 default-xcode-version: &default-xcode-version "12.0.0" diff --git a/Cargo.lock b/Cargo.lock index e87a3b19eb..1982c96e62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,7 +29,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -42,7 +42,7 @@ dependencies = [ "cipher", "cpufeatures", "ctr", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -56,7 +56,7 @@ dependencies = [ "cipher", "ctr", "ghash", - "subtle 2.4.1", + "subtle", ] [[package]] @@ -74,8 +74,8 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e05c92d086290f52938013f6242ac62bf7d401fab8ad36798a609faa65c3fd2c" dependencies = [ - "generic-array 0.14.5", - "subtle 2.4.1", + "generic-array", + "subtle", ] [[package]] @@ -85,7 +85,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac09d3ea1089af7eb2784eca92ed14a41168352d47565f1eb1bdd23460909ba1" dependencies = [ "aligned-array", - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -94,7 +94,16 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.9", + "winapi", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", ] [[package]] @@ -115,12 +124,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arrayvec" version = "0.7.2" @@ -168,7 +171,28 @@ dependencies = [ "futures-core", "memchr", "pin-project-lite", - "tokio 1.16.1", + "tokio", +] + +[[package]] +name = "async-stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -177,9 +201,18 @@ version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" +dependencies = [ + "autocfg", ] [[package]] @@ -190,7 +223,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -225,29 +258,10 @@ dependencies = [ ] [[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "base64" -version = "0.11.0" +name = "base-x" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +checksum = "dc19a4937b4fbd3fe3379793130e42060d10627a360f2127802b10b87e7baf74" [[package]] name = "base64" @@ -293,13 +307,13 @@ dependencies = [ "env_logger 0.8.3", "lazy_static", "lazycell", - "log 0.4.14", + "log", "peeking_take_while", - "proc-macro2 1.0.37", - "quote 1.0.18", + "proc-macro2", + "quote", "regex", "rustc-hash", - "shlex 1.0.0", + "shlex", "which 3.1.1", ] @@ -316,13 +330,13 @@ dependencies = [ "env_logger 0.9.0", "lazy_static", "lazycell", - "log 0.4.14", + "log", "peeking_take_while", - "proc-macro2 1.0.37", - "quote 1.0.18", + "proc-macro2", + "quote", "regex", "rustc-hash", - "shlex 1.0.0", + "shlex", "which 4.2.4", ] @@ -362,36 +376,13 @@ dependencies = [ "digest 0.10.3", ] -[[package]] -name = "blake2b_simd" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.3", -] - [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -400,16 +391,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -453,7 +435,7 @@ dependencies = [ "serde", "serde_derive", "sha3", - "subtle 2.4.1", + "subtle", ] [[package]] @@ -462,12 +444,6 @@ version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "bytecount" version = "0.4.0" @@ -480,17 +456,6 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "either", - "iovec", -] - [[package]] name = "bytes" version = "0.5.4" @@ -554,7 +519,7 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.7", + "semver 1.0.9", "serde", "serde_json", ] @@ -580,17 +545,17 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b6d248e3ca02f3fbfabcb9284464c596baec223a26d91bbf44a5a62ddb0d900" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "heck", "indexmap", - "log 0.4.14", - "proc-macro2 1.0.37", - "quote 1.0.18", + "log", + "proc-macro2", + "quote", "serde", "serde_json", - "syn 1.0.91", + "syn", "tempfile", - "toml 0.5.9", + "toml", ] [[package]] @@ -646,7 +611,7 @@ dependencies = [ "num-traits", "serde", "time 0.1.43", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -655,7 +620,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -675,7 +640,7 @@ version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" dependencies = [ - "ansi_term", + "ansi_term 0.11.0", "atty", "bitflags", "strsim 0.8.0", @@ -686,9 +651,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.12" +version = "3.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c167e37342afc5f33fd87bbc870cedd020d2a6dffa05d45ccd9241fbdd146db" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" dependencies = [ "atty", "bitflags", @@ -703,22 +668,22 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.1.7" +version = "3.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "clap_lex" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" dependencies = [ "os_str_bytes", ] @@ -732,15 +697,6 @@ dependencies = [ "cc", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - [[package]] name = "cmake" version = "0.1.45" @@ -769,19 +725,20 @@ dependencies = [ ] [[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "const_fn" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" [[package]] name = "cookie" -version = "0.11.3" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5795cda0897252e34380a27baf884c53aa7ad9990329cdad96d4c5d027015d44" +checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d" dependencies = [ - "percent-encoding 2.1.0", - "time 0.1.43", + "percent-encoding", + "time 0.2.27", + "version_check", ] [[package]] @@ -791,9 +748,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" dependencies = [ "time 0.3.9", - "version_check 0.9.3", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "cpufeatures" version = "0.2.1" @@ -805,18 +778,18 @@ dependencies = [ [[package]] name = "crc" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" -version = "1.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" [[package]] name = "crc32fast" @@ -870,18 +843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" -dependencies = [ - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-utils", ] [[package]] @@ -891,23 +853,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.5", - "crossbeam-utils 0.8.5", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.4", - "scopeguard", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] @@ -917,57 +864,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils", "lazy_static", - "memoffset 0.6.4", + "memoffset", "scopeguard", ] -[[package]] -name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -dependencies = [ - "crossbeam-utils 0.6.6", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" -dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", -] - -[[package]] -name = "crossbeam-utils" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -dependencies = [ - "cfg-if 0.1.10", - "lazy_static", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", -] - [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if 1.0.0", "lazy_static", @@ -985,28 +892,28 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ - "generic-array 0.14.5", + "generic-array", "typenum", ] [[package]] name = "crypto-mac" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.12.3", - "subtle 1.0.0", + "generic-array", + "subtle", ] [[package]] name = "crypto-mac" -version = "0.8.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.5", - "subtle 2.4.1", + "generic-array", + "subtle", ] [[package]] @@ -1031,15 +938,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ct-logs" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" -dependencies = [ - "sct 0.6.0", -] - [[package]] name = "ctr" version = "0.8.0" @@ -1061,7 +959,7 @@ dependencies = [ "openssl-sys", "schannel", "socket2", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1076,7 +974,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1089,7 +987,7 @@ dependencies = [ "packed_simd_2", "rand_core 0.6.3", "serde", - "subtle 2.4.1", + "subtle", "zeroize", ] @@ -1105,9 +1003,9 @@ dependencies = [ [[package]] name = "devise" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e04ba2d03c5fa0d954c061fc8c9c288badadffc272ebb87679a89846de3ed3" +checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595" dependencies = [ "devise_codegen", "devise_core", @@ -1115,24 +1013,25 @@ dependencies = [ [[package]] name = "devise_codegen" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7" +checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2" dependencies = [ "devise_core", - "quote 0.6.13", + "quote", ] [[package]] name = "devise_core" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487" +checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0" dependencies = [ "bitflags", - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", ] [[package]] @@ -1156,9 +1055,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8910921b014e2af16298f006de12aa08af894b71f0f49a486ab6d74b17bbed" dependencies = [ "heck", - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1167,9 +1066,9 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1188,22 +1087,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.3", -] - [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.5", + "generic-array", ] [[package]] @@ -1214,18 +1104,7 @@ checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ "block-buffer 0.10.0", "crypto-common", - "subtle 2.4.1", -] - -[[package]] -name = "dirs" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" -dependencies = [ - "libc", - "redox_users 0.3.4", - "winapi 0.3.9", + "subtle", ] [[package]] @@ -1254,8 +1133,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" dependencies = [ "libc", - "redox_users 0.4.0", - "winapi 0.3.9", + "redox_users", + "winapi", ] [[package]] @@ -1265,19 +1144,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users 0.4.0", - "winapi 0.3.9", + "redox_users", + "winapi", ] +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" + [[package]] name = "displaydoc" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1294,9 +1179,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "ed25519" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" +checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" dependencies = [ "serde", "signature", @@ -1339,7 +1224,7 @@ checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" dependencies = [ "atty", "humantime", - "log 0.4.14", + "log", "regex", "termcolor", ] @@ -1352,7 +1237,7 @@ checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", "humantime", - "log 0.4.14", + "log", "regex", "termcolor", ] @@ -1373,7 +1258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" dependencies = [ "backtrace", - "version_check 0.9.3", + "version_check", ] [[package]] @@ -1398,18 +1283,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", "synstructure", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fastrand" version = "1.7.0" @@ -1420,15 +1299,17 @@ dependencies = [ ] [[package]] -name = "filetime" -version = "0.2.9" +name = "figment" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e" +checksum = "790b4292c72618abbab50f787a477014fe15634f96291de45672ce46afe122df" dependencies = [ - "cfg-if 0.1.10", - "libc", - "redox_syscall 0.1.56", - "winapi 0.3.9", + "atomic", + "pear", + "serde", + "toml", + "uncased", + "version_check", ] [[package]] @@ -1454,9 +1335,9 @@ dependencies = [ [[package]] name = "fnv" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" @@ -1465,7 +1346,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" dependencies = [ "matches", - "percent-encoding 2.1.0", + "percent-encoding", ] [[package]] @@ -1480,53 +1361,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" -[[package]] -name = "fsevent" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" -dependencies = [ - "bitflags", - "fsevent-sys", -] - -[[package]] -name = "fsevent-sys" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" -dependencies = [ - "libc", -] - [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" - [[package]] name = "futures" version = "0.3.21" @@ -1558,16 +1398,6 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" -[[package]] -name = "futures-cpupool" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -dependencies = [ - "futures 0.1.29", - "num_cpus", -] - [[package]] name = "futures-executor" version = "0.3.21" @@ -1606,9 +1436,9 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1642,12 +1472,16 @@ dependencies = [ ] [[package]] -name = "generic-array" -version = "0.12.3" +name = "generator" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" dependencies = [ - "typenum", + "cc", + "libc", + "log", + "rustversion", + "winapi", ] [[package]] @@ -1658,7 +1492,7 @@ checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "serde", "typenum", - "version_check 0.9.3", + "version_check", ] [[package]] @@ -1699,7 +1533,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" dependencies = [ - "opaque-debug 0.3.0", + "opaque-debug", "polyval", ] @@ -1725,9 +1559,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" name = "go-grpc-gateway-testing" version = "1.0.0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "mc-attest-core", "mc-common", @@ -1750,8 +1584,8 @@ dependencies = [ "futures-util", "grpcio-sys", "libc", - "log 0.4.14", - "parking_lot 0.11.2", + "log", + "parking_lot", "protobuf", ] @@ -1782,37 +1616,19 @@ dependencies = [ [[package]] name = "h2" -version = "0.1.26" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" dependencies = [ - "byteorder", - "bytes 0.4.12", - "fnv", - "futures 0.1.29", - "http 0.1.21", - "indexmap", - "log 0.4.14", - "slab", - "string", - "tokio-io", -] - -[[package]] -name = "h2" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" -dependencies = [ - "bytes 1.1.0", + "bytes 1.1.0", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.1", + "http", "indexmap", "slab", - "tokio 1.16.1", + "tokio", "tokio-util", "tracing", ] @@ -1828,6 +1644,12 @@ name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hashbrown" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" dependencies = [ "serde", ] @@ -1870,21 +1692,21 @@ dependencies = [ [[package]] name = "hmac" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ - "crypto-mac 0.7.0", - "digest 0.8.1", + "crypto-mac 0.8.0", + "digest 0.9.0", ] [[package]] name = "hmac" -version = "0.8.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ - "crypto-mac 0.8.0", + "crypto-mac 0.11.1", "digest 0.9.0", ] @@ -1911,18 +1733,7 @@ checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", "match_cfg", - "winapi 0.3.9", -] - -[[package]] -name = "http" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -dependencies = [ - "bytes 0.4.12", - "fnv", - "itoa 0.4.8", + "winapi", ] [[package]] @@ -1936,18 +1747,6 @@ dependencies = [ "itoa 0.4.8", ] -[[package]] -name = "http-body" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "http 0.1.21", - "tokio-buf", -] - [[package]] name = "http-body" version = "0.4.4" @@ -1955,15 +1754,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ "bytes 1.1.0", - "http 0.2.1", + "http", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.5.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -1979,92 +1778,26 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -dependencies = [ - "base64 0.9.3", - "httparse", - "language-tags", - "log 0.3.9", - "mime 0.2.6", - "num_cpus", - "time 0.1.43", - "traitobject", - "typeable", - "unicase", - "url 1.7.2", -] - -[[package]] -name = "hyper" -version = "0.12.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "futures-cpupool", - "h2 0.1.26", - "http 0.1.21", - "http-body 0.1.0", - "httparse", - "iovec", - "itoa 0.4.8", - "log 0.4.14", - "net2", - "rustc_version 0.2.3", - "time 0.1.43", - "tokio 0.1.22", - "tokio-buf", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "want 0.2.0", -] - -[[package]] -name = "hyper" -version = "0.14.16" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes 1.1.0", "futures-channel", "futures-core", "futures-util", - "h2 0.3.11", - "http 0.2.1", - "http-body 0.4.4", + "h2", + "http", + "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa 1.0.1", "pin-project-lite", "socket2", - "tokio 1.16.1", + "tokio", "tower-service", "tracing", - "want 0.3.0", -] - -[[package]] -name = "hyper-rustls" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719d85c7df4a7f309a77d145340a063ea929dcb2e025bae46a80345cffec2952" -dependencies = [ - "bytes 0.4.12", - "ct-logs", - "futures 0.1.29", - "hyper 0.12.35", - "rustls 0.16.0", - "tokio-io", - "tokio-rustls 0.10.3", - "webpki 0.21.2", - "webpki-roots 0.17.0", + "want", ] [[package]] @@ -2073,22 +1806,13 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ - "http 0.2.1", - "hyper 0.14.16", - "rustls 0.20.2", - "tokio 1.16.1", - "tokio-rustls 0.23.2", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "http", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", ] [[package]] @@ -2109,28 +1833,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", - "hashbrown", -] - -[[package]] -name = "inotify" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", + "hashbrown 0.11.2", + "serde", ] [[package]] -name = "inotify-sys" -version = "0.1.3" +name = "inlinable_string" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -dependencies = [ - "libc", -] +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" [[package]] name = "instant" @@ -2147,15 +1858,6 @@ version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90c11140ffea82edce8dcd74137ce9324ec24b3cf0175fc9d7e29164da9915b8" -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - [[package]] name = "ipnet" version = "2.3.1" @@ -2170,20 +1872,20 @@ checksum = "d140e84730d325378912ede32d7cd53ef1542725503b3353e5ec8113c7c6f588" dependencies = [ "async-channel", "castaway", - "crossbeam-utils 0.8.5", + "crossbeam-utils", "curl", "curl-sys", "event-listener", "futures-lite", - "http 0.2.1", - "log 0.4.14", + "http", + "log", "once_cell", "polling", "slab", "sluice", "tracing", "tracing-futures", - "url 2.2.2", + "url", "waker-fn", ] @@ -2217,7 +1919,7 @@ dependencies = [ "cesu8", "combine", "jni-sys", - "log 0.4.14", + "log", "thiserror", "walkdir", ] @@ -2249,22 +1951,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - [[package]] name = "lazy_static" version = "1.4.0" @@ -2282,9 +1968,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.124" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "libloading" @@ -2293,7 +1979,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" dependencies = [ "cfg-if 1.0.0", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2311,7 +1997,7 @@ dependencies = [ "cmake", "crc", "displaydoc", - "generic-array 0.14.5", + "generic-array", "libc", "mc-account-keys", "mc-account-keys-slip10", @@ -2342,9 +2028,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" +checksum = "92e7e15d7610cce1d9752e137625f14e61a28cd45929b6e12e47b50fe154ee2e" dependencies = [ "cc", "libc", @@ -2388,15 +2074,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "lock_api" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] - [[package]] name = "lock_api" version = "0.4.5" @@ -2408,20 +2085,26 @@ dependencies = [ [[package]] name = "log" -version = "0.3.9" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "log 0.4.14", + "cfg-if 1.0.0", ] [[package]] -name = "log" -version = "0.4.14" +name = "loom" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309" dependencies = [ "cfg-if 1.0.0", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", ] [[package]] @@ -2437,16 +2120,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] -name = "matches" -version = "0.1.8" +name = "matchers" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] [[package]] -name = "maybe-uninit" -version = "2.0.0" +name = "matches" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "mbedtls" @@ -2479,8 +2165,8 @@ dependencies = [ "lazy_static", "libc", "libz-sys", - "quote 1.0.18", - "syn 1.0.91", + "quote", + "syn", ] [[package]] @@ -2506,7 +2192,7 @@ dependencies = [ "rand 0.8.5", "rand_core 0.6.3", "rand_hc 0.3.1", - "subtle 2.4.1", + "subtle", "tempdir", "zeroize", ] @@ -2531,13 +2217,12 @@ dependencies = [ name = "mc-admin-http-gateway" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "grpcio", "mc-common", "mc-util-grpc", "mc-util-uri", "rocket", - "rocket_contrib", "serde", "serde_derive", "serde_json", @@ -2550,7 +2235,7 @@ dependencies = [ "aes-gcm", "anyhow", "displaydoc", - "generic-array 0.14.5", + "generic-array", "jni", "mc-account-keys", "mc-account-keys-slip10", @@ -2589,7 +2274,7 @@ dependencies = [ "crc", "curve25519-dalek", "displaydoc", - "generic-array 0.14.5", + "generic-array", "mc-account-keys", "mc-attest-core", "mc-crypto-keys", @@ -2648,7 +2333,7 @@ dependencies = [ "aead", "cargo-emit", "digest 0.10.3", - "futures 0.3.21", + "futures", "grpcio", "mc-attest-ake", "mc-attest-enclave-api", @@ -2688,7 +2373,7 @@ dependencies = [ "rjson", "serde", "sha2 0.10.2", - "subtle 2.4.1", + "subtle", ] [[package]] @@ -2717,7 +2402,7 @@ dependencies = [ "mc-sgx-build", "mc-util-encodings", "pem", - "percent-encoding 2.1.0", + "percent-encoding", "rand 0.8.5", "reqwest", "serde_json", @@ -2779,7 +2464,7 @@ dependencies = [ "cfg-if 1.0.0", "chrono", "displaydoc", - "hashbrown", + "hashbrown 0.12.1", "hex_fmt", "hostname", "lazy_static", @@ -2852,7 +2537,7 @@ name = "mc-consensus-api" version = "1.3.0-pre0" dependencies = [ "cargo-emit", - "futures 0.3.21", + "futures", "grpcio", "mc-api", "mc-attest-api", @@ -2950,11 +2635,12 @@ dependencies = [ "mc-util-from-random", "mc-util-serial", "once_cell", + "pem", "prost", "rand 0.8.5", "rand_core 0.6.3", "rand_hc 0.3.1", - "subtle 2.4.1", + "subtle", ] [[package]] @@ -2996,7 +2682,7 @@ dependencies = [ name = "mc-consensus-mint-client" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "grpcio", "hex", "mc-account-keys", @@ -3013,10 +2699,11 @@ dependencies = [ "mc-util-parse", "mc-util-uri", "pem", + "protobuf", "rand 0.8.5", "serde", "serde_json", - "toml 0.5.9", + "toml", ] [[package]] @@ -3046,7 +2733,7 @@ dependencies = [ name = "mc-consensus-scp-play" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "mc-common", "mc-consensus-scp", "mc-transaction-core", @@ -3058,13 +2745,13 @@ dependencies = [ name = "mc-consensus-service" version = "1.3.0-pre0" dependencies = [ - "base64 0.13.0", + "base64", "chrono", - "clap 3.1.12", + "clap 3.1.18", "curve25519-dalek", "displaydoc", "fs_extra", - "futures 0.3.21", + "futures", "grpcio", "hex", "lazy_static", @@ -3120,8 +2807,8 @@ dependencies = [ name = "mc-consensus-service-config" version = "1.3.0-pre0" dependencies = [ - "base64 0.13.0", - "clap 3.1.12", + "base64", + "clap 3.1.18", "displaydoc", "hex", "mc-attest-core", @@ -3138,7 +2825,7 @@ dependencies = [ "pem", "serde", "serde_json", - "toml 0.5.9", + "toml", ] [[package]] @@ -3184,7 +2871,7 @@ dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", "ed25519-dalek", - "generic-array 0.14.5", + "generic-array", "mc-crypto-digestible-derive", "merlin", "x25519-dalek", @@ -3194,9 +2881,9 @@ dependencies = [ name = "mc-crypto-digestible-derive" version = "1.3.0-pre0" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3255,12 +2942,12 @@ dependencies = [ "rand_core 0.6.3", "rand_hc 0.3.1", "schnorrkel-og", - "semver 1.0.7", + "semver 1.0.9", "serde", "serde_json", "sha2 0.10.2", "signature", - "subtle 2.4.1", + "subtle", "tempdir", "x25519-dalek", "zeroize", @@ -3272,12 +2959,12 @@ version = "1.3.0-pre0" dependencies = [ "aes-gcm", "displaydoc", - "generic-array 0.14.5", + "generic-array", "mc-util-serial", "mc-util-test-helper", "rand_core 0.6.3", "serde", - "subtle 2.4.1", + "subtle", ] [[package]] @@ -3302,7 +2989,7 @@ dependencies = [ "aes-gcm", "digest 0.10.3", "displaydoc", - "generic-array 0.14.5", + "generic-array", "hkdf", "mc-crypto-keys", "mc-util-from-random", @@ -3311,7 +2998,7 @@ dependencies = [ "secrecy", "serde", "sha2 0.10.2", - "subtle 2.4.1", + "subtle", "zeroize", ] @@ -3344,7 +3031,7 @@ name = "mc-crypto-x509-test-vectors" version = "1.3.0-pre0" dependencies = [ "cargo-emit", - "clap 3.1.12", + "clap 3.1.18", "mc-crypto-keys", "mc-util-build-script", "pem", @@ -3379,7 +3066,7 @@ version = "1.3.0-pre0" dependencies = [ "cargo-emit", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "mc-api", "mc-attest-api", @@ -3409,7 +3096,7 @@ dependencies = [ name = "mc-fog-distribution" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "crossbeam-channel", "curve25519-dalek", "grpcio", @@ -3466,7 +3153,7 @@ name = "mc-fog-ingest-client" version = "1.3.0-pre0" dependencies = [ "assert_cmd", - "clap 3.1.12", + "clap 3.1.18", "displaydoc", "grpcio", "hex", @@ -3610,10 +3297,10 @@ dependencies = [ name = "mc-fog-ingest-server" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", - "dirs 4.0.0", + "clap 3.1.18", + "dirs", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "hex", "itertools", @@ -3660,7 +3347,7 @@ dependencies = [ "serde", "serde_json", "tempdir", - "url 2.2.2", + "url", ] [[package]] @@ -3795,9 +3482,9 @@ dependencies = [ name = "mc-fog-ledger-server" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "hex", "lazy_static", @@ -3841,7 +3528,7 @@ dependencies = [ "serde", "serde_json", "tempdir", - "url 2.2.2", + "url", ] [[package]] @@ -3864,7 +3551,7 @@ dependencies = [ name = "mc-fog-load-testing" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "grpcio", "mc-account-keys", "mc-common", @@ -3921,7 +3608,7 @@ dependencies = [ "mc-sgx-compat", "mc-util-test-helper", "rand_core 0.6.3", - "subtle 2.4.1", + "subtle", ] [[package]] @@ -3936,7 +3623,7 @@ dependencies = [ name = "mc-fog-overseer-server" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "displaydoc", "grpcio", "lazy_static", @@ -3965,10 +3652,9 @@ dependencies = [ "regex", "retry", "rocket", - "rocket_contrib", "serde", "tempdir", - "url 2.2.2", + "url", ] [[package]] @@ -3990,7 +3676,7 @@ name = "mc-fog-report-api" version = "1.3.0-pre0" dependencies = [ "cargo-emit", - "futures 0.3.21", + "futures", "grpcio", "mc-api", "mc-attest-api", @@ -4017,9 +3703,9 @@ dependencies = [ name = "mc-fog-report-cli" version = "1.3.0-pre0" dependencies = [ - "base64 0.13.0", + "base64", "binascii", - "clap 3.1.12", + "clap 3.1.18", "grpcio", "mc-account-keys", "mc-attest-core", @@ -4056,9 +3742,9 @@ dependencies = [ name = "mc-fog-report-server" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "mc-attest-core", "mc-common", @@ -4113,6 +3799,7 @@ dependencies = [ "mc-util-serial", "mc-util-uri", "mockall", + "serde", ] [[package]] @@ -4128,9 +3815,9 @@ name = "mc-fog-sample-paykit" version = "1.3.0-pre0" dependencies = [ "cargo-emit", - "clap 3.1.12", + "clap 3.1.18", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "link-cplusplus", "mc-account-keys", @@ -4221,7 +3908,7 @@ name = "mc-fog-sql-recovery-db" version = "1.3.0-pre0" dependencies = [ "chrono", - "clap 3.1.12", + "clap 3.1.18", "diesel", "diesel-derive-enum", "diesel_migrations", @@ -4253,7 +3940,7 @@ dependencies = [ name = "mc-fog-test-client" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "displaydoc", "grpcio", "hex_fmt", @@ -4284,7 +3971,7 @@ dependencies = [ name = "mc-fog-test-infra" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "digest 0.10.3", "hex", "mc-account-keys", @@ -4308,7 +3995,7 @@ dependencies = [ "rand_hc 0.3.1", "serde", "serde_json", - "url 2.2.2", + "url", ] [[package]] @@ -4459,7 +4146,7 @@ dependencies = [ name = "mc-fog-view-load-test" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "grpcio", "mc-account-keys", "mc-attest-verifier", @@ -4501,9 +4188,9 @@ dependencies = [ name = "mc-fog-view-server" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "hex", "lazy_static", @@ -4577,8 +4264,8 @@ dependencies = [ name = "mc-ledger-distribution" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", - "dirs 4.0.0", + "clap 3.1.18", + "dirs", "displaydoc", "mc-api", "mc-common", @@ -4591,14 +4278,15 @@ dependencies = [ "rusoto_s3", "serde", "serde_json", - "url 2.2.2", + "tokio", + "url", ] [[package]] name = "mc-ledger-from-archive" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "mc-api", "mc-common", "mc-ledger-db", @@ -4609,7 +4297,7 @@ dependencies = [ name = "mc-ledger-migration" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "lmdb-rkv", "mc-common", "mc-ledger-db", @@ -4646,14 +4334,14 @@ dependencies = [ "retry", "serde", "tempdir", - "url 2.2.2", + "url", ] [[package]] name = "mc-mint-auditor" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "displaydoc", "grpcio", "hostname", @@ -4687,7 +4375,7 @@ name = "mc-mint-auditor-api" version = "1.3.0-pre0" dependencies = [ "cargo-emit", - "futures 0.3.21", + "futures", "grpcio", "mc-util-build-grpc", "mc-util-build-script", @@ -4701,7 +4389,7 @@ name = "mc-mobilecoind" version = "1.3.0-pre0" dependencies = [ "aes-gcm", - "clap 3.1.12", + "clap 3.1.18", "crossbeam-channel", "displaydoc", "grpcio", @@ -4765,7 +4453,7 @@ name = "mc-mobilecoind-api" version = "1.3.0-pre0" dependencies = [ "cargo-emit", - "futures 0.3.21", + "futures", "grpcio", "hex_fmt", "mc-api", @@ -4782,7 +4470,7 @@ dependencies = [ name = "mc-mobilecoind-json" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "grpcio", "hex", "mc-api", @@ -4797,7 +4485,6 @@ dependencies = [ "protobuf", "rand 0.8.5", "rocket", - "rocket_contrib", "serde", "serde_derive", ] @@ -4813,7 +4500,7 @@ dependencies = [ "cipher", "ctr", "ghash", - "subtle 2.4.1", + "subtle", "zeroize", ] @@ -4825,7 +4512,7 @@ checksum = "b3a5d3ec41e27ef685e5aa261d3de25c42354771015865af874a5fbb0ceb1a87" dependencies = [ "aligned-array", "aligned-cmov", - "generic-array 0.14.5", + "generic-array", "mc-oblivious-traits", "rand_core 0.6.3", "siphasher", @@ -4948,7 +4635,7 @@ dependencies = [ name = "mc-sgx-css-dump" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "hex_fmt", "mc-sgx-css", ] @@ -5103,7 +4790,7 @@ dependencies = [ "crc", "curve25519-dalek", "displaydoc", - "generic-array 0.14.5", + "generic-array", "hex_fmt", "hkdf", "lazy_static", @@ -5131,7 +4818,7 @@ dependencies = [ "rand_hc 0.3.1", "serde", "sha2 0.10.2", - "subtle 2.4.1", + "subtle", "tempdir", "zeroize", ] @@ -5175,7 +4862,7 @@ dependencies = [ "rand 0.8.5", "rand_core 0.6.3", "sha2 0.10.2", - "subtle 2.4.1", + "subtle", "yaml-rust", "zeroize", ] @@ -5184,7 +4871,7 @@ dependencies = [ name = "mc-util-b58-decoder" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "hex", "mc-api", ] @@ -5228,7 +4915,7 @@ dependencies = [ "cargo-emit", "displaydoc", "lazy_static", - "url 2.2.2", + "url", "walkdir", ] @@ -5247,7 +4934,7 @@ dependencies = [ name = "mc-util-cli" version = "0.1.0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "mc-util-build-info", ] @@ -5255,7 +4942,7 @@ dependencies = [ name = "mc-util-encodings" version = "1.3.0-pre0" dependencies = [ - "base64 0.13.0", + "base64", "binascii", "displaydoc", "hex", @@ -5278,7 +4965,7 @@ dependencies = [ name = "mc-util-generate-sample-ledger" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "hex", "mc-account-keys", "mc-common", @@ -5297,11 +4984,11 @@ dependencies = [ name = "mc-util-grpc" version = "1.3.0-pre0" dependencies = [ - "base64 0.13.0", - "clap 3.1.12", + "base64", + "clap 3.1.18", "cookie 0.16.0", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "hex", "hex_fmt", @@ -5322,7 +5009,7 @@ dependencies = [ "serde", "sha2 0.10.2", "signal-hook", - "subtle 2.4.1", + "subtle", "tempfile", "zeroize", ] @@ -5331,7 +5018,7 @@ dependencies = [ name = "mc-util-grpc-admin-tool" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "grpcio", "mc-common", "mc-util-grpc", @@ -5342,11 +5029,11 @@ dependencies = [ name = "mc-util-grpc-token-generator" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "hex", "mc-common", "mc-util-grpc", - "percent-encoding 2.1.0", + "percent-encoding", ] [[package]] @@ -5357,8 +5044,8 @@ version = "1.3.0-pre0" name = "mc-util-keyfile" version = "1.3.0-pre0" dependencies = [ - "base64 0.13.0", - "clap 3.1.12", + "base64", + "clap 3.1.18", "displaydoc", "hex", "mc-account-keys", @@ -5395,9 +5082,9 @@ dependencies = [ name = "mc-util-logger-macros" version = "1.3.0-pre0" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -5433,7 +5120,7 @@ dependencies = [ name = "mc-util-repr-bytes" version = "1.3.0-pre0" dependencies = [ - "generic-array 0.14.5", + "generic-array", "prost", "serde", "serde_cbor", @@ -5443,7 +5130,7 @@ dependencies = [ name = "mc-util-seeded-ed25519-key-gen" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "hex", "mc-crypto-keys", "mc-util-from-random", @@ -5476,7 +5163,7 @@ dependencies = [ name = "mc-util-test-helper" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "itertools", "lazy_static", "mc-account-keys", @@ -5498,36 +5185,36 @@ dependencies = [ name = "mc-util-test-with-data" version = "1.3.0-pre0" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "mc-util-uri" version = "1.3.0-pre0" dependencies = [ - "base64 0.13.0", + "base64", "displaydoc", "hex", "mc-common", "mc-crypto-keys", "mc-util-from-random", "mc-util-host-cert", - "percent-encoding 2.1.0", + "percent-encoding", "rand 0.8.5", "rand_hc 0.3.1", "serde", - "url 2.2.2", + "url", ] [[package]] name = "mc-watcher" version = "1.3.0-pre0" dependencies = [ - "clap 3.1.12", + "clap 3.1.18", "displaydoc", - "futures 0.3.21", + "futures", "grpcio", "hex", "lazy_static", @@ -5561,8 +5248,8 @@ dependencies = [ "serde", "serial_test", "tempdir", - "toml 0.5.9", - "url 2.2.2", + "toml", + "url", ] [[package]] @@ -5574,10 +5261,15 @@ dependencies = [ ] [[package]] -name = "md5" -version = "0.7.0" +name = "md-5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug", +] [[package]] name = "memchr" @@ -5585,15 +5277,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" -[[package]] -name = "memoffset" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.6.4" @@ -5631,18 +5314,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" dependencies = [ "migrations_internals", - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", -] - -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -5676,25 +5350,6 @@ dependencies = [ "adler 1.0.2", ] -[[package]] -name = "mio" -version = "0.6.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log 0.4.14", - "miow 0.2.1", - "net2", - "slab", - "winapi 0.2.8", -] - [[package]] name = "mio" version = "0.7.14" @@ -5702,57 +5357,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", - "log 0.4.14", - "miow 0.3.7", + "log", + "miow", "ntapi", - "winapi 0.3.9", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log 0.4.14", - "mio 0.6.22", - "slab", -] - -[[package]] -name = "mio-named-pipes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" -dependencies = [ - "log 0.4.14", - "mio 0.6.22", - "miow 0.3.7", - "winapi 0.3.9", -] - -[[package]] -name = "mio-uds" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" -dependencies = [ - "iovec", - "libc", - "mio 0.6.22", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "winapi", ] [[package]] @@ -5761,7 +5369,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5786,9 +5394,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79ef208208a0dea3f72221e26e904cdc6db2e481d9ade89081ddd494f1dbaa6b" dependencies = [ "cfg-if 1.0.0", - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -5798,14 +5406,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] -name = "net2" -version = "0.2.34" +name = "multer" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" +checksum = "5f8f35e687561d5c1667590911e6698a8cb714a134a7505718a182e7bc9d3836" dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", + "bytes 1.1.0", + "encoding_rs", + "futures-util", + "http", + "httparse", + "log", + "memchr", + "mime", + "spin 0.9.3", + "tokio", + "tokio-util", + "version_check", ] [[package]] @@ -5815,7 +5432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" dependencies = [ "memchr", - "version_check 0.9.3", + "version_check", ] [[package]] @@ -5826,7 +5443,7 @@ checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ "memchr", "minimal-lexical", - "version_check 0.9.3", + "version_check", ] [[package]] @@ -5835,31 +5452,13 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" -[[package]] -name = "notify" -version = "4.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" -dependencies = [ - "bitflags", - "filetime", - "fsevent", - "fsevent-sys", - "inotify", - "libc", - "mio 0.6.22", - "mio-extras", - "walkdir", - "winapi 0.3.9", -] - [[package]] name = "ntapi" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5932,12 +5531,6 @@ version = "11.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af325bc33c7f60191be4e2c984d48aaa21e2854f473b85398344b60c9b6358" -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "opaque-debug" version = "0.3.0" @@ -5966,8 +5559,7 @@ dependencies = [ [[package]] name = "opentelemetry" version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8" +source = "git+https://github.com/mobilecoinofficial/opentelemetry-rust.git?rev=1817229c56340bbb4a6dca63c8dfb5154606e5bf#1817229c56340bbb4a6dca63c8dfb5154606e5bf" dependencies = [ "async-trait", "crossbeam-channel", @@ -5976,7 +5568,7 @@ dependencies = [ "futures-util", "js-sys", "lazy_static", - "percent-encoding 2.1.0", + "percent-encoding", "pin-project", "rand 0.8.5", "thiserror", @@ -5985,23 +5577,21 @@ dependencies = [ [[package]] name = "opentelemetry-http" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449048140ee61e28f57abe6e9975eedc1f3a29855c7407bd6c12b18578863379" +source = "git+https://github.com/mobilecoinofficial/opentelemetry-rust.git?rev=1817229c56340bbb4a6dca63c8dfb5154606e5bf#1817229c56340bbb4a6dca63c8dfb5154606e5bf" dependencies = [ "async-trait", "bytes 1.1.0", - "http 0.2.1", + "http", "opentelemetry", ] [[package]] name = "opentelemetry-jaeger" version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c0b12cd9e3f9b35b52f6e0dac66866c519b26f424f4bbf96e3fe8bfbdc5229" +source = "git+https://github.com/mobilecoinofficial/opentelemetry-rust.git?rev=1817229c56340bbb4a6dca63c8dfb5154606e5bf#1817229c56340bbb4a6dca63c8dfb5154606e5bf" dependencies = [ "async-trait", - "http 0.2.1", + "http", "isahc", "lazy_static", "opentelemetry", @@ -6014,17 +5604,16 @@ dependencies = [ [[package]] name = "opentelemetry-semantic-conventions" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985cc35d832d412224b2cffe2f9194b1b89b6aa5d0bef76d080dce09d90e62bd" +source = "git+https://github.com/mobilecoinofficial/opentelemetry-rust.git?rev=1817229c56340bbb4a6dca63c8dfb5154606e5bf#1817229c56340bbb4a6dca63c8dfb5154606e5bf" dependencies = [ "opentelemetry", ] [[package]] name = "ordered-float" -version = "1.1.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" +checksum = "96bcbab4bfea7a59c2c0fe47211a1ac4e3e96bea6eb446d704f310bc5c732ae2" dependencies = [ "num-traits", ] @@ -6051,17 +5640,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.6.2", - "rustc_version 0.2.3", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -6069,23 +5647,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.5", - "parking_lot_core 0.8.5", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.56", - "rustc_version 0.2.3", - "smallvec 0.6.13", - "winapi 0.3.9", + "lock_api", + "parking_lot_core", ] [[package]] @@ -6097,9 +5660,9 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.10", - "smallvec 1.6.1", - "winapi 0.3.9", + "redox_syscall", + "smallvec", + "winapi", ] [[package]] @@ -6113,24 +5676,25 @@ dependencies = [ [[package]] name = "pear" -version = "0.1.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5320f212db967792b67cfe12bd469d08afd6318a249bd917d5c19bc92200ab8a" +checksum = "15e44241c5e4c868e3eaa78b7c1848cadd6344ed4f54d029832d32b415a58702" dependencies = [ + "inlinable_string", "pear_codegen", + "yansi", ] [[package]] name = "pear_codegen" -version = "0.1.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc1c836fdc3d1ef87c348b237b5b5c4dff922156fb2d968f57734f9669768ca" +checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", - "version_check 0.9.3", - "yansi", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn", ] [[package]] @@ -6145,15 +5709,9 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" dependencies = [ - "base64 0.13.0", + "base64", ] -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.1.0" @@ -6175,9 +5733,9 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -6234,9 +5792,9 @@ checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" dependencies = [ "cfg-if 1.0.0", "libc", - "log 0.4.14", + "log", "wepoll-ffi", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -6247,7 +5805,7 @@ checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "opaque-debug 0.3.0", + "opaque-debug", "universal-hash", ] @@ -6303,10 +5861,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", - "version_check 0.9.3", + "proc-macro2", + "quote", + "syn", + "version_check", ] [[package]] @@ -6315,29 +5873,39 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", "syn-mid", - "version_check 0.9.3", + "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + [[package]] name = "proc-macro2" -version = "0.4.30" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ - "unicode-xid 0.1.0", + "unicode-xid", ] [[package]] -name = "proc-macro2" -version = "1.0.37" +name = "proc-macro2-diagnostics" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" dependencies = [ - "unicode-xid 0.2.2", + "proc-macro2", + "quote", + "syn", + "version_check", + "yansi", ] [[package]] @@ -6350,7 +5918,7 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot 0.11.2", + "parking_lot", "protobuf", "thiserror", ] @@ -6377,9 +5945,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07b0857a71a8cb765763950499cae2413c3f9cede1133478c43600d9e146890" +checksum = "bc03e116981ff7d8da8e5c220e374587b98d294af7ba7dd7fda761158f00086f" dependencies = [ "bytes 1.1.0", "prost-derive", @@ -6393,9 +5961,9 @@ checksum = "df35198f0777b75e9ff669737c6da5136b59dba33cf5a010a6d1cc4d56defc6f" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -6419,7 +5987,7 @@ version = "2.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2ef1dc036942fac2470fdb8a911f125404ee9129e9e807f3d12d8589001a38f" dependencies = [ - "log 0.4.14", + "log", "which 4.2.4", ] @@ -6458,22 +6026,13 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] - [[package]] name = "quote" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ - "proc-macro2 1.0.37", + "proc-macro2", ] [[package]] @@ -6482,8 +6041,8 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" dependencies = [ - "log 0.4.14", - "parking_lot 0.11.2", + "log", + "parking_lot", "scheduled-thread-pool", ] @@ -6497,7 +6056,7 @@ dependencies = [ "libc", "rand_core 0.3.1", "rdrand", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -6611,7 +6170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" dependencies = [ "autocfg", - "crossbeam-deque 0.8.1", + "crossbeam-deque", "either", "rayon-core", ] @@ -6623,8 +6182,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" dependencies = [ "crossbeam-channel", - "crossbeam-deque 0.8.1", - "crossbeam-utils 0.8.5", + "crossbeam-deque", + "crossbeam-utils", "num_cpus", ] @@ -6637,12 +6196,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - [[package]] name = "redox_syscall" version = "0.2.10" @@ -6654,23 +6207,32 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.3.4" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.1.14", - "redox_syscall 0.1.56", - "rust-argon2", + "getrandom 0.2.6", + "redox_syscall", ] [[package]] -name = "redox_users" -version = "0.4.0" +name = "ref-cast" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "685d58625b6c2b83e4cc88a27c4bf65adb7b6b16dbdc413e515c9405b47432ab" dependencies = [ - "getrandom 0.2.6", - "redox_syscall 0.2.10", + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -6691,6 +6253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" dependencies = [ "byteorder", + "regex-syntax", ] [[package]] @@ -6705,7 +6268,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -6715,36 +6278,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" dependencies = [ "async-compression", - "base64 0.13.0", + "base64", "bytes 1.1.0", "encoding_rs", "futures-core", "futures-util", - "h2 0.3.11", - "http 0.2.1", - "http-body 0.4.4", - "hyper 0.14.16", - "hyper-rustls 0.23.0", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", "ipnet", "js-sys", "lazy_static", - "log 0.4.14", - "mime 0.3.16", - "percent-encoding 2.1.0", + "log", + "mime", + "percent-encoding", "pin-project-lite", - "rustls 0.20.2", - "rustls-pemfile", + "rustls", + "rustls-pemfile 0.3.0", "serde", "serde_json", "serde_urlencoded", - "tokio 1.16.1", - "tokio-rustls 0.23.2", + "tokio", + "tokio-rustls", "tokio-util", - "url 2.2.2", + "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.22.2", + "webpki-roots", "winreg", ] @@ -6769,7 +6332,7 @@ dependencies = [ "spin 0.5.2", "untrusted", "web-sys", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -6780,68 +6343,85 @@ checksum = "5510dbde48c4c37bf69123b1f636b6dd5f8dffe1f4e358af03c46a4947dca219" [[package]] name = "rocket" -version = "0.4.10" +version = "0.5.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a7ab1dfdc75bb8bd2be381f37796b1b300c45a3c9145b34d86715e8dd90bf28" +checksum = "0a71c18c42a0eb15bf3816831caf0dad11e7966f2a41aaf486a701979c4dd1f2" dependencies = [ + "async-stream", + "async-trait", + "atomic", "atty", - "base64 0.13.0", - "log 0.4.14", + "binascii", + "bytes 1.1.0", + "either", + "figment", + "futures", + "indexmap", + "log", "memchr", + "multer", "num_cpus", - "pear", + "parking_lot", + "pin-project-lite", + "rand 0.8.5", + "ref-cast", "rocket_codegen", "rocket_http", + "serde", + "serde_json", "state", - "time 0.1.43", - "toml 0.4.10", - "version_check 0.9.3", + "tempfile", + "time 0.2.27", + "tokio", + "tokio-stream", + "tokio-util", + "ubyte", + "version_check", "yansi", ] [[package]] name = "rocket_codegen" -version = "0.4.10" +version = "0.5.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729e687d6d2cf434d174da84fb948f7fef4fac22d20ce94ca61c28b72dbcf9f" +checksum = "66f5fa462f7eb958bba8710c17c5d774bbbd59809fa76fb1957af7e545aea8bb" dependencies = [ "devise", "glob 0.3.0", "indexmap", - "quote 0.6.13", + "proc-macro2", + "quote", "rocket_http", - "version_check 0.9.3", - "yansi", -] - -[[package]] -name = "rocket_contrib" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6303dccab46dce6c7ac26c9b9d8d8cde1b19614b027c3f913be6611bff6d9b" -dependencies = [ - "log 0.4.14", - "notify", - "rocket", - "serde", - "serde_json", + "syn", + "unicode-xid", ] [[package]] name = "rocket_http" -version = "0.4.10" +version = "0.5.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6131e6e6d38a9817f4a494ff5da95971451c2eb56a53915579fc9c80f6ef0117" +checksum = "23c8b7d512d2fcac2316ebe590cde67573844b99e6cc9ee0f53375fa16e25ebd" dependencies = [ - "cookie 0.11.3", - "hyper 0.10.16", + "cookie 0.15.1", + "either", + "http", + "hyper", "indexmap", + "log", + "memchr", + "mime", + "parking_lot", "pear", - "percent-encoding 1.0.1", - "smallvec 1.6.1", + "percent-encoding", + "pin-project-lite", + "ref-cast", + "serde", + "smallvec", + "stable-pattern", "state", - "time 0.1.43", - "unicode-xid 0.1.0", + "time 0.2.27", + "tokio", + "uncased", ] [[package]] @@ -6855,96 +6435,84 @@ dependencies = [ [[package]] name = "rusoto_core" -version = "0.42.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d1ecfe8dac29878a713fbc4c36b0a84a48f7a6883541841cdff9fdd2ba7dfb" +checksum = "1db30db44ea73551326269adcf7a2169428a054f14faf9e1768f2163494f2fa2" dependencies = [ - "base64 0.11.0", - "bytes 0.4.12", - "futures 0.1.29", - "http 0.1.21", - "hyper 0.12.35", - "hyper-rustls 0.17.1", + "async-trait", + "base64", + "bytes 1.1.0", + "crc32fast", + "futures", + "http", + "hyper", + "hyper-rustls", "lazy_static", - "log 0.4.14", + "log", "rusoto_credential", "rusoto_signature", - "rustc_version 0.2.3", + "rustc_version 0.4.0", "serde", - "serde_derive", "serde_json", - "time 0.1.43", - "tokio 0.1.22", - "tokio-timer", + "tokio", "xml-rs", ] [[package]] name = "rusoto_credential" -version = "0.42.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8632e41d289db90dd40d0389c71a23c5489e3afd448424226529113102e2a002" +checksum = "ee0a6c13db5aad6047b6a44ef023dbbc21a056b6dab5be3b79ce4283d5c02d05" dependencies = [ + "async-trait", "chrono", - "dirs 1.0.5", - "futures 0.1.29", - "hyper 0.12.35", - "lazy_static", - "regex", + "dirs-next", + "futures", + "hyper", "serde", - "serde_derive", "serde_json", - "shlex 0.1.1", - "tokio-process", - "tokio-timer", + "shlex", + "tokio", + "zeroize", ] [[package]] name = "rusoto_s3" -version = "0.42.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fedcadf3d73c2925b05d547b66787f2219c5e727a98c893fff5cf2197dbd678" +checksum = "7aae4677183411f6b0b412d66194ef5403293917d66e70ab118f07cc24c5b14d" dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", + "async-trait", + "bytes 1.1.0", + "futures", "rusoto_core", "xml-rs", ] [[package]] name = "rusoto_signature" -version = "0.42.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7063a70614eb4b36f49bcf4f6f6bb30cc765e3072b317d6afdfe51e7a9f482d1" +checksum = "a5ae95491c8b4847931e291b151127eccd6ff8ca13f33603eb3d0035ecb05272" dependencies = [ - "base64 0.11.0", - "bytes 0.4.12", - "futures 0.1.29", + "base64", + "bytes 1.1.0", + "chrono", + "digest 0.9.0", + "futures", "hex", - "hmac 0.7.1", - "http 0.1.21", - "hyper 0.12.35", - "log 0.4.14", - "md5", - "percent-encoding 2.1.0", + "hmac 0.11.0", + "http", + "hyper", + "log", + "md-5", + "percent-encoding", + "pin-project-lite", "rusoto_credential", - "rustc_version 0.2.3", + "rustc_version 0.4.0", "serde", - "sha2 0.8.2", - "time 0.1.43", - "tokio 0.1.22", -] - -[[package]] -name = "rust-argon2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" -dependencies = [ - "base64 0.11.0", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils 0.7.2", + "sha2 0.9.8", + "tokio", ] [[package]] @@ -6974,32 +6542,31 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.7", + "semver 1.0.9", ] [[package]] name = "rustls" -version = "0.16.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" dependencies = [ - "base64 0.10.1", - "log 0.4.14", + "log", "ring", - "sct 0.6.0", - "webpki 0.21.2", + "sct", + "webpki", ] [[package]] -name = "rustls" -version = "0.20.2" +name = "rustls-native-certs" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ - "log 0.4.14", - "ring", - "sct 0.7.0", - "webpki 0.22.0", + "openssl-probe", + "rustls-pemfile 1.0.0", + "schannel", + "security-framework", ] [[package]] @@ -7008,7 +6575,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" dependencies = [ - "base64 0.13.0", + "base64", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" +dependencies = [ + "base64", ] [[package]] @@ -7035,12 +6611,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - [[package]] name = "same-file" version = "1.0.6" @@ -7057,7 +6627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -7066,7 +6636,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" dependencies = [ - "parking_lot 0.11.2", + "parking_lot", ] [[package]] @@ -7075,15 +6645,21 @@ version = "0.11.0-pre.0" source = "git+https://github.com/mobilecoinfoundation/schnorrkel.git?rev=5c98ae068ee4652d6df6463b549fbf2d5d132faa#5c98ae068ee4652d6df6463b549fbf2d5d132faa" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec", "curve25519-dalek", "merlin", "rand_core 0.6.3", "sha2 0.10.2", - "subtle 2.4.1", + "subtle", "zeroize", ] +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -7096,16 +6672,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "sct" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sct" version = "0.7.0" @@ -7125,6 +6691,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "0.9.0" @@ -7137,9 +6726,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4" +checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" dependencies = [ "serde", ] @@ -7165,7 +6754,7 @@ dependencies = [ "sentry-panic", "sentry-slog", "serde_json", - "tokio 1.16.1", + "tokio", ] [[package]] @@ -7212,7 +6801,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91b56c287a5295358bd4a3481a32add1f3fb7131102e300f561f788e33b79efe" dependencies = [ - "log 0.4.14", + "log", "sentry-core", ] @@ -7250,15 +6839,15 @@ dependencies = [ "serde_json", "thiserror", "time 0.3.9", - "url 2.2.2", + "url", "uuid", ] [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] @@ -7293,20 +6882,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa 1.0.1", "ryu", @@ -7332,7 +6921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5bcc41d18f7a1d50525d080fd3e953be87c4f9f1a974f3c21798ca00d54ec15" dependencies = [ "lazy_static", - "parking_lot 0.11.2", + "parking_lot", "serial_test_derive", ] @@ -7343,24 +6932,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.37", - "quote 1.0.18", + "proc-macro2", + "quote", "rustversion", - "syn 1.0.91", + "syn", ] [[package]] -name = "sha2" -version = "0.8.2" +name = "sha1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", + "sha1_smol", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" version = "0.9.8" @@ -7371,7 +6963,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug 0.3.0", + "opaque-debug", ] [[package]] @@ -7406,10 +6998,13 @@ dependencies = [ ] [[package]] -name = "shlex" -version = "0.1.1" +name = "sharded-slab" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] [[package]] name = "shlex" @@ -7519,7 +7114,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "906a1a0bc43fed692df4b82a5e2fbfc3733db8dad8bb514ab27a4f23ad04f5c0" dependencies = [ - "log 0.4.14", + "log", "regex", "slog", "slog-async", @@ -7572,7 +7167,7 @@ version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6706b2ace5bbae7291d3f8d2473e2bfab073ccd7d03670946197aec98471fa3e" dependencies = [ - "log 0.4.14", + "log", "slog", "slog-scope", ] @@ -7601,15 +7196,6 @@ dependencies = [ "futures-io", ] -[[package]] -name = "smallvec" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -dependencies = [ - "maybe-uninit", -] - [[package]] name = "smallvec" version = "1.6.1" @@ -7623,7 +7209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -7638,21 +7224,88 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" + +[[package]] +name = "stable-pattern" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" +dependencies = [ + "memchr", +] + +[[package]] +name = "standback" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" +dependencies = [ + "version_check", +] + [[package]] name = "state" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028" +checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" +dependencies = [ + "loom", +] [[package]] -name = "string" -version = "0.2.1" +name = "stdweb" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +dependencies = [ + "discard", + "rustc_version 0.2.3", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "bytes 0.4.12", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "syn", ] +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +dependencies = [ + "base-x", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "serde_json", + "sha1", + "syn", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" + [[package]] name = "strsim" version = "0.8.0" @@ -7665,12 +7318,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" - [[package]] name = "subtle" version = "2.4.1" @@ -7679,24 +7326,13 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "0.15.44" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +checksum = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", -] - -[[package]] -name = "syn" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" -dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "unicode-xid 0.2.2", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] @@ -7705,9 +7341,9 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -7716,10 +7352,10 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", - "unicode-xid 0.2.2", + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] @@ -7747,9 +7383,9 @@ dependencies = [ "cfg-if 1.0.0", "fastrand", "libc", - "redox_syscall 0.2.10", + "redox_syscall", "remove_dir_all", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -7760,7 +7396,7 @@ checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ "dirs-next", "rustversion", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -7802,9 +7438,9 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -7827,13 +7463,12 @@ dependencies = [ [[package]] name = "thrift" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b82ca8f46f95b3ce96081fe3dd89160fdea970c254bb72925255d1b62aae692e" +version = "0.17.0" +source = "git+https://github.com/mobilecoinofficial/thrift.git?rev=9caf65384c5ec50b4988e2fb07b984f275785123#9caf65384c5ec50b4988e2fb07b984f275785123" dependencies = [ "byteorder", "integer-encoding", - "log 0.4.14", + "log", "ordered-float", "threadpool", ] @@ -7845,7 +7480,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", +] + +[[package]] +name = "time" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +dependencies = [ + "const_fn", + "libc", + "standback", + "stdweb", + "time-macros 0.1.1", + "version_check", + "winapi", ] [[package]] @@ -7857,7 +7507,17 @@ dependencies = [ "itoa 1.0.1", "libc", "num_threads", - "time-macros", + "time-macros 0.2.4", +] + +[[package]] +name = "time-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +dependencies = [ + "proc-macro-hack", + "time-macros-impl", ] [[package]] @@ -7866,6 +7526,19 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +[[package]] +name = "time-macros-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "standback", + "syn", +] + [[package]] name = "tiny-bip39" version = "0.8.2" @@ -7910,30 +7583,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" -[[package]] -name = "tokio" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "mio 0.6.22", - "num_cpus", - "tokio-codec", - "tokio-current-thread", - "tokio-executor", - "tokio-fs", - "tokio-io", - "tokio-reactor", - "tokio-sync", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "tokio-udp", - "tokio-uds", -] - [[package]] name = "tokio" version = "1.16.1" @@ -7943,126 +7592,24 @@ dependencies = [ "bytes 1.1.0", "libc", "memchr", - "mio 0.7.14", + "mio", "num_cpus", + "once_cell", "pin-project-lite", - "winapi 0.3.9", -] - -[[package]] -name = "tokio-buf" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -dependencies = [ - "bytes 0.4.12", - "either", - "futures 0.1.29", -] - -[[package]] -name = "tokio-codec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "tokio-io", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -dependencies = [ - "futures 0.1.29", - "tokio-executor", -] - -[[package]] -name = "tokio-executor" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.29", -] - -[[package]] -name = "tokio-fs" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" -dependencies = [ - "futures 0.1.29", - "tokio-io", - "tokio-threadpool", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "log 0.4.14", -] - -[[package]] -name = "tokio-process" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "382d90f43fa31caebe5d3bc6cfd854963394fff3b8cb59d5146607aaae7e7e43" -dependencies = [ - "crossbeam-queue 0.1.2", - "futures 0.1.29", - "lazy_static", - "libc", - "log 0.4.14", - "mio 0.6.22", - "mio-named-pipes", - "tokio-io", - "tokio-reactor", - "tokio-signal", - "winapi 0.3.9", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.29", - "lazy_static", - "log 0.4.14", - "mio 0.6.22", - "num_cpus", - "parking_lot 0.9.0", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", + "signal-hook-registry", + "tokio-macros", + "winapi", ] [[package]] -name = "tokio-rustls" -version = "0.10.3" +name = "tokio-macros" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d7cf08f990090abd6c6a73cab46fed62f85e8aef8b99e4b918a9f4a637f0676" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "iovec", - "rustls 0.16.0", - "tokio-io", - "webpki 0.21.2", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -8071,112 +7618,20 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" dependencies = [ - "rustls 0.20.2", - "tokio 1.16.1", - "webpki 0.22.0", + "rustls", + "tokio", + "webpki", ] [[package]] -name = "tokio-signal" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12" -dependencies = [ - "futures 0.1.29", - "libc", - "mio 0.6.22", - "mio-uds", - "signal-hook-registry", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "winapi 0.3.9", -] - -[[package]] -name = "tokio-sync" +name = "tokio-stream" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures 0.1.29", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "iovec", - "mio 0.6.22", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -dependencies = [ - "crossbeam-deque 0.7.3", - "crossbeam-queue 0.2.1", - "crossbeam-utils 0.7.2", - "futures 0.1.29", - "lazy_static", - "log 0.4.14", - "num_cpus", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-timer" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.29", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-udp" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "log 0.4.14", - "mio 0.6.22", - "tokio-codec", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-uds" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.29", - "iovec", - "libc", - "log 0.4.14", - "mio 0.6.22", - "mio-uds", - "tokio-codec", - "tokio-io", - "tokio-reactor", + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] @@ -8188,18 +7643,9 @@ dependencies = [ "bytes 1.1.0", "futures-core", "futures-sink", - "log 0.4.14", + "log", "pin-project-lite", - "tokio 1.16.1", -] - -[[package]] -name = "toml" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -dependencies = [ - "serde", + "tokio", ] [[package]] @@ -8224,7 +7670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", - "log 0.4.14", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -8236,9 +7682,9 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -8261,10 +7707,33 @@ dependencies = [ ] [[package]] -name = "traitobject" -version = "0.1.0" +name = "tracing-log" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77be66445c4eeebb934a7340f227bfe7b338173d3f8c00a60a5a58005c9faecf" +dependencies = [ + "ansi_term 0.12.1", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] [[package]] name = "treeline" @@ -8278,18 +7747,21 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" - [[package]] name = "typenum" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "ubyte" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42756bb9e708855de2f8a98195643dff31a97f0485d90d8467b39dc24be9e8fe" +dependencies = [ + "serde", +] + [[package]] name = "uname" version = "0.1.1" @@ -8300,12 +7772,13 @@ dependencies = [ ] [[package]] -name = "unicase" -version = "1.4.2" +name = "uncased" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" dependencies = [ - "version_check 0.1.5", + "serde", + "version_check", ] [[package]] @@ -8332,12 +7805,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -8350,8 +7817,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ - "generic-array 0.14.5", - "subtle 2.4.1", + "generic-array", + "subtle", ] [[package]] @@ -8360,17 +7827,6 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - [[package]] name = "url" version = "2.2.2" @@ -8378,9 +7834,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" dependencies = [ "form_urlencoded", - "idna 0.2.0", + "idna", "matches", - "percent-encoding 2.1.0", + "percent-encoding", "serde", ] @@ -8406,12 +7862,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "version_check" version = "0.9.3" @@ -8446,28 +7896,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", - "winapi 0.3.9", + "winapi", "winapi-util", ] -[[package]] -name = "want" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -dependencies = [ - "futures 0.1.29", - "log 0.4.14", - "try-lock", -] - [[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ - "log 0.4.14", + "log", "try-lock", ] @@ -8501,10 +7940,10 @@ checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" dependencies = [ "bumpalo", "lazy_static", - "log 0.4.14", - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "log", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-shared", ] @@ -8526,7 +7965,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ - "quote 1.0.18", + "quote", "wasm-bindgen-macro-support", ] @@ -8536,9 +7975,9 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -8559,16 +7998,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki" version = "0.22.0" @@ -8579,22 +8008,13 @@ dependencies = [ "untrusted", ] -[[package]] -name = "webpki-roots" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" -dependencies = [ - "webpki 0.21.2", -] - [[package]] name = "webpki-roots" version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" dependencies = [ - "webpki 0.22.0", + "webpki", ] [[package]] @@ -8626,12 +8046,6 @@ dependencies = [ "libc", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -8642,12 +8056,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -8660,7 +8068,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -8675,17 +8083,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", + "winapi", ] [[package]] @@ -8741,9 +8139,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] @@ -8754,8 +8152,8 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" dependencies = [ - "proc-macro2 1.0.37", - "quote 1.0.18", - "syn 1.0.91", + "proc-macro2", + "quote", + "syn", "synstructure", ] diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index 8d539d9287..f61607f41b 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -11,8 +11,7 @@ mc-util-uri = { path = "../util/uri" } clap = { version = "3.1", features = ["derive", "env"] } grpcio = "0.10.2" -rocket = { version = "0.4.10", default-features = false } -rocket_contrib = { version = "0.4.10", default-features = false, features = ["json"] } +rocket = { version = "0.5.0-rc.1", features = ["json"] } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" diff --git a/admin-http-gateway/src/main.rs b/admin-http-gateway/src/main.rs index 415a5e2e95..1bda68980f 100644 --- a/admin-http-gateway/src/main.rs +++ b/admin-http-gateway/src/main.rs @@ -11,12 +11,13 @@ use mc_common::logger::{create_app_logger, log, o}; use mc_util_grpc::{admin, admin_grpc::AdminApiClient, ConnectionUriGrpcioChannel, Empty}; use mc_util_uri::AdminUri; use rocket::{ + form::Form, get, post, - request::Form, response::{content, Redirect}, - routes, FromForm, + routes, + serde::json::Json, + FromForm, }; -use rocket_contrib::json::Json; use serde_derive::Serialize; use std::{convert::TryFrom, sync::Arc}; @@ -79,7 +80,7 @@ impl TryFrom<&admin::GetInfoResponse> for JsonInfoResponse { } #[get("/info")] -fn info(state: rocket::State) -> Result, String> { +fn info(state: &rocket::State) -> Result, String> { let info = state .admin_api_client .get_info(&Empty::new()) @@ -95,7 +96,7 @@ struct SetRustLogForm { #[post("/set-rust-log", data = "
")] fn set_rust_log( - state: rocket::State, + state: &rocket::State, form: Form, ) -> Result { let mut req = admin::SetRustLogRequest::new(); @@ -110,7 +111,7 @@ fn set_rust_log( } #[get("/metrics")] -fn metrics(state: rocket::State) -> Result { +fn metrics(state: &rocket::State) -> Result { let resp = state .admin_api_client .get_prometheus_metrics(&Empty::new()) @@ -118,7 +119,8 @@ fn metrics(state: rocket::State) -> Result { Ok(resp.metrics) } -fn main() { +#[rocket::main] +async fn main() -> Result<(), rocket::Error> { mc_common::setup_panic_handler(); let _sentry_guard = mc_common::sentry::init(); @@ -138,13 +140,13 @@ fn main() { ChannelBuilder::default_channel_builder(env).connect_to_uri(&config.admin_uri, &logger); let admin_api_client = AdminApiClient::new(ch); - let rocket_config = rocket::Config::build(rocket::config::Environment::Production) - .address(&config.listen_host) - .port(config.listen_port) - .unwrap(); + let figment = rocket::Config::figment() + .merge(("port", config.listen_port)) + .merge(("address", config.listen_host.clone())); - rocket::custom(rocket_config) + rocket::custom(figment) .mount("/", routes![index, info, set_rust_log, metrics]) .manage(State { admin_api_client }) - .launch(); + .launch() + .await } diff --git a/api/Cargo.toml b/api/Cargo.toml index 92d4bbb2a9..3d703d3a16 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -17,7 +17,7 @@ mc-util-serial = { path = "../util/serial" } mc-watcher-api = { path = "../watcher/api" } bs58 = "0.4.0" -crc = "2.1.0" +crc = "3.0.0" displaydoc = { version = "0.2", default-features = false } protobuf = "2.27.1" diff --git a/attest/verifier/build.rs b/attest/verifier/build.rs index faf4d8c245..f960bc298c 100644 --- a/attest/verifier/build.rs +++ b/attest/verifier/build.rs @@ -140,7 +140,9 @@ fn main() { purge_expired_cert(&root_anchor_path); purge_expired_cert(&chain_path); - if !(root_anchor_path.exists() && signer_key_path.exists() && chain_path.exists()) { + if !(root_anchor_path.exists() && signer_key_path.exists() && chain_path.exists()) + || env::var("MC_SEED").is_ok() + { const ROOT_SUBJECT: &str = "C=US,ST=CA,L=Santa Clara,O=Intel Corporation,CN=Simulation Intel SGX Attestation Report Signing CA\0"; const SIGNER_SUBJECT: &str = "C=US,ST=CA,L=Santa Clara,O=Intel Corporation,CN=Simulation Intel SGX Attestation Report Signer\0"; diff --git a/attest/verifier/data/sim/.gitignore b/attest/verifier/data/sim/.gitignore index 9193cf5d56..458dcb7c0a 100644 --- a/attest/verifier/data/sim/.gitignore +++ b/attest/verifier/data/sim/.gitignore @@ -1,3 +1,3 @@ *.pem *.crt -*.key +*.key \ No newline at end of file diff --git a/common/Cargo.toml b/common/Cargo.toml index 000cc148f1..a73f7db186 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -51,7 +51,7 @@ binascii = "0.1.4" cfg-if = "1.0" chrono = { version = "0.4", optional = true } displaydoc = { version = "0.2", default-features = false } -hashbrown = { version = "0.11.2", default-features = false, features = ["serde", "nightly"] } +hashbrown = { version = "0.12.1", default-features = false, features = ["serde", "nightly"] } hex_fmt = "0.3" hostname = { version = "0.3.1", optional = true } lazy_static = { version = "1.4", optional = true } diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index 539c640580..131a1375f8 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -58,7 +58,9 @@ rand = "0.8" rand_hc = "0.3" [build-dependencies] +mc-crypto-keys = { path = "../../../crypto/keys" } mc-util-build-script = { path = "../../../util/build/script" } cargo-emit = "0.2" hex = "0.4" +pem = "1.0" diff --git a/consensus/enclave/impl/build.rs b/consensus/enclave/impl/build.rs index 24228a5ac8..c9eda0e493 100644 --- a/consensus/enclave/impl/build.rs +++ b/consensus/enclave/impl/build.rs @@ -3,6 +3,7 @@ //! Bake the compile-time target features into the enclave. use cargo_emit::rerun_if_env_changed; +use mc_crypto_keys::{DistinguishedEncoding, Ed25519Public, ReprBytes}; use mc_util_build_script::Environment; use std::{env::var, fs}; @@ -33,19 +34,15 @@ fn main() { rerun_if_env_changed!("FEE_SPEND_PUBLIC_KEY"); rerun_if_env_changed!("FEE_VIEW_PUBLIC_KEY"); - rerun_if_env_changed!("MINTING_TRUST_ROOT_PUBLIC_KEY"); let mut fee_spend_public_key = [0u8; 32]; let mut fee_view_public_key = [0u8; 32]; - let mut minting_trust_root_public_key = [0u8; 32]; // These public keys are associated with the private keys used in the tests for // consensus/enclave/impl. These are the hex-encoded public spend and view key // bytes as well as a minting trust root public key. let default_fee_spend_pub = "26b507c63124a2f5e940b4fb89e4b2bb0a2078ed0c8e551ad59268b9646ec241"; let default_fee_view_pub = "5222a1e9ae32d21c23114a5ce6bb39e0cb56aea350d4619d43b1207061b10346"; - let default_minting_trust_root_pub = - "1f4fe69277ae2385e9ecd9dde5e42e9ea7907ef3982a63d9ce4118950b696e35"; // Check for env var and override fee_spend_public_key[..].copy_from_slice( @@ -61,13 +58,28 @@ fn main() { .expect("Failed parsing public view key."), ); - minting_trust_root_public_key[..].copy_from_slice( - &hex::decode( - &var("MINTING_TRUST_ROOT_PUBLIC_KEY") - .unwrap_or_else(|_| default_minting_trust_root_pub.to_string()), - ) - .expect("Failed parsing public minting trust root key."), - ); + // Get the minting trust root public key from the env var or use the default. + // The default comes from a private key that was generated using the + // mc-util-seeded-ed25519-key-gen utility with the seed + // abababababababababababababababababababababababababababababababab + let default_minting_trust_root_pub = r#" + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VwAyEAH0/mkneuI4Xp7Nnd5eQunqeQfvOYKmPZzkEYlQtpbjU= + -----END PUBLIC KEY-----"#; + + rerun_if_env_changed!("MINTING_TRUST_ROOT_PUBLIC_KEY_PEM"); + let pem_bytes = if let Ok(pem_file_path) = var("MINTING_TRUST_ROOT_PUBLIC_KEY_PEM") { + cargo_emit::rerun_if_changed!(pem_file_path); + fs::read(pem_file_path).expect("Failed reading minting trust root public key PEM file") + } else { + default_minting_trust_root_pub.as_bytes().to_vec() + }; + + let parsed_pem = + pem::parse(&pem_bytes).expect("Failed parsing minting trust root public key PEM file"); + let minting_trust_root_public_key = Ed25519Public::try_from_der(&parsed_pem.contents[..]) + .expect("Failed parsing minting trust root public key DER"); + let minting_trust_root_public_key_bytes = minting_trust_root_public_key.to_bytes(); let mut constants = "// Copyright (c) 2018-2022 The MobileCoin Foundation\n\n// Auto-generated file\n\n" @@ -82,7 +94,7 @@ fn main() { )); constants.push_str(&format!( "pub const MINTING_TRUST_ROOT_PUBLIC_KEY: [u8; 32] = {:?};\n", - minting_trust_root_public_key + minting_trust_root_public_key_bytes )); // Output directory for generated constants. diff --git a/consensus/enclave/impl/src/lib.rs b/consensus/enclave/impl/src/lib.rs index 8cade02fae..6cf121701a 100644 --- a/consensus/enclave/impl/src/lib.rs +++ b/consensus/enclave/impl/src/lib.rs @@ -325,10 +325,18 @@ impl SgxConsensusEnclave { } /// Validate a list of MintConfigTxs. + /// + /// # Arguments + /// * `mint_config_txs` - The [MintConfigTx] objects to validate. + /// * `current_block_index` - The index of the current block that is being + /// built. See documentation of + /// [mc_transaction_core::mint::validate_mint_config_tx] for more details + /// on why this is optional. + /// * `config` - The current blockchain configuration. fn validate_mint_config_txs( &self, mint_config_txs: Vec, - current_block_index: u64, + current_block_index: Option, config: &BlockchainConfig, ) -> Result> { let mut seen_nonces = BTreeSet::default(); @@ -401,7 +409,11 @@ impl SgxConsensusEnclave { } // The associated MintConfigTx should be valid. - self.validate_mint_config_txs(vec![mint_config_tx], current_block_index, config)?; + // No block index is passed since the MintConfigTx is already assumed to be in + // the ledger, so doing the tombstone check is pointless (and could + // fail if enough blocks have passed since the MintConfigTx got + // accepted). + self.validate_mint_config_txs(vec![mint_config_tx], None, config)?; // The MintTx should be valid. validate_mint_tx( @@ -902,8 +914,11 @@ impl ConsensusEnclave for SgxConsensusEnclave { key_images.sort(); // Get the list of MintConfigTxs included in the block. - let validated_mint_config_txs = - self.validate_mint_config_txs(inputs.mint_config_txs, parent_block.index + 1, config)?; + let validated_mint_config_txs = self.validate_mint_config_txs( + inputs.mint_config_txs, + Some(parent_block.index + 1), + config, + )?; // We purposefully do not ..Default::default() here so that new block fields // show up as a compilation error until addressed. @@ -2250,7 +2265,12 @@ mod tests { // Initialize a ledger. let sender = AccountKey::random(&mut rng); let mut ledger = create_ledger(); - let n_blocks = 3; + + // We want the next block that getts appended to the ledger to exceed the + // tombstone limit of the mint config tx, since we want to make sure + // that minting that relies on an old MintConfigTx (one that is past + // its tombstone block) still validate and mint successfully. + let n_blocks = mint_config_tx1.prefix.tombstone_block; initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); // Form block @@ -2541,7 +2561,7 @@ mod tests { // Initialize a ledger. let sender = AccountKey::random(&mut rng); let mut ledger = create_ledger(); - let n_blocks = 3; + let n_blocks = mint_config_tx1.prefix.tombstone_block - 1; // Don't want to exceed the tombstone block initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); // Form block @@ -2700,7 +2720,7 @@ mod tests { // Initialize a ledger. let sender = AccountKey::random(&mut rng); let mut ledger = create_ledger(); - let n_blocks = 3; + let n_blocks = mint_config_tx1.prefix.tombstone_block - 1; // Don't want to exceed the tombstone block initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); // Form block @@ -2761,7 +2781,7 @@ mod tests { // Initialize a ledger. let sender = AccountKey::random(&mut rng); let mut ledger = create_ledger(); - let n_blocks = 3; + let n_blocks = mint_config_tx1.prefix.tombstone_block - 1; // Don't want to exceed the tombstone block initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); // Form block diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index 9613399838..df77880776 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -40,9 +40,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.8" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -294,18 +294,18 @@ dependencies = [ [[package]] name = "crc" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" -version = "1.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" [[package]] name = "crypto-common" @@ -364,9 +364,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" +checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" dependencies = [ "serde", "signature", @@ -470,9 +470,9 @@ checksum = "20d6a47d6e4b8559729f58287efa8e6f767e603c068fea7a5e4d9f1cebe2bebb" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" dependencies = [ "serde", ] @@ -834,6 +834,7 @@ dependencies = [ "mc-util-from-random", "mc-util-serial", "once_cell", + "pem", "prost", "rand_core", "subtle", @@ -1256,9 +1257,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "merlin" @@ -1340,6 +1341,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +[[package]] +name = "pem" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" +dependencies = [ + "base64", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1372,18 +1382,18 @@ checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "prost" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07b0857a71a8cb765763950499cae2413c3f9cede1133478c43600d9e146890" +checksum = "bc03e116981ff7d8da8e5c220e374587b98d294af7ba7dd7fda761158f00086f" dependencies = [ "bytes", "prost-derive", @@ -1452,21 +1462,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.14" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "rjson" @@ -1524,9 +1533,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] @@ -1551,9 +1560,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -1640,9 +1649,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.67" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ "proc-macro2", "quote", @@ -1679,15 +1688,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - [[package]] name = "time" version = "0.1.43" @@ -1859,9 +1859,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index 24545f1fe5..99c0d76001 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -30,6 +30,7 @@ clap = { version = "3.1", features = ["derive", "env"] } grpcio = "0.10.2" hex = "0.4" pem = "1.0" +protobuf = "2.27.1" rand = "0.8" serde = "1" serde_json = "1.0" diff --git a/consensus/mint-client/src/bin/main.rs b/consensus/mint-client/src/bin/main.rs index c621bc5cd3..d6b7595678 100644 --- a/consensus/mint-client/src/bin/main.rs +++ b/consensus/mint-client/src/bin/main.rs @@ -18,8 +18,9 @@ use mc_transaction_core::{ mint::{MintConfigTx, MintTx}, }; use mc_util_grpc::ConnectionUriGrpcioChannel; +use protobuf::ProtobufEnum; use serde::de::DeserializeOwned; -use std::{fs, path::PathBuf, sync::Arc}; +use std::{fs, path::PathBuf, process::exit, sync::Arc}; fn main() { let (logger, _global_logger_guard) = create_app_logger(o!()); @@ -45,6 +46,11 @@ fn main() { .propose_mint_config_tx(&(&tx).into()) .expect("propose tx"); println!("response: {:?}", resp); + + // Relying on the success result code being 0, we terminate ourselves in a way + // that allows whoever started this binary to easily determine if submitting the + // transaction succeeded. + exit(resp.get_result().get_code().value()); } Commands::GenerateMintConfigTx { out, params } => { @@ -101,6 +107,11 @@ fn main() { .propose_mint_config_tx(&(&merged_tx).into()) .expect("propose tx"); println!("response: {:?}", resp); + + // Relying on the success result code being 0, we terminate ourselves in a way + // that allows whoever started this binary to easily determine if submitting the + // transaction succeeded. + exit(resp.get_result().get_code().value()); } Commands::GenerateAndSubmitMintTx { node, params } => { @@ -121,6 +132,11 @@ fn main() { .propose_mint_tx(&(&tx).into()) .expect("propose tx"); println!("response: {:?}", resp); + + // Relying on the success result code being 0, we terminate ourselves in a way + // that allows whoever started this binary to easily determine if submitting the + // transaction succeeded. + exit(resp.get_result().get_code().value()); } Commands::GenerateMintTx { out, params } => { @@ -177,6 +193,11 @@ fn main() { .propose_mint_tx(&(&merged_tx).into()) .expect("propose tx"); println!("response: {:?}", resp); + + // Relying on the success result code being 0, we terminate ourselves in a way + // that allows whoever started this binary to easily determine if submitting the + // transaction succeeded. + exit(resp.get_result().get_code().value()); } Commands::SignGovernors { diff --git a/consensus/scp/tests/mock_network/mod.rs b/consensus/scp/tests/mock_network/mod.rs index c9459b1060..b75557d163 100644 --- a/consensus/scp/tests/mock_network/mod.rs +++ b/consensus/scp/tests/mock_network/mod.rs @@ -77,7 +77,7 @@ impl TestOptions { values_to_submit: 5000, submissions_per_sec: 20000, max_slot_proposed_values: 100, - allowed_test_time: Duration::from_secs(300), + allowed_test_time: Duration::from_secs(500), log_flush_delay: Duration::from_millis(50), scp_timebase: Duration::from_millis(1000), validity_fn: Arc::new(test_utils::trivial_validity_fn::), diff --git a/consensus/service/src/consensus_service.rs b/consensus/service/src/consensus_service.rs index 4d06d33515..3d15b3f471 100644 --- a/consensus/service/src/consensus_service.rs +++ b/consensus/service/src/consensus_service.rs @@ -382,12 +382,13 @@ impl< .build(), ); - let server_builder = ServerBuilder::new(env) + let server_builder = ServerBuilder::new(env.clone()) .register_service(client_service) .register_service(blockchain_service) .register_service(health_service) .register_service(attested_service) .register_service(build_info_service) + .set_default_channel_args(env) .bind_using_uri(&self.config.client_listen_uri, self.logger.clone()); let mut server = server_builder.build().unwrap(); diff --git a/consensus/service/src/mint_tx_manager/mod.rs b/consensus/service/src/mint_tx_manager/mod.rs index f77e4078c4..a089bbbc9b 100644 --- a/consensus/service/src/mint_tx_manager/mod.rs +++ b/consensus/service/src/mint_tx_manager/mod.rs @@ -83,13 +83,13 @@ impl MintTxManager for MintTxManagerImpl { MintValidationError::NoGovernors(token_id), ))?; - // Get the current block index. - let current_block_index = self.ledger_db.num_blocks()? - 1; + // Get the index of the block currently being built. + let current_block_index = self.ledger_db.num_blocks()?; // Perform the actual validation. validate_mint_config_tx( mint_config_tx, - current_block_index, + Some(current_block_index), self.block_version, &governors, )?; @@ -147,8 +147,8 @@ impl MintTxManager for MintTxManagerImpl { err => err.into(), })?; - // Get the current block index. - let current_block_index = self.ledger_db.num_blocks()? - 1; + // Get the index of the block currently being built. + let current_block_index = self.ledger_db.num_blocks()?; // Perform the actual validation. validate_mint_tx( @@ -236,9 +236,9 @@ mod mint_config_tx_tests { use super::*; use mc_common::logger::test_with_logger; use mc_crypto_multisig::SignerSet; - use mc_transaction_core::{Block, BlockContents}; + use mc_transaction_core::{ring_signature::KeyImage, Block, BlockContents}; use mc_transaction_core_test_utils::{ - create_ledger, create_mint_config_tx_and_signers, initialize_ledger, + create_ledger, create_mint_config_tx_and_signers, create_test_tx_out, initialize_ledger, mint_config_tx_to_validated as to_validated, AccountKey, }; use rand::{rngs::StdRng, SeedableRng}; @@ -251,7 +251,7 @@ mod mint_config_tx_tests { let token_id_1 = TokenId::from(1); let mut ledger = create_ledger(); - let n_blocks = 3; + let n_blocks = 1; let block_version = BlockVersion::MAX; let sender = AccountKey::random(&mut rng); initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); @@ -281,7 +281,7 @@ mod mint_config_tx_tests { let token_id_3 = TokenId::from(3); let mut ledger = create_ledger(); - let n_blocks = 3; + let n_blocks = 1; let block_version = BlockVersion::MAX; let sender = AccountKey::random(&mut rng); initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); @@ -323,6 +323,72 @@ mod mint_config_tx_tests { ); } + /// validate_mint_config_tx rejects a mint config tx with an exceeded + /// tombstone block. + #[test_with_logger] + fn validate_mint_config_tx_rejects_past_tombstone(logger: Logger) { + let mut rng: StdRng = SeedableRng::from_seed([77u8; 32]); + let token_id_1 = TokenId::from(1); + + let (mint_config_tx, signers) = create_mint_config_tx_and_signers(token_id_1, &mut rng); + let token_id_to_governors = GovernorsMap::try_from_iter(vec![( + token_id_1, + SignerSet::new(signers.iter().map(|s| s.public_key()).collect(), 1), + )]) + .unwrap(); + + let mut ledger = create_ledger(); + // tombstone_block specifies that the tx will get accepted at any block whose + // index is less than tombstone_block. n_blocks controls how many blocks + // we create, specifically it will result in blocks with indexes [0, n_blocks). + // setting n_blocks to tombstone_block - 1 means the transaction will be valid + // for exactly 1 block, but once that's written it will exceed it. + let n_blocks = mint_config_tx.prefix.tombstone_block - 1; + let block_version = BlockVersion::MAX; + let sender = AccountKey::random(&mut rng); + initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); + + let mint_tx_manager = MintTxManagerImpl::new( + ledger.clone(), + BlockVersion::MAX, + token_id_to_governors, + logger, + ); + + // At first we should succeed since we have not yet exceeded the tombstone + // block. + assert_eq!( + mint_tx_manager.validate_mint_config_tx(&mint_config_tx), + Ok(()) + ); + + // Append a block to the ledger. + let parent_block = ledger.get_block(n_blocks - 1).unwrap(); + + let block_contents = BlockContents { + outputs: vec![create_test_tx_out(&mut rng)], + key_images: vec![KeyImage::from(123)], + ..Default::default() + }; + + let block = Block::new_with_parent( + BlockVersion::MAX, + &parent_block, + &Default::default(), + &block_contents, + ); + + ledger.append_block(&block, &block_contents, None).unwrap(); + + // Try again, we should fail. + assert_eq!( + mint_tx_manager.validate_mint_config_tx(&mint_config_tx), + Err(MintTxManagerError::MintValidation( + MintValidationError::TombstoneBlockExceeded + )) + ); + } + /// validate_mint_config_tx rejects a mint config tx with a nonce that /// already appears in the ledger. #[test_with_logger] @@ -331,7 +397,7 @@ mod mint_config_tx_tests { let token_id_1 = TokenId::from(1); let mut ledger = create_ledger(); - let n_blocks = 3; + let n_blocks = 1; let block_version = BlockVersion::MAX; let sender = AccountKey::random(&mut rng); initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); @@ -422,7 +488,7 @@ mod mint_config_tx_tests { let token_id_1 = TokenId::from(1); let mut ledger = create_ledger(); - let n_blocks = 3; + let n_blocks = 1; let block_version = BlockVersion::MAX; let sender = AccountKey::random(&mut rng); initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); @@ -562,7 +628,7 @@ mod mint_tx_tests { use mc_common::logger::test_with_logger; use mc_crypto_keys::Ed25519Pair; use mc_crypto_multisig::SignerSet; - use mc_transaction_core::{Block, BlockContents}; + use mc_transaction_core::{ring_signature::KeyImage, Block, BlockContents}; use mc_transaction_core_test_utils::{ create_ledger, create_mint_config_tx_and_signers, create_mint_tx, create_test_tx_out, initialize_ledger, mint_config_tx_to_validated as to_validated, AccountKey, @@ -1085,6 +1151,174 @@ mod mint_tx_tests { ); } + /// validate_mint_tx rejects a tx with an exceeded tombstone block. + #[test_with_logger] + fn validate_mint_tx_rejects_past_tombstone(logger: Logger) { + let mut rng: StdRng = SeedableRng::from_seed([77u8; 32]); + let token_id_1 = TokenId::from(1); + + let (mint_config_tx, signers) = create_mint_config_tx_and_signers(token_id_1, &mut rng); + let mint_tx = create_mint_tx( + token_id_1, + &[Ed25519Pair::from(signers[0].private_key())], + 1, + &mut rng, + ); + + let mut ledger = create_ledger(); + // tombstone_block specifies that the tx will get accepted at any block whose + // index is less than tombstone_block. n_blocks controls how many blocks + // we create, specifically it will result in blocks with indexes [0, n_blocks). + // setting n_blocks to tombstone_block - 1 means the transaction will be valid + // for exactly 1 block, but once that's written it will exceed it. However, we + // subtract 2 since we also need to add a block for the mint config tx. + let n_blocks = mint_tx.prefix.tombstone_block - 2; + let block_version = BlockVersion::MAX; + let sender = AccountKey::random(&mut rng); + initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); + + // Append the mint config to the ledger + let parent_block = ledger.get_block(ledger.num_blocks().unwrap() - 1).unwrap(); + + let block_contents = BlockContents { + validated_mint_config_txs: vec![to_validated(&mint_config_tx)], + ..Default::default() + }; + + let block = Block::new_with_parent( + BlockVersion::MAX, + &parent_block, + &Default::default(), + &block_contents, + ); + + ledger.append_block(&block, &block_contents, None).unwrap(); + + // Create MintTxManagerImpl + let token_id_to_governors = GovernorsMap::try_from_iter(vec![( + token_id_1, + SignerSet::new(signers.iter().map(|s| s.public_key()).collect(), 1), + )]) + .unwrap(); + let mint_tx_manager = MintTxManagerImpl::new( + ledger.clone(), + BlockVersion::MAX, + token_id_to_governors, + logger, + ); + + // At first we should succeed since we have not yet exceeded the tombstone + // block. + assert_eq!(mint_tx_manager.validate_mint_tx(&mint_tx), Ok(())); + + // Append a block to the ledger. + let parent_block = block; + + let block_contents = BlockContents { + outputs: vec![create_test_tx_out(&mut rng)], + key_images: vec![KeyImage::from(123)], + ..Default::default() + }; + + let block = Block::new_with_parent( + BlockVersion::MAX, + &parent_block, + &Default::default(), + &block_contents, + ); + + ledger.append_block(&block, &block_contents, None).unwrap(); + + // Try again, we should fail. + assert_eq!( + mint_tx_manager.validate_mint_tx(&mint_tx), + Err(MintTxManagerError::MintValidation( + MintValidationError::TombstoneBlockExceeded + )) + ); + } + + /// validate_mint_tx rejects duplicate nonce. + #[test_with_logger] + fn validate_mint_tx_rejects_duplicate_nonce(logger: Logger) { + let mut rng: StdRng = SeedableRng::from_seed([77u8; 32]); + let token_id_1 = TokenId::from(1); + + let mut ledger = create_ledger(); + let n_blocks = 3; + let block_version = BlockVersion::MAX; + let sender = AccountKey::random(&mut rng); + initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); + + // Create a mint configuration and append it to the ledger. + let (mint_config_tx, signers) = create_mint_config_tx_and_signers(token_id_1, &mut rng); + + let parent_block = ledger.get_block(ledger.num_blocks().unwrap() - 1).unwrap(); + + let block_contents = BlockContents { + validated_mint_config_txs: vec![to_validated(&mint_config_tx)], + ..Default::default() + }; + + let block = Block::new_with_parent( + BlockVersion::MAX, + &parent_block, + &Default::default(), + &block_contents, + ); + + ledger.append_block(&block, &block_contents, None).unwrap(); + + // Create MintTxManagerImpl + let token_id_to_governors = GovernorsMap::try_from_iter(vec![( + token_id_1, + SignerSet::new(signers.iter().map(|s| s.public_key()).collect(), 1), + )]) + .unwrap(); + let mint_tx_manager = MintTxManagerImpl::new( + ledger.clone(), + BlockVersion::MAX, + token_id_to_governors, + logger, + ); + + // Create a valid MintTx signed by the governor. + let mint_tx = create_mint_tx( + token_id_1, + &[Ed25519Pair::from(signers[0].private_key())], + 1, + &mut rng, + ); + + // At first we should succeed since the nonce is not yet in the ledger. + assert_eq!(mint_tx_manager.validate_mint_tx(&mint_tx), Ok(())); + + // Append to the ledger. + let block_contents = BlockContents { + outputs: vec![create_test_tx_out(&mut rng)], + mint_txs: vec![mint_tx.clone()], + ..Default::default() + }; + + let parent_block = block; + let block = Block::new_with_parent( + BlockVersion::MAX, + &parent_block, + &Default::default(), + &block_contents, + ); + + ledger.append_block(&block, &block_contents, None).unwrap(); + + // Try again, we should fail. + assert_eq!( + mint_tx_manager.validate_mint_tx(&mint_tx), + Err(MintTxManagerError::MintValidation( + MintValidationError::NonceAlreadyUsed + )) + ); + } + /// combine_mint_txs adequately sorts inputs and disposes of /// duplicates. #[test_with_logger] diff --git a/consensus/service/src/validators.rs b/consensus/service/src/validators.rs index 7b8556149f..10732a6239 100644 --- a/consensus/service/src/validators.rs +++ b/consensus/service/src/validators.rs @@ -72,6 +72,7 @@ impl TxManagerUntrustedInterfaces for DefaultTxManagerUntruste /// Checks if a transaction is valid (see definition at top of this file). fn is_valid(&self, context: Arc) -> TransactionValidationResult<()> { + // Get the index of the current block we will be building. let current_block_index = self .ledger .num_blocks() diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index 2e6d5c1006..edea1a59a0 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -15,7 +15,7 @@ mc-util-repr-bytes = { path = "../../util/repr-bytes" } binascii = "0.1.2" digest = "0.10" displaydoc = { version = "0.2", default-features = false } -ed25519 = { version = "1.4", default-features = false, features = ["serde"] } +ed25519 = { version = "1.5", default-features = false, features = ["serde"] } hex_fmt = "0.3" rand_core = { version = "0.6", default-features = false } rand_hc = "0.3" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index 350fa79932..f84395f456 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -19,7 +19,7 @@ secrecy = "0.8" serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } sha2 = { version = "0.10", default-features = false } subtle = { version = "2.4.1", default-features = false, features = ["i128"] } -zeroize = "1.5.4" +zeroize = "1.5" [dev-dependencies] rand_hc = "0.3" diff --git a/docker/Dockerfile b/docker/Dockerfile index 3ba0365ff7..131137966b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -48,7 +48,6 @@ RUN sed -ie 's|host all all 127.0.0.1/32 m su postgres -c "createuser --superuser root" # Export postgres database url's for build environment, for local testing and conformance tests -ENV DATABASE_URL="postgres://localhost" ENV TEST_DATABASE_URL="postgres://localhost" # Export sgx sdk environment variables diff --git a/docker/Dockerfile-version b/docker/Dockerfile-version index 1701d6efde..9d6e30e0f8 100644 --- a/docker/Dockerfile-version +++ b/docker/Dockerfile-version @@ -1 +1 @@ -1_26 +1_27 diff --git a/docker/init_debian.sh b/docker/init_debian.sh index 8a32b647da..f9c5622042 100755 --- a/docker/init_debian.sh +++ b/docker/init_debian.sh @@ -50,6 +50,7 @@ apt-get install --yes \ patch \ pkg-config \ postgresql \ + postgresql-client \ prometheus \ protobuf-c-compiler \ protobuf-compiler \ diff --git a/docker/rust-toolchain b/docker/rust-toolchain index 65b2c487cb..0ad503aac3 100644 --- a/docker/rust-toolchain +++ b/docker/rust-toolchain @@ -1 +1 @@ -nightly-2022-01-10 +nightly-2022-04-29 diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index af3fe400f8..35cadc45f2 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -323,18 +323,18 @@ dependencies = [ [[package]] name = "crc" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" -version = "1.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" [[package]] name = "crypto-common" @@ -393,9 +393,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" +checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" dependencies = [ "serde", "signature", @@ -499,9 +499,9 @@ checksum = "20d6a47d6e4b8559729f58287efa8e6f767e603c068fea7a5e4d9f1cebe2bebb" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" dependencies = [ "serde", ] @@ -1486,18 +1486,18 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "prost" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07b0857a71a8cb765763950499cae2413c3f9cede1133478c43600d9e146890" +checksum = "bc03e116981ff7d8da8e5c220e374587b98d294af7ba7dd7fda761158f00086f" dependencies = [ "bytes", "prost-derive", @@ -1638,9 +1638,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] @@ -1665,9 +1665,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -1754,9 +1754,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.67" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ "proc-macro2", "quote", @@ -1983,9 +1983,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 0ce5509a13..2de2e5731e 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -318,18 +318,18 @@ dependencies = [ [[package]] name = "crc" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" -version = "1.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" [[package]] name = "crypto-common" @@ -388,9 +388,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" +checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" dependencies = [ "serde", "signature", @@ -494,9 +494,9 @@ checksum = "20d6a47d6e4b8559729f58287efa8e6f767e603c068fea7a5e4d9f1cebe2bebb" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" dependencies = [ "serde", ] @@ -1471,9 +1471,9 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] @@ -1622,9 +1622,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] @@ -1649,9 +1649,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -1738,9 +1738,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.73" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ "proc-macro2", "quote", @@ -1958,9 +1958,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 2cae048162..cd9eb3ec13 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -17,8 +17,7 @@ grpcio = "0.10.2" lazy_static = "1.4" prometheus = "0.13.0" retry = "1.3" -rocket = { version = "0.4.5", default-features = false } -rocket_contrib = { version = "0.4.5", default-features = false, features = ["json"] } +rocket = { version = "0.5.0-rc.1", features = ["json"] } serde = "1" # mc diff --git a/fog/overseer/server/src/bin/main.rs b/fog/overseer/server/src/bin/main.rs index 75dd5d03f8..eabec6e9b4 100644 --- a/fog/overseer/server/src/bin/main.rs +++ b/fog/overseer/server/src/bin/main.rs @@ -12,7 +12,8 @@ use mc_fog_overseer_server::{config::OverseerConfig, server, service::OverseerSe use mc_fog_sql_recovery_db::SqlRecoveryDb; use mc_util_cli::ParserWithBuildInfo; -fn main() { +#[rocket::main] +async fn main() -> Result<(), rocket::Error> { mc_common::setup_panic_handler(); let _sentry_guard = sentry::init(); let config = OverseerConfig::parse(); @@ -36,12 +37,10 @@ fn main() { let overseer_state = server::OverseerState { overseer_service }; - let rocket_config: rocket::Config = - rocket::Config::build(rocket::config::Environment::Development) - .address(config.overseer_listen_host) - .port(config.overseer_listen_port) - .unwrap(); + let rocket_config = rocket::Config::figment() + .merge(("port", config.overseer_listen_port)) + .merge(("address", config.overseer_listen_host.clone())); let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - rocket.launch(); + rocket.launch().await } diff --git a/fog/overseer/server/src/server.rs b/fog/overseer/server/src/server.rs index 78f260b819..aaed981ac8 100644 --- a/fog/overseer/server/src/server.rs +++ b/fog/overseer/server/src/server.rs @@ -10,27 +10,26 @@ use crate::{ }; use mc_fog_recovery_db_iface::RecoveryDb; use mc_fog_sql_recovery_db::SqlRecoveryDb; -use rocket::{get, post, routes}; -use rocket_contrib::json::Json; +use rocket::{get, post, routes, serde::json::Json}; #[post("/enable")] -fn enable(state: rocket::State>) -> Result { +fn enable(state: &rocket::State>) -> Result { state.overseer_service.enable() } #[post("/disable")] -fn disable(state: rocket::State>) -> Result { +fn disable(state: &rocket::State>) -> Result { state.overseer_service.disable() } #[get("/status")] -fn get_status(state: rocket::State>) -> Result { +fn get_status(state: &rocket::State>) -> Result { state.overseer_service.get_status() } #[get("/ingest_summaries")] fn get_ingest_summaries( - state: rocket::State>, + state: &rocket::State>, ) -> Result, String> { state.overseer_service.get_ingest_summaries().map(Json) } @@ -39,7 +38,7 @@ fn get_ingest_summaries( /// /// Meant to be called only by the Prometheus pull mechanism. #[get("/metrics")] -fn get_metrics(state: rocket::State>) -> Result { +fn get_metrics(state: &rocket::State>) -> Result { state.overseer_service.get_metrics() } @@ -56,10 +55,10 @@ where /// Returns an instance of a Rocket server. #[must_use = "Use with a Client or call launch"] -pub fn initialize_rocket_server( - rocket_config: rocket::Config, +pub fn initialize_rocket_server( + rocket_config: T, state: OverseerState, -) -> rocket::Rocket { +) -> rocket::Rocket { rocket::custom(rocket_config) .mount( "/", diff --git a/fog/overseer/server/tests/get_ingest_summaries.rs b/fog/overseer/server/tests/get_ingest_summaries.rs index 0c212ea901..94fef9edac 100644 --- a/fog/overseer/server/tests/get_ingest_summaries.rs +++ b/fog/overseer/server/tests/get_ingest_summaries.rs @@ -9,7 +9,7 @@ use mc_watcher::watcher_db::WatcherDB; use rand_core::SeedableRng; use rand_hc::Hc128Rng; use regex::Regex; -use rocket::local::Client; +use rocket::local::blocking::Client; use std::time::Duration; use tempdir::TempDir; @@ -100,22 +100,19 @@ fn one_active_node_produces_ingest_summaries(logger: Logger) { // Set up the Rocket instance let overseer_state = OverseerState { overseer_service }; // TODO: Consider testing the CLI here instead. - let rocket_config: rocket::Config = - rocket::Config::build(rocket::config::Environment::Development) - // TODO: Make these either passed from CLI or in a Rocket.toml. - .address("127.0.0.1") - .port(PORT_NUMBER) - .unwrap(); + let rocket_config = rocket::Config::figment() + .merge(("port", PORT_NUMBER)) + .merge(("address", "127.0.0.1")); let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - let client = Client::new(rocket).expect("valid rocket instance"); + let client = Client::tracked(rocket).expect("valid rocket instance"); client.post("/enable").dispatch(); // Give overseer time to perform its logic. std::thread::sleep(Duration::from_secs(10)); - let mut response = client.get("/ingest_summaries").dispatch(); + let response = client.get("/ingest_summaries").dispatch(); - let body = response.body_string().unwrap(); + let body = response.into_string().unwrap(); let active_pattern = Regex::new("ACTIVE").unwrap(); active_pattern.captures(&body); diff --git a/fog/overseer/server/tests/inactive_outstanding_key_idle_does_not_have_key.rs b/fog/overseer/server/tests/inactive_outstanding_key_idle_does_not_have_key.rs index 2605f16add..be1246ca5c 100644 --- a/fog/overseer/server/tests/inactive_outstanding_key_idle_does_not_have_key.rs +++ b/fog/overseer/server/tests/inactive_outstanding_key_idle_does_not_have_key.rs @@ -10,7 +10,7 @@ use mc_transaction_core::{Block, BlockContents}; use mc_watcher::watcher_db::WatcherDB; use rand_core::SeedableRng; use rand_hc::Hc128Rng; -use rocket::local::Client; +use rocket::local::blocking::Client; use std::{convert::TryFrom, str::FromStr, time::Duration}; use tempdir::TempDir; use url::Url; @@ -116,14 +116,11 @@ fn inactive_oustanding_key_idle_node_does_not_have_key_idle_node_is_activated_an // Set up the Rocket instance let overseer_state = OverseerState { overseer_service }; // TODO: Consider testing the CLI here instead. - let rocket_config: rocket::Config = - rocket::Config::build(rocket::config::Environment::Development) - // TODO: Make these either passed from CLI or in a Rocket.toml. - .address("127.0.0.1") - .port(PORT_NUMBER) - .unwrap(); + let rocket_config = rocket::Config::figment() + .merge(("port", PORT_NUMBER)) + .merge(("address", "127.0.0.1")); let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - let client = Client::new(rocket).expect("valid rocket instance"); + let client = Client::tracked(rocket).expect("valid rocket instance"); client.post("/enable").dispatch(); // Add 11 test blocks. diff --git a/fog/overseer/server/tests/inactive_outstanding_key_idle_has_key.rs b/fog/overseer/server/tests/inactive_outstanding_key_idle_has_key.rs index 2d46ce48b4..f630414c4b 100644 --- a/fog/overseer/server/tests/inactive_outstanding_key_idle_has_key.rs +++ b/fog/overseer/server/tests/inactive_outstanding_key_idle_has_key.rs @@ -10,7 +10,7 @@ use mc_transaction_core::{Block, BlockContents}; use mc_watcher::watcher_db::WatcherDB; use rand_core::SeedableRng; use rand_hc::Hc128Rng; -use rocket::local::Client; +use rocket::local::blocking::Client; use std::{convert::TryFrom, str::FromStr, time::Duration}; use tempdir::TempDir; use url::Url; @@ -123,14 +123,11 @@ fn inactive_oustanding_key_idle_node_has_original_key_node_is_activated_and_key_ // Set up the Rocket instance let overseer_state = OverseerState { overseer_service }; // TODO: Consider testng the CLI here instead - let rocket_config: rocket::Config = - rocket::Config::build(rocket::config::Environment::Development) - // TODO: Make these either passed from CLI or in a Rocket.toml. - .address("127.0.0.1") - .port(PORT_NUMBER) - .unwrap(); + let rocket_config = rocket::Config::figment() + .merge(("port", PORT_NUMBER)) + .merge(("address", "127.0.0.1")); let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - let client = Client::new(rocket).expect("valid rocket instance"); + let client = Client::tracked(rocket).expect("valid rocket instance"); client.post("/enable").dispatch(); // Add 11 test blocks. diff --git a/fog/overseer/server/tests/one_active_node.rs b/fog/overseer/server/tests/one_active_node.rs index 82266e0e9e..2a39a7f887 100644 --- a/fog/overseer/server/tests/one_active_node.rs +++ b/fog/overseer/server/tests/one_active_node.rs @@ -7,7 +7,7 @@ use mc_fog_recovery_db_iface::RecoveryDb; use mc_fog_sql_recovery_db::test_utils::SqlRecoveryDbTestContext; use mc_ledger_db::LedgerDB; use mc_watcher::watcher_db::WatcherDB; -use rocket::local::Client; +use rocket::local::blocking::Client; use std::{convert::TryFrom, str::FromStr, time::Duration}; use tempdir::TempDir; use url::Url; @@ -92,12 +92,9 @@ fn one_active_node_cluster_state_does_not_change(logger: Logger) { // Consider testing the CLI here instead // Initialize an OverSeerService object... - let rocket_config: rocket::Config = - rocket::Config::build(rocket::config::Environment::Development) - // TODO: Make these either passed from CLI or in a Rocket.toml. - .address("127.0.0.1") - .port(PORT_NUMBER) - .unwrap(); + let rocket_config = rocket::Config::figment() + .merge(("port", PORT_NUMBER)) + .merge(("address", "127.0.0.1")); let mut overseer_service = OverseerService::new( vec![client_listen_uri0, client_listen_uri1, client_listen_uri2], @@ -107,7 +104,7 @@ fn one_active_node_cluster_state_does_not_change(logger: Logger) { overseer_service.start().unwrap(); let overseer_state = OverseerState { overseer_service }; let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - let client = Client::new(rocket).expect("valid rocket instance"); + let client = Client::tracked(rocket).expect("valid rocket instance"); let _req = client.post("/enable").dispatch(); // Give Overseer time to perform logic diff --git a/fog/overseer/server/tests/prometheus_produces_metrics.rs b/fog/overseer/server/tests/prometheus_produces_metrics.rs index 38010d5c2f..4bf19c9a32 100644 --- a/fog/overseer/server/tests/prometheus_produces_metrics.rs +++ b/fog/overseer/server/tests/prometheus_produces_metrics.rs @@ -9,7 +9,7 @@ use mc_watcher::watcher_db::WatcherDB; use rand_core::SeedableRng; use rand_hc::Hc128Rng; use regex::Regex; -use rocket::local::Client; +use rocket::local::blocking::Client; use std::time::Duration; use tempdir::TempDir; @@ -104,22 +104,19 @@ fn one_active_node_idle_nodes_different_keys_produces_prometheus_metrics(logger: // Set up the Rocket instance let overseer_state = OverseerState { overseer_service }; // TODO: Consider testing the CLI here instead. - let rocket_config: rocket::Config = - rocket::Config::build(rocket::config::Environment::Development) - // TODO: Make these either passed from CLI or in a Rocket.toml. - .address("127.0.0.1") - .port(PORT_NUMBER) - .unwrap(); + let rocket_config = rocket::Config::figment() + .merge(("port", PORT_NUMBER)) + .merge(("address", "127.0.0.1")); let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - let client = Client::new(rocket).expect("valid rocket instance"); + let client = Client::tracked(rocket).expect("valid rocket instance"); client.post("/enable").dispatch(); // Give overseer time to perform its logic. std::thread::sleep(Duration::from_secs(10)); - let mut response = client.get("/metrics").dispatch(); + let response = client.get("/metrics").dispatch(); - let body = response.body_string().unwrap(); + let body = response.into_string().unwrap(); let correct_active_node_count = Regex::new(r#"active_node_count"} 1"#).unwrap(); assert!(correct_active_node_count.is_match(&body)); diff --git a/fog/overseer/server/tests/retired_key_not_outstanding_idles_have_different_keys.rs b/fog/overseer/server/tests/retired_key_not_outstanding_idles_have_different_keys.rs index 1d73159891..9bf300066e 100644 --- a/fog/overseer/server/tests/retired_key_not_outstanding_idles_have_different_keys.rs +++ b/fog/overseer/server/tests/retired_key_not_outstanding_idles_have_different_keys.rs @@ -10,7 +10,7 @@ use mc_transaction_core::{Block, BlockContents}; use mc_watcher::watcher_db::WatcherDB; use rand_core::SeedableRng; use rand_hc::Hc128Rng; -use rocket::local::Client; +use rocket::local::blocking::Client; use std::{convert::TryFrom, str::FromStr, time::Duration}; use tempdir::TempDir; use url::Url; @@ -123,14 +123,11 @@ fn active_key_is_retired_not_outstanding_idle_nodes_have_different_keys_new_key_ // Set up the Rocket instance let overseer_state = OverseerState { overseer_service }; // Consider testng the CLI here instead - let rocket_config: rocket::Config = - rocket::Config::build(rocket::config::Environment::Development) - // TODO: Make these either passed from CLI or in a Rocket.toml. - .address("127.0.0.1") - .port(PORT_NUMBER) - .unwrap(); + let rocket_config = rocket::Config::figment() + .merge(("port", PORT_NUMBER)) + .merge(("address", "127.0.0.1")); let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - let client = Client::new(rocket).expect("valid rocket instance"); + let client = Client::tracked(rocket).expect("valid rocket instance"); let _req = client.post("/enable").dispatch(); // Retire the current active node. diff --git a/fog/overseer/server/tests/retired_key_not_outstanding_idles_have_same_key.rs b/fog/overseer/server/tests/retired_key_not_outstanding_idles_have_same_key.rs index 43f2f4ef01..395b153bf4 100644 --- a/fog/overseer/server/tests/retired_key_not_outstanding_idles_have_same_key.rs +++ b/fog/overseer/server/tests/retired_key_not_outstanding_idles_have_same_key.rs @@ -10,7 +10,7 @@ use mc_transaction_core::{Block, BlockContents}; use mc_watcher::watcher_db::WatcherDB; use rand_core::SeedableRng; use rand_hc::Hc128Rng; -use rocket::local::Client; +use rocket::local::blocking::Client; use std::{convert::TryFrom, str::FromStr, time::Duration}; use tempdir::TempDir; use url::Url; @@ -114,13 +114,9 @@ fn active_key_is_retired_not_outstanding_new_key_is_set_node_activated(logger: L // Consider testing the CLI here instead. Initialize an OverSeerService // object... - let rocket_config: rocket::Config = - rocket::Config::build(rocket::config::Environment::Development) - // TODO: Make these either passed from CLI or in a Rocket.toml. - .address("127.0.0.1") - .port(PORT_NUMBER) - .unwrap(); - + let rocket_config = rocket::Config::figment() + .merge(("port", PORT_NUMBER)) + .merge(("address", "127.0.0.1")); let mut overseer_service = OverseerService::new( vec![client_listen_uri0, client_listen_uri1, client_listen_uri2], recovery_db.clone(), @@ -129,7 +125,7 @@ fn active_key_is_retired_not_outstanding_new_key_is_set_node_activated(logger: L overseer_service.start().unwrap(); let overseer_state = OverseerState { overseer_service }; let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - let client = Client::new(rocket).expect("valid rocket instance"); + let client = Client::tracked(rocket).expect("valid rocket instance"); let _req = client.post("/enable").dispatch(); // Retire the current active node. diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index cfe25a69ab..4a914b7bb6 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -21,3 +21,4 @@ mc-util-uri = { path = "../../../util/uri" } displaydoc = { version = "0.2", default-features = false } mockall = { version = "0.11.0", optional = true } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } diff --git a/fog/report/validation/src/ingest_report.rs b/fog/report/validation/src/ingest_report.rs index 4ea2da4aa9..d0e7510263 100644 --- a/fog/report/validation/src/ingest_report.rs +++ b/fog/report/validation/src/ingest_report.rs @@ -6,13 +6,14 @@ use mc_attest_core::{VerificationReport, VerifyError}; use mc_attest_verifier::{Error as VerifierError, Verifier}; use mc_crypto_keys::{KeyError, RistrettoPublic}; use mc_util_encodings::Error as EncodingError; +use serde::{Deserialize, Serialize}; /// A structure that can validate ingest enclave reports and measurements at /// runtime. /// /// This is expected to take the verification report and produce the /// ias-validated and decompressed RistrettoPublic key. -#[derive(Default, Clone, Debug)] +#[derive(Default, Clone, Debug, Serialize, Deserialize)] pub struct IngestReportVerifier { verifier: Verifier, } diff --git a/fog/report/validation/src/lib.rs b/fog/report/validation/src/lib.rs index ed163dd356..42269bea90 100644 --- a/fog/report/validation/src/lib.rs +++ b/fog/report/validation/src/lib.rs @@ -34,6 +34,7 @@ use mc_attest_verifier::Verifier; use mc_fog_report_types::ReportResponse; use mc_fog_sig::Verifier as FogSigVerifier; use mc_util_uri::{FogUri, UriParseError}; +use serde::{Deserialize, Serialize}; /// Represents a set of unvalidated responses from Fog report servers /// Key = Fog-url that was contacted, must match the string in user's public @@ -76,7 +77,7 @@ pub type FogReportResponses = BTreeMap; /// hints for transactions, without talking to the internet, and so is /// compatible with offline transactions to fog recipients. Only getting the /// FogReportResponses requires an online connection. -#[derive(Default, Clone, Debug)] +#[derive(Default, Clone, Debug, Serialize, Deserialize)] pub struct FogResolver { responses: FogReportResponses, verifier: IngestReportVerifier, diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index 260cdc687c..ca6e1ce554 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -15,7 +15,7 @@ mc-watcher-api = { path = "../../watcher/api" } mc-fog-kex-rng = { path = "../kex_rng" } # third-party -crc = { version = "2.1.0", default-features = false } +crc = { version = "3.0.0", default-features = false } displaydoc = { version = "0.2", default-features = false } prost = { version = "0.10", default-features = false, features = ["prost-derive"] } serde = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index 2ed2f52c81..c417dd0239 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -324,18 +324,18 @@ dependencies = [ [[package]] name = "crc" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" -version = "1.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" [[package]] name = "crypto-common" @@ -394,9 +394,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4" +checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" dependencies = [ "serde", "signature", @@ -500,9 +500,9 @@ checksum = "20d6a47d6e4b8559729f58287efa8e6f767e603c068fea7a5e4d9f1cebe2bebb" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" dependencies = [ "serde", ] @@ -1505,18 +1505,18 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "prost" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07b0857a71a8cb765763950499cae2413c3f9cede1133478c43600d9e146890" +checksum = "bc03e116981ff7d8da8e5c220e374587b98d294af7ba7dd7fda761158f00086f" dependencies = [ "bytes", "prost-derive", @@ -1657,9 +1657,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] @@ -1684,9 +1684,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -1773,9 +1773,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.67" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ "proc-macro2", "quote", @@ -2002,9 +2002,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] diff --git a/jenkins/build-pod.yaml b/jenkins/build-pod.yaml index 48e0e82114..e4a8432039 100644 --- a/jenkins/build-pod.yaml +++ b/jenkins/build-pod.yaml @@ -20,7 +20,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: rust-builder-default - image: gcr.io/mobilenode-211420/builder-install:1_26 + image: gcr.io/mobilenode-211420/builder-install:1_27 env: - name: PATH value: "/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index bd3c4d36a6..1f6ca3d339 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -21,8 +21,9 @@ displaydoc = "0.2" protobuf = "2.27.1" retry = "1.3" # TODO: Replace with https://github.com/awslabs/aws-sdk-rust when it is ready. -rusoto_core = { version = "0.42.0", features = ["rustls"], default_features = false } -rusoto_s3 = { version = "0.42.0", features = ["rustls"], default_features = false } +rusoto_core = { version = "0.48.0", features = ["rustls"], default_features = false } +rusoto_s3 = { version = "0.48.0", features = ["rustls"], default_features = false } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +tokio = { version = "1", features = ["rt-multi-thread"] } url = "2.2" diff --git a/ledger/distribution/src/main.rs b/ledger/distribution/src/main.rs index 551e84e327..9a2af2f77c 100644 --- a/ledger/distribution/src/main.rs +++ b/ledger/distribution/src/main.rs @@ -14,10 +14,12 @@ use mc_ledger_db::{Ledger, LedgerDB}; use mc_transaction_core::{BlockData, BlockIndex}; use mc_util_telemetry::{mark_span_as_active, start_block_span, tracer, Tracer}; use protobuf::Message; -use rusoto_core::{Region, RusotoError}; -use rusoto_s3::{PutObjectError, PutObjectRequest, S3Client, S3}; +use retry::{delay, retry, OperationResult}; +use rusoto_core::Region; +use rusoto_s3::{PutObjectRequest, S3Client, S3}; use serde::{Deserialize, Serialize}; use std::{fs, path::PathBuf}; +use tokio::runtime::Handle; /// Block writer. pub trait BlockHandler { @@ -105,38 +107,37 @@ impl S3BlockWriter { } fn write_bytes_to_s3(&self, path: &str, filename: &str, value: &[u8]) { - let result: Result< - retry::OperationResult<(), ()>, - retry::Error>>, - > = retry::retry( - retry::delay::Exponential::from_millis(10).map(retry::delay::jitter), + let runtime = Handle::current(); + let result = retry( + delay::Exponential::from_millis(10).map(delay::jitter), || { let req = PutObjectRequest { bucket: path.to_string(), - key: String::from(filename), + key: filename.to_string(), body: Some(value.to_vec().into()), acl: Some("public-read".to_string()), ..Default::default() }; - self.s3_client - .put_object(req) - .sync() - .map(|_| retry::OperationResult::Ok(())) - .map_err(|err: RusotoError| { - log::warn!( - self.logger, - "Failed writing {}: {:?}, retrying...", - filename, - err - ); - retry::OperationResult::Retry(err) - }) + runtime + .block_on(self.s3_client.put_object(req)) + .map_or_else( + |err| { + log::warn!( + self.logger, + "Failed writing {}: {:?}, retrying...", + filename, + err + ); + OperationResult::Retry(err) + }, + OperationResult::Ok, + ) }, ); // We should always succeed since retrying should never stop until that happens. - assert!(result.is_ok()); + result.expect("failed to write to S3"); } } @@ -240,11 +241,12 @@ impl BlockHandler for LocalBlockWriter { fs::create_dir_all(dir) .unwrap_or_else(|e| panic!("failed creating directory {:?}: {:?}", dir, e)); - fs::write(&dest, bytes).unwrap_or_else(|_| { + fs::write(&dest, bytes).unwrap_or_else(|err| { panic!( - "failed writing block #{} to {:?}", + "failed writing block #{} to {:?}: {}", block_data.block().index, - dest + dest, + err ) }); } @@ -280,10 +282,10 @@ impl BlockHandler for LocalBlockWriter { fs::create_dir_all(dir) .unwrap_or_else(|e| panic!("failed creating directory {:?}: {:?}", dir, e)); - fs::write(&dest, bytes).unwrap_or_else(|_| { + fs::write(&dest, bytes).unwrap_or_else(|err| { panic!( - "failed writing merged block #{}-{} to {:?}", - first_block_index, last_block_index, dest + "failed writing merged block #{}-{} to {:?}: {}", + first_block_index, last_block_index, dest, err, ) }); } @@ -300,6 +302,12 @@ fn main() { let _tracer = mc_util_telemetry::setup_default_tracer(env!("CARGO_PKG_NAME")) .expect("Failed setting telemetry tracer"); + let runtime = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .expect("tokio runtime"); + let _enter_guard = runtime.enter(); + // Get path to our state file. let state_file_path = config.state_file.clone().unwrap_or_else(|| { let mut home_dir = dirs::home_dir().unwrap_or_else(|| panic!("Unable to get home directory, please specify state file explicitly with --state-file")); diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index 77ab078ebd..5514129569 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["lib", "staticlib", "cdylib"] [dependencies] # External dependencies aes-gcm = "0.9.4" -crc = "2.1.0" +crc = "3.0.0" displaydoc = "0.2" generic-array = { version = "0.14", features = ["serde", "more_lengths"] } libc = "0.2" diff --git a/mint-auditor/src/counters.rs b/mint-auditor/src/counters.rs index aec137a32e..4140041b8f 100644 --- a/mint-auditor/src/counters.rs +++ b/mint-auditor/src/counters.rs @@ -6,7 +6,7 @@ use mc_util_metrics::{IntGauge, OpMetrics}; lazy_static::lazy_static! { /// Prometheus counters. - pub static ref OP_COUNTERS: OpMetrics = OpMetrics::new_and_registered("mc-mint-auditor"); + pub static ref OP_COUNTERS: OpMetrics = OpMetrics::new_and_registered("mc_mint_auditor"); /// Number of blocks synced. pub static ref NUM_BLOCKS_SYNCED: IntGauge = OP_COUNTERS.gauge("num_blocks_synced"); diff --git a/mint-auditor/tests/compile_proto.sh b/mint-auditor/tests/compile_proto.sh new file mode 100644 index 0000000000..9fba2678d1 --- /dev/null +++ b/mint-auditor/tests/compile_proto.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR=$(dirname "$0") +cd $SCRIPT_DIR + +MC_ROOT=$PWD/../.. +MC_API=$MC_ROOT/api/proto +MCD_API=$MC_ROOT/mobilecoind/api/proto +CONSENSUS_API=$MC_ROOT/consensus/api/proto +MINT_AUDITOR_API=$MC_ROOT/mint-auditor/api/proto + +pip3 install grpcio grpcio-tools + +python3 -m grpc_tools.protoc -I$MC_API --python_out=. $MC_API/external.proto +python3 -m grpc_tools.protoc -I$MC_API --python_out=. $MC_API/blockchain.proto +python3 -m grpc_tools.protoc -I$MCD_API -I$CONSENSUS_API -I$MC_API --python_out=. --grpc_python_out=. $MCD_API/mobilecoind_api.proto +python3 -m grpc_tools.protoc -I$MINT_AUDITOR_API --python_out=. --grpc_python_out=. $MINT_AUDITOR_API/mint_auditor.proto diff --git a/mint-auditor/tests/integration_test.py b/mint-auditor/tests/integration_test.py new file mode 100644 index 0000000000..2b49eb0a90 --- /dev/null +++ b/mint-auditor/tests/integration_test.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2022 The MobileCoin Foundation +# +# Integration test that tests the mint auditor tracks mints and burns. + +import argparse +import grpc +import logging +import subprocess +import sys +import time +from google.protobuf import empty_pb2 +from mint_auditor_pb2 import * +from mint_auditor_pb2_grpc import * +from mobilecoind_api_pb2 import * +from mobilecoind_api_pb2_grpc import * + + +logging.basicConfig(stream = sys.stdout, level = logging.INFO, format="%(levelname)s:%(module)s:%(lineno)s: %(message)s") + + +class MintAuditorClient: + def __init__(self, address, ssl=False): + if ssl: + credentials = grpc.ssl_channel_credentials() + self.channel = grpc.secure_channel(address, credentials) + else: + self.channel = grpc.insecure_channel(address) + self.stub = MintAuditorApiStub(self.channel) + + def get_last_block_audit_data(self): + return self.stub.GetLastBlockAuditData(empty_pb2.Empty()) + + def get_counters(self): + return self.stub.GetCounters(empty_pb2.Empty()) + + +class MobilecoindClient: + def __init__(self, address, ssl=False): + if ssl: + credentials = grpc.ssl_channel_credentials() + self.channel = grpc.secure_channel(address, credentials) + else: + self.channel = grpc.insecure_channel(address) + self.stub = MobilecoindAPIStub(self.channel) + + def new_random_monitor(self): + """Create a new monitor from a random mnemomic""" + new_menmonic = self.stub.GenerateMnemonic(empty_pb2.Empty()).mnemonic + account_key = self.stub.GetAccountKeyFromMnemonic( + GetAccountKeyFromMnemonicRequest(mnemonic=new_menmonic) + ).account_key + monitor_id = self.stub.AddMonitor( + AddMonitorRequest( + account_key=account_key, + num_subaddresses=1, + ) + ).monitor_id + return monitor_id + + def remove_monitor(self, monitor_id): + self.stub.RemoveMonitor(RemoveMonitorRequest(monitor_id=monitor_id)) + + def get_b58_public_address(self, monitor_id): + return self.stub.GetPublicAddress( + GetPublicAddressRequest(monitor_id=monitor_id) + ).b58_code + + def get_balance(self, monitor_id, token_id, subaddress_index=0): + return self.stub.GetBalance( + GetBalanceRequest( + monitor_id=monitor_id, + subaddress_index=subaddress_index, + token_id=token_id, + ) + ).balance + + def get_network_block_index(self): + return self.stub.GetNetworkStatus( + empty_pb2.Empty() + ).network_highest_block_index + + def get_utxos(self, monitor_id, token_id, subaddress_index=0): + return self.stub.GetUnspentTxOutList( + GetUnspentTxOutListRequest( + monitor_id=monitor_id, + subaddress_index=subaddress_index, + token_id=token_id, + ) + ).output_list + + def generate_burn_redemption_tx( + self, + monitor_id, + input_list, + burn_amount, + fee, + token_id, + change_subaddress=0, + tombstone=None, + redemption_memo=None, + enable_destination_memo=False, + ): + if tombstone is None: + tombstone = self.get_network_block_index() + 10 + + request = GenerateBurnRedemptionTxRequest( + sender_monitor_id=monitor_id, + change_subaddress=change_subaddress, + input_list=input_list, + burn_amount=burn_amount, + fee=fee, + tombstone=tombstone, + token_id=token_id, + redemption_memo=redemption_memo, + enable_destination_memo=enable_destination_memo, + ) + return self.stub.GenerateBurnRedemptionTx(request).tx_proposal + + def submit_tx(self, tx_proposal): + return self.stub.SubmitTx( + SubmitTxRequest( + tx_proposal=tx_proposal, + ) + ) + + def wait_for_monitor_to_sync(self, monitor_id, poll_interval=0.1): + while True: + network_block_index = self.get_network_block_index() + status = self.stub.GetMonitorStatus( + GetMonitorStatusRequest( + monitor_id=monitor_id + ) + ).status + if status.next_block >= network_block_index: + break + time.sleep(poll_interval) + + +class MintAuditorTest: + def __init__(self, args): + self.args = args + self.mobilecoind_client = MobilecoindClient(args.mobilecoind_addr) + self.mint_auditor_client = MintAuditorClient(args.mint_auditor_addr) + + def run(self): + monitor_id = self.mobilecoind_client.new_random_monitor() + + try: + b58_addr = self.mobilecoind_client.get_b58_public_address(monitor_id) + logging.info(f"Minting to {b58_addr}") + token_id = 1 + mint_amount = 10000 + + # Get the network block height and wait for the mint auditor to catch up + response = self.wait_for_mint_auditor_to_sync() + previous_minted_amount = dict(response.block_audit_data.balance_map).get(token_id) or 0 + + # Mint tokens that go into the new wallet we generated + logging.info(f"Minting {mint_amount} tokens of token_id {token_id}") + output = subprocess.check_output(" ".join([ + self.args.mint_client_bin, + "generate-and-submit-mint-tx", + f"--node {self.args.node_url}", + f"--signing-key {self.args.mint_signing_key}", + f"--recipient {b58_addr}", + f"--token-id {token_id}", + f"--amount {mint_amount}", + ]), shell=True) + logging.info(f"Mint client output: {output}") + + # Give the network time to process the mint and then for mobilecoind and the mint auditor to catch up + self.wait_for_balance(monitor_id, token_id, mint_amount) + + response = self.wait_for_mint_auditor_to_sync() + + current_minted_amount = dict(response.block_audit_data.balance_map).get(token_id) + assert current_minted_amount == previous_minted_amount + mint_amount, (current_minted_amount, previous_minted_amount, mint_amount) + + # Burn 300 tokens + burn_amount = 300 + fee_amount = 1024 + utxos = self.mobilecoind_client.get_utxos(monitor_id, token_id) + tx_proposal = self.mobilecoind_client.generate_burn_redemption_tx( + monitor_id, + utxos, + burn_amount, + fee_amount, + token_id, + ) + logging.info("Submitting burn transaction") + submit_response = self.mobilecoind_client.submit_tx(tx_proposal) + + # Wait for the transaction to go through + logging.info("Verifying burn transaction") + expected_balance = mint_amount - burn_amount - fee_amount + self.wait_for_balance(monitor_id, token_id, expected_balance) + + response = self.wait_for_mint_auditor_to_sync() + + previous_minted_amount = current_minted_amount + current_minted_amount = dict(response.block_audit_data.balance_map).get(token_id) + assert current_minted_amount == previous_minted_amount - burn_amount, (current_minted_amount, previous_minted_amount, burn_amount) + + # Sanity check the counters + logging.info("Checking counters") + counters = self.mint_auditor_client.get_counters() + assert counters.num_blocks_synced == response.block_index + 1, (counters.num_blocks_synced, response.block_index) + assert counters.num_burns_exceeding_balance == 0, counters.num_burns_exceeding_balance + assert counters.num_mint_txs_without_matching_mint_config == 0, counters.num_mint_txs_without_matching_mint_config + + logging.info("All tests passed") + + finally: + self.mobilecoind_client.remove_monitor(monitor_id) + + def wait_for_balance(self, monitor_id, token_id, expected_balance): + """Poll mobilecoind until it has the expected balance""" + + for _ in range(20): + self.mobilecoind_client.wait_for_monitor_to_sync(monitor_id) + + # Balance should show up in mobilecoild + balance = self.mobilecoind_client.get_balance(monitor_id, token_id) + if balance == expected_balance: + break + + time.sleep(1) + + assert balance == expected_balance, (balance, expected_balance) + + + + def wait_for_mint_auditor_to_sync(self): + """Wait for the mint auditor to sync to the network block height. + Return the last block audit data""" + network_block_index = self.mobilecoind_client.get_network_block_index() + for _ in range(20): + response = self.mint_auditor_client.get_last_block_audit_data() + if response.block_index == network_block_index: + break + + time.sleep(1) + + assert response.block_index == network_block_index, f'block index mismatch: {response.block_index} != {network_block_index}' + logging.info(f"Last block audit data: {response}") + return response + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("--mobilecoind-addr", + type=str, + help="mobilecoind host:port") + parser.add_argument("--mint-auditor-addr", + type=str, + help="mint auditor host:port") + parser.add_argument("--mint-client-bin", + type=str, + help="path to the mc-consensus-mint-client binary") + parser.add_argument("--node-url", + type=str, + help="node to issue a mint transaction to") + parser.add_argument("--mint-signing-key", + type=str, + help="path to the mint signing private key file") + + args = parser.parse_args() + MintAuditorTest(args).run() diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index fccb79389b..c396ada83d 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -18,8 +18,7 @@ clap = { version = "3.1", features = ["derive", "env"] } grpcio = "0.10.2" hex = "0.4" protobuf = "2.27.1" -rocket = { version = "0.4.10", default-features = false } -rocket_contrib = { version = "0.4.10", default-features = false, features = ["json"] } +rocket = { version = "0.5.0-rc.1", features = ["json"] } serde = "1.0" serde_derive = "1.0" diff --git a/mobilecoind-json/src/bin/main.rs b/mobilecoind-json/src/bin/main.rs index 7ac1126e20..8f3b285dd2 100644 --- a/mobilecoind-json/src/bin/main.rs +++ b/mobilecoind-json/src/bin/main.rs @@ -13,8 +13,7 @@ use mc_mobilecoind_api::{mobilecoind_api_grpc::MobilecoindApiClient, Mobilecoind use mc_mobilecoind_json::data_types::*; use mc_util_grpc::ConnectionUriGrpcioChannel; use protobuf::RepeatedField; -use rocket::{delete, get, post, routes}; -use rocket_contrib::json::Json; +use rocket::{delete, get, post, routes, serde::json::Json}; use std::{convert::TryFrom, sync::Arc}; /// Command line config, set with defaults that will work with @@ -47,7 +46,7 @@ struct State { /// Set the password for the mobilecoind-db #[post("/set-password", format = "json", data = "")] fn set_password( - state: rocket::State, + state: &rocket::State, password: Json, ) -> Result, String> { let mut req = mc_mobilecoind_api::SetDbPasswordRequest::new(); @@ -65,7 +64,7 @@ fn set_password( /// Unlock a previously-encrypted mobilecoind-db #[post("/unlock-db", format = "json", data = "")] fn unlock_db( - state: rocket::State, + state: &rocket::State, password: Json, ) -> Result, String> { let mut req = mc_mobilecoind_api::UnlockDbRequest::new(); @@ -82,7 +81,7 @@ fn unlock_db( /// Requests a new root entropy from mobilecoind #[post("/entropy")] -fn entropy(state: rocket::State) -> Result, String> { +fn entropy(state: &rocket::State) -> Result, String> { let resp = state .mobilecoind_api_client .generate_root_entropy(&mc_mobilecoind_api::Empty::new()) @@ -92,7 +91,7 @@ fn entropy(state: rocket::State) -> Result, #[get("/entropy/")] fn account_key_from_root_entropy( - state: rocket::State, + state: &rocket::State, root_entropy: String, ) -> Result, String> { let entropy = @@ -111,7 +110,7 @@ fn account_key_from_root_entropy( /// Requests a new mnemonic from mobilecoind #[post("/mnemonic")] -fn mnemonic(state: rocket::State) -> Result, String> { +fn mnemonic(state: &rocket::State) -> Result, String> { let resp = state .mobilecoind_api_client .generate_mnemonic(&mc_mobilecoind_api::Empty::new()) @@ -121,7 +120,7 @@ fn mnemonic(state: rocket::State) -> Result, S #[post("/account-key-from-mnemonic", format = "json", data = "")] fn account_key_from_mnemonic( - state: rocket::State, + state: &rocket::State, mnemonic: Json, ) -> Result, String> { let mut req = mc_mobilecoind_api::GetAccountKeyFromMnemonicRequest::new(); @@ -139,7 +138,7 @@ fn account_key_from_mnemonic( /// above. #[post("/monitors", format = "json", data = "")] fn add_monitor( - state: rocket::State, + state: &rocket::State, monitor: Json, ) -> Result, String> { let mut account_key = mc_mobilecoind_api::external::AccountKey::new(); @@ -172,7 +171,7 @@ fn add_monitor( /// Remove a monitor #[delete("/monitors/")] -fn remove_monitor(state: rocket::State, monitor_hex: String) -> Result<(), String> { +fn remove_monitor(state: &rocket::State, monitor_hex: String) -> Result<(), String> { let monitor_id = hex::decode(monitor_hex).map_err(|err| format!("Failed to decode monitor hex: {}", err))?; @@ -189,7 +188,7 @@ fn remove_monitor(state: rocket::State, monitor_hex: String) -> Result<() /// Gets a list of existing monitors #[get("/monitors")] -fn monitors(state: rocket::State) -> Result, String> { +fn monitors(state: &rocket::State) -> Result, String> { let resp = state .mobilecoind_api_client .get_monitor_list(&mc_mobilecoind_api::Empty::new()) @@ -200,7 +199,7 @@ fn monitors(state: rocket::State) -> Result /// Get the current status of a created monitor #[get("/monitors/")] fn monitor_status( - state: rocket::State, + state: &rocket::State, monitor_hex: String, ) -> Result, String> { let monitor_id = @@ -220,7 +219,7 @@ fn monitor_status( /// Balance check using a created monitor and subaddress index #[get("/monitors//subaddresses//balance")] fn balance( - state: rocket::State, + state: &rocket::State, monitor_hex: String, subaddress_index: u64, ) -> Result, String> { @@ -241,7 +240,7 @@ fn balance( #[get("/monitors//subaddresses//utxos")] fn utxos( - state: rocket::State, + state: &rocket::State, monitor_hex: String, subaddress_index: u64, ) -> Result, String> { @@ -263,7 +262,7 @@ fn utxos( /// Balance check using a created monitor and subaddress index #[get("/monitors//subaddresses//public-address")] fn public_address( - state: rocket::State, + state: &rocket::State, monitor_hex: String, subaddress_index: u64, ) -> Result, String> { @@ -286,7 +285,7 @@ fn public_address( /// Generates a request code with an optional value and memo #[post("/codes/request", format = "json", data = "")] fn create_request_code( - state: rocket::State, + state: &rocket::State, request: Json, ) -> Result, String> { let receiver = mc_mobilecoind_api::external::PublicAddress::try_from(&request.receiver) @@ -317,7 +316,7 @@ fn create_request_code( /// Retrieves the data in a request b58_code #[get("/codes/request/")] fn parse_request_code( - state: rocket::State, + state: &rocket::State, b58_code: String, ) -> Result, String> { let mut req = mc_mobilecoind_api::ParseRequestCodeRequest::new(); @@ -336,7 +335,7 @@ fn parse_request_code( /// Generates an address code #[post("/codes/address", format = "json", data = "")] fn create_address_code( - state: rocket::State, + state: &rocket::State, request: Json, ) -> Result, String> { let receiver = mc_mobilecoind_api::external::PublicAddress::try_from(&request.receiver) @@ -357,7 +356,7 @@ fn create_address_code( /// Retrieves the data in an address b58_code #[get("/codes/address/")] fn parse_address_code( - state: rocket::State, + state: &rocket::State, b58_code: String, ) -> Result, String> { let mut req = mc_mobilecoind_api::ParseAddressCodeRequest::new(); @@ -379,7 +378,7 @@ fn parse_address_code( data = "" )] fn build_and_submit( - state: rocket::State, + state: &rocket::State, monitor_hex: String, subaddress_index: u64, transfer: Json, @@ -440,7 +439,7 @@ fn build_and_submit( data = "" )] fn pay_address_code( - state: rocket::State, + state: &rocket::State, monitor_hex: String, subaddress_index: u64, transfer: Json, @@ -496,7 +495,7 @@ fn pay_address_code( data = "" )] fn generate_request_code_transaction( - state: rocket::State, + state: &rocket::State, monitor_hex: String, subaddress_index: u64, request: Json, @@ -544,7 +543,7 @@ fn generate_request_code_transaction( /// Submit a prepared TxProposal #[post("/submit-tx", format = "json", data = "")] fn submit_tx( - state: rocket::State, + state: &rocket::State, proposal: Json, ) -> Result, String> { // Send the payment request @@ -566,7 +565,7 @@ fn submit_tx( /// Checks the status of a transfer given a key image and tombstone block #[post("/tx/status-as-sender", format = "json", data = "")] fn check_transfer_status( - state: rocket::State, + state: &rocket::State, submit_response: Json, ) -> Result, String> { let resp = state @@ -593,7 +592,7 @@ fn check_transfer_status( data = "" )] fn check_receiver_transfer_status( - state: rocket::State, + state: &rocket::State, monitor_hex: String, receipt: Json, ) -> Result, String> { @@ -625,7 +624,7 @@ fn check_receiver_transfer_status( /// Gets information about the entire ledger #[get("/ledger/local")] -fn ledger_info(state: rocket::State) -> Result, String> { +fn ledger_info(state: &rocket::State) -> Result, String> { let resp = state .mobilecoind_api_client .get_ledger_info(&mc_mobilecoind_api::Empty::new()) @@ -637,7 +636,7 @@ fn ledger_info(state: rocket::State) -> Result/header")] fn block_info( - state: rocket::State, + state: &rocket::State, block_num: u64, ) -> Result, String> { let mut req = mc_mobilecoind_api::GetBlockInfoRequest::new(); @@ -654,7 +653,7 @@ fn block_info( /// Retrieves the details for a given block. #[get("/ledger/blocks/")] fn block_details( - state: rocket::State, + state: &rocket::State, block_num: u64, ) -> Result, String> { let mut req = mc_mobilecoind_api::GetBlockRequest::new(); @@ -670,7 +669,7 @@ fn block_details( /// Retreives processed block information. #[get("/monitors//processed-block/")] fn processed_block( - state: rocket::State, + state: &rocket::State, monitor_hex: String, block_num: u64, ) -> Result, String> { @@ -692,7 +691,7 @@ fn processed_block( /// Get the block index of a given tx out, identified by its public key. #[get("/tx-out//block-index")] fn tx_out_get_block_index_by_public_key( - state: rocket::State, + state: &rocket::State, public_key_hex: String, ) -> Result, String> { let tx_out_public_key = hex::decode(public_key_hex) @@ -715,7 +714,7 @@ fn tx_out_get_block_index_by_public_key( #[post("/tx-out/proof-of-membership", format = "json", data = "")] /// Get a proof of membership for each queried TxOut. fn get_proof_of_membership( - state: rocket::State, + state: &rocket::State, request: Json, ) -> Result, String> { // Requested TxOuts. @@ -757,7 +756,7 @@ fn get_proof_of_membership( #[post("/tx-out/mixin", format = "json", data = "")] /// Get a list of TxOuts for use as mixins. fn get_mixins( - state: rocket::State, + state: &rocket::State, request: Json, ) -> Result, String> { let num_mixins = request.num_mixins; @@ -796,7 +795,8 @@ fn get_mixins( Ok(Json(response)) } -fn main() { +#[rocket::main] +async fn main() -> Result<(), rocket::Error> { mc_common::setup_panic_handler(); let _sentry_guard = mc_common::sentry::init(); @@ -820,12 +820,11 @@ fn main() { let mobilecoind_api_client = MobilecoindApiClient::new(ch); - let rocket_config = rocket::Config::build(rocket::config::Environment::Production) - .address(&config.listen_host) - .port(config.listen_port) - .unwrap(); + let figment = rocket::Config::figment() + .merge(("port", config.listen_port)) + .merge(("address", config.listen_host.clone())); - rocket::custom(rocket_config) + rocket::custom(figment) .mount( "/", routes![ @@ -864,5 +863,6 @@ fn main() { .manage(State { mobilecoind_api_client, }) - .launch(); + .launch() + .await } diff --git a/mobilecoind-json/tests/integration_test.py b/mobilecoind-json/tests/integration_test.py new file mode 100644 index 0000000000..c1901f5256 --- /dev/null +++ b/mobilecoind-json/tests/integration_test.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2022 The MobileCoin Foundation +# +# Integration test that uses mobilecoind-json to submit a transaction and check balance. + +import argparse +import glob +import json +import logging +import os +import sys +import time +import urllib.request + + +logging.basicConfig(stream = sys.stdout, level = logging.INFO, format="%(levelname)s:%(module)s:%(lineno)s: %(message)s") + + +class MobilecoindJsonClient: + def __init__(self, base_url): + if not base_url.endswith("/"): + base_url += "/" + self.base_url = base_url + + def request(self, url, data=None): + req = urllib.request.Request(self.base_url + url) + + if data: + data = json.dumps(data) + data_bytes = data.encode("utf-8") + + req.add_header("Content-Type", "application/json; charset=utf-8") + req.add_header("Content-Length", len(data_bytes)) + response = urllib.request.urlopen(req, data_bytes) + else: + response = urllib.request.urlopen(req) + + return json.loads(response.read()) + + def get_balance(self, monitor_id, subaddress_index=0): + response = self.request(f"monitors/{monitor_id}/subaddresses/{subaddress_index}/balance") + if "balance" not in response: + raise Exception(f"Invalid response: {response}") + return int(response["balance"]) + + def create_monitor(self, account_key, first_subaddress_index=0, num_subaddresses=1): + return self.request(f"monitors", { + "account_key": account_key, + "first_subaddress": first_subaddress_index, + "num_subaddresses": num_subaddresses, + }) + + def get_monitor(self, monitor_id): + return self.request(f"monitors/{monitor_id}") + + def get_ledger_local(self): + return self.request(f"ledger/local") + + def account_key_from_mnemonic(self, mnemonic): + return self.request("account-key-from-mnemonic", {"mnemonic": mnemonic}) + + def get_public_address(self, monitor_id, subaddress_index=0): + return self.request(f"monitors/{monitor_id}/subaddresses/{subaddress_index}/public-address") + + def pay_address_code(self, from_monitor_id, from_subaddress_index, to_b58_address, value): + return self.request(f"monitors/{from_monitor_id}/subaddresses/{from_subaddress_index}/pay-address-code", { + "receiver_b58_address_code": to_b58_address, + "value": str(value), + }) + + def tx_status_as_sender(self, tx_info): + return self.request(f"tx/status-as-sender", tx_info) + + def tx_status_as_receiver(self, monitor_id, receipt): + return self.request(f"monitors/{monitor_id}/tx-status-as-receiver", receipt) + + def get_utxos(self, monitor_id, subaddress_index=0): + return self.request(f"monitors/{monitor_id}/subaddresses/{subaddress_index}/utxos")["output_list"] + + def wait_for_monitor_to_sync(self, monitor_id, poll_interval=0.1): + while True: + local_ledger = self.get_ledger_local() + monitor = self.get_monitor(monitor_id) + if int(monitor["next_block"]) >= int(local_ledger["block_count"]): + break + time.sleep(poll_interval) + + +def load_keys(keys_dir): + """Load all keys from the keys_dir directory""" + + # When Comparing filenames, make shorter file names compare less than longer filenames, + # using this key function + def filename_key(filename): + return (len(filename), filename); + + return [ + json.load(open(f)) for f in + sorted(glob.glob(os.path.join(keys_dir, "*.json")), key=filename_key) + ] + + +def run_test(mobilecoind_json_url, keys_dir, max_seconds): + logging.info(f"mobilecoind-json integration test starting with url={mobilecoind_json_url} keys_dir={keys_dir} max_seconds={max_seconds}") + keys = load_keys(keys_dir) + if not keys: + raise Exception(f"No keys found in directory: {keys_dir}") + logging.info(f"Loaded {len(keys)} keys") + + client = MobilecoindJsonClient(mobilecoind_json_url) + + # Add two monitors and wait for them to sync + monitor_ids = [] + for i in range(2): + account_key = client.account_key_from_mnemonic(keys[i]["mnemonic"]) + monitor = client.create_monitor(account_key) + logging.info(f"{i}: Monitor created: {monitor}, waiting to sync...") + monitor_id = monitor["monitor_id"] + client.wait_for_monitor_to_sync(monitor_id) + balance = client.get_balance(monitor_id) + logging.info(f"{i}: Monitor synced: balance={balance}") + monitor_ids.append(monitor_id) + + # Run tests + test_pay_address_code(client, monitor_ids) + test_utxos(client, monitor_ids[1]) + +def test_pay_address_code(client, monitor_ids): + # Get the balance of both monitors and then transact from one to the other using the pay_address_code endpoint + balance0 = client.get_balance(monitor_ids[0]) + balance1 = client.get_balance(monitor_ids[1]) + + amount = 1 + addr1 = client.get_public_address(monitor_ids[1])["b58_address_code"] + tx_info = client.pay_address_code(monitor_ids[0], 0, addr1, amount) + logging.info(f"Tx submitted: {tx_info}") + + # Wait up to 30 seconds for tx to happen + for _ in range(30): + new_balance1 = client.get_balance(monitor_ids[1]) + if new_balance1 != balance1: + break + time.sleep(1) + + assert new_balance1 == balance1 + amount, f"Balance mismatch: {new_balance1} != {balance1} + {amount}" + logging.info("Balance check passed") + + # Check the status as the sender + response = client.tx_status_as_sender(tx_info) + logging.info(f"tx_status_as_sender: {response}") + if response["status"] != "verified": + raise Exception(f"Failed tx_status_as_sender check: {response}") + + # Check the status as the receiver + response = client.tx_status_as_receiver(monitor_ids[1], tx_info["receiver_tx_receipt_list"][0]) + logging.info(f"tx_status_as_receiver: {response}") + if response["status"] != "verified": + raise Exception(f"Failed tx_status_as_receiver check: {response}") + + +def test_utxos(client, monitor_id): + # Confirm the balance matches the list of utos + balance = client.get_balance(monitor_id) + utxos = client.get_utxos(monitor_id) + + utxo_balance = sum(int(utxo["value"]) for utxo in utxos) + logging.info(f"balance is {balance}, utxo_balance is {utxo_balance}") + assert balance == utxo_balance + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("--mobilecoind-json-url", + default="http://localhost:9090/", + type=str, + help="mobilecoind-json host") + parser.add_argument("--key-dir", + type=str, + help="Path to directory of account_keys", + required=True) + parser.add_argument("--max-seconds", + type=int, + default=40, + help="Number of seconds to wait for a tx to clean") + args = parser.parse_args() + run_test( + args.mobilecoind_json_url, + args.key_dir, + args.max_seconds, + ) + diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index 4ca7da4c90..aff196978b 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -80,4 +80,4 @@ tempdir = "0.3" [build-dependencies] # Resolves a build failure for the x86_64-apple-darwin target by overriding the grpcio libz dep, which is pinned to v1.0.25 -libz-sys = "1.1.5" +libz-sys = "1.1.6" diff --git a/mobilecoind/src/utxo_store.rs b/mobilecoind/src/utxo_store.rs index 1f25059fc6..54194e64dc 100644 --- a/mobilecoind/src/utxo_store.rs +++ b/mobilecoind/src/utxo_store.rs @@ -69,13 +69,13 @@ impl From<&UnspentTxOut> for UtxoId { fn from(src: &UnspentTxOut) -> Self { // The key image uniquely identifies a TxOut, which uniquely identifies an // UnspentTxOut. - Self::from(&src.key_image) + (&src.key_image).into() } } impl From<&KeyImage> for UtxoId { fn from(src: &KeyImage) -> Self { - Self::from(src.as_bytes()) + src.as_bytes().into() } } diff --git a/mobilecoind/strategies/drain-accounts.py b/mobilecoind/strategies/drain-accounts.py index e0c7a8debd..8330cb413a 100644 --- a/mobilecoind/strategies/drain-accounts.py +++ b/mobilecoind/strategies/drain-accounts.py @@ -54,7 +54,7 @@ def parse_args() -> argparse.ArgumentParser: parser.add_argument("--max-seconds", type=int, default=40, - help="Number of seconds to wait for a tx to clearn") + help="Number of seconds to wait for a tx to clear") parser.add_argument("--fee", type=int, default=20, diff --git a/mobilecoind/strategies/test_client.py b/mobilecoind/strategies/test_client.py index 4c1b0c6ce7..22ca85f174 100755 --- a/mobilecoind/strategies/test_client.py +++ b/mobilecoind/strategies/test_client.py @@ -39,7 +39,7 @@ def parse_args() -> argparse.ArgumentParser: parser.add_argument("--max-seconds", type=int, default=40, - help="Number of seconds to wait for a tx to clearn") + help="Number of seconds to wait for a tx to clear") return parser.parse_args() diff --git a/sgx/types/src/types.rs b/sgx/types/src/types.rs index 01c6a20cdd..7761af550c 100644 --- a/sgx/types/src/types.rs +++ b/sgx/types/src/types.rs @@ -27,7 +27,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use core::default::Default; -use core::mem::zeroed; use error::*; use marker::ContiguousMemory; @@ -1138,23 +1137,3 @@ pub const SL_DEFAULT_FALLBACK_RETRIES: ::uint32_t = 20000; pub const SL_DEFAULT_SLEEP_RETRIES: ::uint32_t = 20000; pub const SL_DEFUALT_MAX_TASKS_QWORDS: ::uint32_t = 1; pub const SL_MAX_TASKS_MAX_QWORDS: ::uint32_t = 8; - -pub const _SGX_USWITCHLESS_WORKER_EVENT_NUM: ::size_t = 4; - -pub struct sgx_uswitchless_config_t { - pub switchless_calls_pool_size_qwords: ::uint32_t, - pub num_uworkers: ::uint32_t, - pub num_tworkers: ::uint32_t, - pub retries_before_fallback: ::uint32_t, - pub retries_before_sleep: ::uint32_t, - pub callback_func: [sgx_uswitchless_worker_callback_t; _SGX_USWITCHLESS_WORKER_EVENT_NUM], -} - -impl Default for sgx_uswitchless_config_t { - fn default() -> sgx_uswitchless_config_t { - let mut config: sgx_uswitchless_config_t = unsafe{ zeroed() }; - config.num_uworkers = 1; - config.num_tworkers = 1; - config - } -} diff --git a/tools/local-network/local_network.py b/tools/local-network/local_network.py index 183df7e372..00465c802b 100755 --- a/tools/local-network/local_network.py +++ b/tools/local-network/local_network.py @@ -31,7 +31,7 @@ MOB_RELEASE = os.getenv('MOB_RELEASE', '1') CARGO_FLAGS = '--release' TARGET_DIR = 'target/release' -WORK_DIR = '/tmp/mc-local-network' +WORK_DIR = os.path.join(PROJECT_DIR, TARGET_DIR, 'mc-local-network') MINTING_KEYS_DIR = os.path.join(WORK_DIR, 'minting-keys') CLI_PORT = 31337 @@ -461,7 +461,7 @@ def build_binaries(self): ) subprocess.run( - f'cd {PROJECT_DIR} && CONSENSUS_ENCLAVE_PRIVKEY="{enclave_pem}" cargo build -p mc-consensus-service -p mc-ledger-distribution -p mc-admin-http-gateway -p mc-util-grpc-admin-tool -p mc-mobilecoind -p mc-crypto-x509-test-vectors -p mc-consensus-mint-client -p mc-util-seeded-ed25519-key-gen {CARGO_FLAGS}', + f'cd {PROJECT_DIR} && CONSENSUS_ENCLAVE_PRIVKEY="{enclave_pem}" cargo build -p mc-consensus-service -p mc-ledger-distribution -p mc-admin-http-gateway -p mc-util-grpc-admin-tool -p mc-mint-auditor -p mc-mobilecoind -p mc-crypto-x509-test-vectors -p mc-consensus-mint-client -p mc-util-seeded-ed25519-key-gen {CARGO_FLAGS}', shell=True, check=True, ) diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index a4c0e84847..fa3aba171b 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] # External dependencies aes = { version = "0.7.5", default-features = false, features = ["ctr"] } -crc = { version = "2.1.0", default-features = false } +crc = { version = "3.0.0", default-features = false } displaydoc = { version = "0.2", default-features = false } generic-array = { version = "0.14", features = ["serde", "more_lengths"] } hex_fmt = "0.3" diff --git a/transaction/core/src/mint/validation/config.rs b/transaction/core/src/mint/validation/config.rs index e610c7c2c0..1eb459c81d 100644 --- a/transaction/core/src/mint/validation/config.rs +++ b/transaction/core/src/mint/validation/config.rs @@ -23,13 +23,16 @@ use mc_crypto_multisig::SignerSet; /// # Arguments /// * `tx` - A pending transaction. /// * `current_block_index` - The index of the current block that is being -/// built. +/// built. This is used to enforce the tombstone block limit, and is optional. +/// It is optional because we want to be able to validate MintConfigTxs that +/// are already in the ledger (e.g. when we are validating new MintTxs and +/// matching them against existing MintConfigTxs). /// * `block_version` - The version of the block that is being built. /// * `governors` - The set of signers that are allowed to sign MintConfigTx /// transactions. pub fn validate_mint_config_tx( tx: &MintConfigTx, - current_block_index: u64, + current_block_index: Option, block_version: BlockVersion, governors: &SignerSet, ) -> Result<(), Error> { @@ -42,7 +45,9 @@ pub fn validate_mint_config_tx( validate_nonce(&tx.prefix.nonce)?; - validate_tombstone(current_block_index, tx.prefix.tombstone_block)?; + if let Some(current_block_index) = current_block_index { + validate_tombstone(current_block_index, tx.prefix.tombstone_block)?; + } validate_signature(tx, governors)?; diff --git a/transaction/core/test-utils/src/mint.rs b/transaction/core/test-utils/src/mint.rs index 9197e205a3..e18b6db149 100644 --- a/transaction/core/test-utils/src/mint.rs +++ b/transaction/core/test-utils/src/mint.rs @@ -64,7 +64,7 @@ pub fn create_mint_config_tx_and_signers( token_id: *token_id, configs: configs.clone(), nonce, - tombstone_block: 10, + tombstone_block: 2, total_mint_limit: configs[0].mint_limit + configs[1].mint_limit + configs[2].mint_limit, }; diff --git a/transaction/std/src/memo/macros.rs b/transaction/std/src/memo/macros.rs index 7797bce041..7ee494d3fb 100644 --- a/transaction/std/src/memo/macros.rs +++ b/transaction/std/src/memo/macros.rs @@ -43,21 +43,21 @@ macro_rules! impl_memo_enum { } // Try to match memo type from src.get_memo_type - impl TryFrom<&crate::MemoPayload> for $enum_name { - type Error = crate::MemoDecodingError; - fn try_from(src: &crate::MemoPayload) -> Result { + impl TryFrom<&$crate::MemoPayload> for $enum_name { + type Error = $crate::MemoDecodingError; + fn try_from(src: &$crate::MemoPayload) -> Result { let memo_type_bytes: [u8; 2] = *src.get_memo_type(); match memo_type_bytes { - $(<$memo_type as crate::RegisteredMemoType>::MEMO_TYPE_BYTES => Ok($enum_name::$memo_name(<$memo_type>::from(src.get_memo_data()))),)+ - _ => Err(crate::MemoDecodingError::UnknownMemoType(memo_type_bytes)) + $(<$memo_type as $crate::RegisteredMemoType>::MEMO_TYPE_BYTES => Ok($enum_name::$memo_name(<$memo_type>::from(src.get_memo_data()))),)+ + _ => Err($crate::MemoDecodingError::UnknownMemoType(memo_type_bytes)) } } } // Implement From<$enum_name> for MemoPayload - impl From<$enum_name> for crate::MemoPayload { - fn from(src: $enum_name) -> crate::MemoPayload { + impl From<$enum_name> for $crate::MemoPayload { + fn from(src: $enum_name) -> $crate::MemoPayload { match src { $($enum_name::$memo_name(memo) => memo.into(),)+ } @@ -75,10 +75,10 @@ macro_rules! impl_memo_enum { #[macro_export] macro_rules! impl_memo_type_conversions { ($memo_type: ty) => { - impl From<$memo_type> for crate::MemoPayload { - fn from(src: $memo_type) -> crate::MemoPayload { - crate::MemoPayload::new( - <$memo_type as crate::RegisteredMemoType>::MEMO_TYPE_BYTES, + impl From<$memo_type> for $crate::MemoPayload { + fn from(src: $memo_type) -> $crate::MemoPayload { + $crate::MemoPayload::new( + <$memo_type as $crate::RegisteredMemoType>::MEMO_TYPE_BYTES, src.into(), ) } diff --git a/util/grpc/src/grpcio_extensions.rs b/util/grpc/src/grpcio_extensions.rs index 8f7bef71f3..58f2a62d5b 100644 --- a/util/grpc/src/grpcio_extensions.rs +++ b/util/grpc/src/grpcio_extensions.rs @@ -18,7 +18,7 @@ pub trait ConnectionUriGrpcioChannel { fn default_channel_builder(env: Arc) -> ChannelBuilder { ChannelBuilder::new(env) .keepalive_permit_without_calls(true) - .keepalive_time(Duration::from_secs(1)) + .keepalive_time(Duration::from_secs(10)) .keepalive_timeout(Duration::from_secs(20)) .max_reconnect_backoff(Duration::from_millis(2000)) .initial_reconnect_backoff(Duration::from_millis(1000)) @@ -61,6 +61,19 @@ pub trait ConnectionUriGrpcioServer { /// hot-reloading certificates when TLS is used. #[must_use] fn bind_using_uri(self, uri: &impl ConnectionUri, logger: Logger) -> Self; + + /// Create the default channel settings for server + fn default_channel_builder(env: Arc) -> ChannelBuilder { + ChannelBuilder::new(env) + .keepalive_permit_without_calls(true) + .keepalive_time(Duration::from_secs(10)) + .keepalive_timeout(Duration::from_secs(20)) + .http2_min_recv_ping_interval_without_data(Duration::from_secs(5)) + } + + /// Set the channel args to our defaults. + #[must_use] + fn set_default_channel_args(self, env: Arc) -> Self; } impl ConnectionUriGrpcioServer for ServerBuilder { @@ -86,4 +99,9 @@ impl ConnectionUriGrpcioServer for ServerBuilder { self.bind(uri.host(), uri.port()) } } + + /// Set the channel args to our defaults. + fn set_default_channel_args(self, env: Arc) -> Self { + self.channel_args(Self::default_channel_builder(env).build_args()) + } } diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index 72a926f050..a52621effb 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -36,7 +36,7 @@ clap = { version = "3.1", features = ["derive", "env"] } displaydoc = "0.2" hex = "0.4" pem = "1.0" -prost = "0.10.1" +prost = "0.10" rand = "0.8" rand_core = "0.6.3" rand_hc = "0.3" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index 1e6600f344..a75caa61ba 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -14,5 +14,7 @@ path = "src/lib.rs" cfg-if = "1.0" displaydoc = "0.2" hostname = "0.3.1" -opentelemetry = "0.17" -opentelemetry-jaeger = { version = "0.16", features = ["collector_client", "isahc"], optional = true } + +# requires a fork due to a dependency upgrade on the `thrift` crate that has not yet been released +opentelemetry = { git = "https://github.com/mobilecoinofficial/opentelemetry-rust.git", rev = "1817229c56340bbb4a6dca63c8dfb5154606e5bf" } +opentelemetry-jaeger = { git = "https://github.com/mobilecoinofficial/opentelemetry-rust.git", rev = "1817229c56340bbb4a6dca63c8dfb5154606e5bf", features = ["collector_client", "isahc"], optional = true } From 9d30d3b95644a9d18fb1b2afb9c0f33dea38b5c6 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Wed, 18 May 2022 10:45:56 -0600 Subject: [PATCH 09/77] add an option to use an ipinfo token (#1996) --- mobilecoind/src/config.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/mobilecoind/src/config.rs b/mobilecoind/src/config.rs index e23ccb59f9..015cc8065e 100644 --- a/mobilecoind/src/config.rs +++ b/mobilecoind/src/config.rs @@ -18,7 +18,7 @@ use mc_util_uri::{ConnectionUri, ConsensusClientUri, FogUri}; #[cfg(feature = "ip-check")] use reqwest::{ blocking::Client, - header::{HeaderMap, HeaderValue, CONTENT_TYPE}, + header::{HeaderMap, HeaderValue, InvalidHeaderValue, AUTHORIZATION, CONTENT_TYPE}, }; use std::{path::PathBuf, sync::Arc, time::Duration}; @@ -98,6 +98,10 @@ pub struct Config { /// Automatically migrate the ledger db into the most recent version. #[clap(long, env = "MC_LEDGER_DB_MIGRATE")] pub ledger_db_migrate: bool, + + /// An authorization token for the ipinfo.io service, if available + #[clap(long, env = "MC_IP_INFO_TOKEN", default_value = "")] + pub ip_info_token: String, } fn parse_quorum_set_from_json(src: &str) -> Result, String> { @@ -125,6 +129,9 @@ pub enum ConfigError { /// Data missing in the response {0} DataMissing(String), + + /// Invalid header: {0} + InvalidHeader(InvalidHeaderValue), } impl From for ConfigError { @@ -139,6 +146,12 @@ impl From for ConfigError { } } +impl From for ConfigError { + fn from(e: InvalidHeaderValue) -> Self { + Self::InvalidHeader(e) + } +} + impl Config { /// Parse the quorom set. /// Panics on error. @@ -219,6 +232,14 @@ impl Config { let client = Client::builder().gzip(true).use_rustls_tls().build()?; let mut json_headers = HeaderMap::new(); json_headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); + + if !self.ip_info_token.is_empty() { + json_headers.insert( + AUTHORIZATION, + HeaderValue::from_str(&format!("Bearer {}", self.ip_info_token))?, + ); + } + let response = client .get("https://ipinfo.io/json/") .headers(json_headers) From 24e4daf8d41ff999d7d48455363b789bcc358a22 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Wed, 18 May 2022 12:57:50 -0600 Subject: [PATCH 10/77] make permission denied log level be info (#1997) (#1999) Logging at error causes a sentry alert, and so if a client like fog distro is in a retry loop submitting transactions and getting this error, it can blow out our sentry quota --- consensus/service/src/api/grpc_error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/service/src/api/grpc_error.rs b/consensus/service/src/api/grpc_error.rs index 6bd6a5f466..bf31893121 100644 --- a/consensus/service/src/api/grpc_error.rs +++ b/consensus/service/src/api/grpc_error.rs @@ -111,7 +111,7 @@ impl From for RpcStatus { "Temporarily not serving requests".into(), ), ConsensusGrpcError::Enclave(EnclaveError::Attest(err)) => { - global_log::error!("Permission denied: {}", err); + global_log::info!("Permission denied: {}", err); RpcStatus::with_message( RpcStatusCode::PERMISSION_DENIED, "Permission Denied (attestation)".into(), From afdf66c792780eb9e2ca1e4f62eb23a1756ee04b Mon Sep 17 00:00:00 2001 From: James Cape Date: Thu, 19 May 2022 12:31:36 -0700 Subject: [PATCH 11/77] Cherry-pick updates from master. (#2006) * Bump ed25519 from 1.5.0 to 1.5.2 (#1987) Bumps [ed25519](https://github.com/RustCrypto/signatures) from 1.5.0 to 1.5.2. - [Release notes](https://github.com/RustCrypto/signatures/releases) - [Commits](https://github.com/RustCrypto/signatures/compare/ed25519/v1.5.0...ed25519/v1.5.2) --- updated-dependencies: - dependency-name: ed25519 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump rayon from 1.5.2 to 1.5.3 (#1985) Bumps [rayon](https://github.com/rayon-rs/rayon) from 1.5.2 to 1.5.3. - [Release notes](https://github.com/rayon-rs/rayon/releases) - [Changelog](https://github.com/rayon-rs/rayon/blob/master/RELEASES.md) - [Commits](https://github.com/rayon-rs/rayon/compare/v1.5.2...v1.5.3) --- updated-dependencies: - dependency-name: rayon dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump rocket from 0.5.0-rc.1 to 0.5.0-rc.2 (#1949) * Bump rocket from 0.5.0-rc.1 to 0.5.0-rc.2 Bumps [rocket](https://github.com/SergioBenitez/Rocket) from 0.5.0-rc.1 to 0.5.0-rc.2. - [Release notes](https://github.com/SergioBenitez/Rocket/releases) - [Changelog](https://github.com/SergioBenitez/Rocket/blob/master/CHANGELOG.md) - [Commits](https://github.com/SergioBenitez/Rocket/compare/v0.5.0-rc.1...v0.5.0-rc.2) --- updated-dependencies: - dependency-name: rocket dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Update for Rocket v0.5.0-rc.2 Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrew Wygle * Bump ed25519 from 1.5.0 to 1.5.2 in /fog/view/enclave/trusted (#1983) Bumps [ed25519](https://github.com/RustCrypto/signatures) from 1.5.0 to 1.5.2. - [Release notes](https://github.com/RustCrypto/signatures/releases) - [Commits](https://github.com/RustCrypto/signatures/compare/ed25519/v1.5.0...ed25519/v1.5.2) --- updated-dependencies: - dependency-name: ed25519 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ed25519 from 1.5.0 to 1.5.2 in /consensus/enclave/trusted (#1982) Bumps [ed25519](https://github.com/RustCrypto/signatures) from 1.5.0 to 1.5.2. - [Release notes](https://github.com/RustCrypto/signatures/releases) - [Commits](https://github.com/RustCrypto/signatures/compare/ed25519/v1.5.0...ed25519/v1.5.2) --- updated-dependencies: - dependency-name: ed25519 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Implement some improvements to the `mc-consensus-mint-client` utility (#1993) * add TxFile and dump subcommand * add signing command * Uprev mbedtls to the newer version. (#2002) * Remove bigint in favor of primitive-types. (#1917) * Replace bigint with primitive_types. * rustfmt like a n00b * Update consensus/scp/src/slot.rs * Sort SCP dependencies. * Import std::convert::TryFrom * Fix build (again). * pr review fixes (#2000) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrew Wygle Co-authored-by: Eran Rundstein --- Cargo.lock | 484 +++++++++++++++----------- Cargo.toml | 4 +- admin-http-gateway/Cargo.toml | 2 +- admin-http-gateway/src/main.rs | 10 +- consensus/enclave/trusted/Cargo.lock | 18 +- consensus/enclave/trusted/Cargo.toml | 4 +- consensus/mint-client/Cargo.toml | 1 + consensus/mint-client/src/bin/main.rs | 114 ++++-- consensus/mint-client/src/config.rs | 56 ++- consensus/mint-client/src/lib.rs | 4 + consensus/mint-client/src/printers.rs | 119 +++++++ consensus/mint-client/src/tx_file.rs | 114 ++++++ consensus/scp/Cargo.toml | 6 +- consensus/scp/src/slot.rs | 13 +- consensus/scp/src/utils.rs | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 14 +- fog/ingest/enclave/trusted/Cargo.toml | 4 +- fog/ledger/enclave/trusted/Cargo.lock | 14 +- fog/ledger/enclave/trusted/Cargo.toml | 4 +- fog/overseer/server/Cargo.toml | 2 +- fog/overseer/server/src/bin/main.rs | 3 +- fog/view/enclave/trusted/Cargo.lock | 18 +- fog/view/enclave/trusted/Cargo.toml | 4 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind-json/src/bin/main.rs | 5 +- 25 files changed, 722 insertions(+), 299 deletions(-) create mode 100644 consensus/mint-client/src/printers.rs create mode 100644 consensus/mint-client/src/tx_file.rs diff --git a/Cargo.lock b/Cargo.lock index 1982c96e62..49881735a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -228,9 +228,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" @@ -257,28 +257,12 @@ dependencies = [ "rand_core 0.6.3", ] -[[package]] -name = "base-x" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc19a4937b4fbd3fe3379793130e42060d10627a360f2127802b10b87e7baf74" - [[package]] name = "base64" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" -[[package]] -name = "bigint" -version = "4.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0e8c8a600052b52482eff2cf4d810e462fdff1f656ac1ecb6232132a1ed7def" -dependencies = [ - "byteorder", - "crunchy", -] - [[package]] name = "binascii" version = "0.1.4" @@ -367,6 +351,18 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2" version = "0.10.4" @@ -444,6 +440,12 @@ version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" +[[package]] +name = "byte-slice-cast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" + [[package]] name = "bytecount" version = "0.4.0" @@ -452,9 +454,9 @@ checksum = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" @@ -724,29 +726,20 @@ dependencies = [ "cache-padded", ] -[[package]] -name = "const_fn" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" - -[[package]] -name = "cookie" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d" -dependencies = [ - "percent-encoding", - "time 0.2.27", - "version_check", -] - [[package]] name = "cookie" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" dependencies = [ + "aes-gcm", + "base64", + "hkdf", + "hmac 0.12.1", + "percent-encoding", + "rand 0.8.5", + "sha2 0.10.2", + "subtle", "time 0.3.9", "version_check", ] @@ -882,9 +875,9 @@ dependencies = [ [[package]] name = "crunchy" -version = "0.1.6" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" @@ -1148,12 +1141,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "displaydoc" version = "0.2.3" @@ -1179,9 +1166,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "ed25519" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ "serde", "signature", @@ -1312,6 +1299,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + [[package]] name = "flate2" version = "1.0.19" @@ -1367,6 +1366,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.3.21" @@ -1585,7 +1590,7 @@ dependencies = [ "grpcio-sys", "libc", "log", - "parking_lot", + "parking_lot 0.11.2", "protobuf", ] @@ -1629,7 +1634,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util", + "tokio-util 0.6.9", "tracing", ] @@ -1826,6 +1831,26 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "indexmap" version = "1.7.0" @@ -2076,10 +2101,11 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] @@ -2137,7 +2163,7 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "mbedtls" version = "0.8.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bitflags", "byteorder", @@ -2149,14 +2175,14 @@ dependencies = [ "rs-libc", "serde", "serde_derive", - "spin 0.4.10", + "spin 0.9.3", "yasna", ] [[package]] name = "mbedtls-sys-auto" version = "2.26.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bindgen 0.58.1", "cc", @@ -2497,7 +2523,7 @@ name = "mc-connection" version = "1.3.0-pre0" dependencies = [ "aes-gcm", - "cookie 0.16.0", + "cookie", "displaydoc", "grpcio", "mc-attest-ake", @@ -2683,6 +2709,7 @@ name = "mc-consensus-mint-client" version = "1.3.0-pre0" dependencies = [ "clap 3.1.18", + "displaydoc", "grpcio", "hex", "mc-account-keys", @@ -2710,7 +2737,6 @@ dependencies = [ name = "mc-consensus-scp" version = "1.3.0-pre0" dependencies = [ - "bigint", "crossbeam-channel", "maplit", "mc-common", @@ -2721,6 +2747,7 @@ dependencies = [ "mc-util-serial", "mc-util-test-helper", "mockall", + "primitive-types", "rand 0.8.5", "rand_hc 0.3.1", "serde", @@ -3129,7 +3156,7 @@ name = "mc-fog-enclave-connection" version = "1.3.0-pre0" dependencies = [ "aes-gcm", - "cookie 0.16.0", + "cookie", "displaydoc", "grpcio", "mc-attest-ake", @@ -4986,7 +5013,7 @@ version = "1.3.0-pre0" dependencies = [ "base64", "clap 3.1.18", - "cookie 0.16.0", + "cookie", "displaydoc", "futures", "grpcio", @@ -5374,9 +5401,9 @@ dependencies = [ [[package]] name = "mockall" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4d70639a72f972725db16350db56da68266ca368b2a1fe26724a903ad3d6b8" +checksum = "5641e476bbaf592a3939a7485fa079f427b4db21407d5ebfd5bba4e07a1f6f4c" dependencies = [ "cfg-if 1.0.0", "downcast", @@ -5389,9 +5416,9 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ef208208a0dea3f72221e26e904cdc6db2e481d9ade89081ddd494f1dbaa6b" +checksum = "262d56735932ee0240d515656e5a7667af3af2a5b0af4da558c4cff2b2aeb0c7" dependencies = [ "cfg-if 1.0.0", "proc-macro2", @@ -5421,7 +5448,7 @@ dependencies = [ "mime", "spin 0.9.3", "tokio", - "tokio-util", + "tokio-util 0.6.9", "version_check", ] @@ -5634,6 +5661,32 @@ dependencies = [ "libm", ] +[[package]] +name = "parity-scale-codec" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "parking" version = "2.0.0" @@ -5648,7 +5701,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.3", ] [[package]] @@ -5665,6 +5728,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "pbkdf2" version = "0.4.0" @@ -5854,6 +5930,27 @@ dependencies = [ "treeline", ] +[[package]] +name = "primitive-types" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +dependencies = [ + "thiserror", + "toml", +] + [[package]] name = "proc-macro-error" version = "1.0.2" @@ -5880,12 +5977,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - [[package]] name = "proc-macro2" version = "1.0.38" @@ -5918,7 +6009,7 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot", + "parking_lot 0.11.2", "protobuf", "thiserror", ] @@ -6042,10 +6133,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" dependencies = [ "log", - "parking_lot", + "parking_lot 0.11.2", "scheduled-thread-pool", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.4.6" @@ -6165,9 +6262,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ "autocfg", "crossbeam-deque", @@ -6302,7 +6399,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-rustls", - "tokio-util", + "tokio-util 0.6.9", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -6343,9 +6440,9 @@ checksum = "5510dbde48c4c37bf69123b1f636b6dd5f8dffe1f4e358af03c46a4947dca219" [[package]] name = "rocket" -version = "0.5.0-rc.1" +version = "0.5.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a71c18c42a0eb15bf3816831caf0dad11e7966f2a41aaf486a701979c4dd1f2" +checksum = "98ead083fce4a405feb349cf09abdf64471c6077f14e0ce59364aa90d4b99317" dependencies = [ "async-stream", "async-trait", @@ -6361,7 +6458,7 @@ dependencies = [ "memchr", "multer", "num_cpus", - "parking_lot", + "parking_lot 0.12.0", "pin-project-lite", "rand 0.8.5", "ref-cast", @@ -6371,10 +6468,10 @@ dependencies = [ "serde_json", "state", "tempfile", - "time 0.2.27", + "time 0.3.9", "tokio", "tokio-stream", - "tokio-util", + "tokio-util 0.7.2", "ubyte", "version_check", "yansi", @@ -6382,9 +6479,9 @@ dependencies = [ [[package]] name = "rocket_codegen" -version = "0.5.0-rc.1" +version = "0.5.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66f5fa462f7eb958bba8710c17c5d774bbbd59809fa76fb1957af7e545aea8bb" +checksum = "d6aeb6bb9c61e9cd2c00d70ea267bf36f76a4cc615e5908b349c2f9d93999b47" dependencies = [ "devise", "glob 0.3.0", @@ -6398,19 +6495,18 @@ dependencies = [ [[package]] name = "rocket_http" -version = "0.5.0-rc.1" +version = "0.5.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c8b7d512d2fcac2316ebe590cde67573844b99e6cc9ee0f53375fa16e25ebd" +checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2" dependencies = [ - "cookie 0.15.1", + "cookie", "either", + "futures", "http", "hyper", "indexmap", "log", "memchr", - "mime", - "parking_lot", "pear", "percent-encoding", "pin-project-lite", @@ -6419,7 +6515,7 @@ dependencies = [ "smallvec", "stable-pattern", "state", - "time 0.2.27", + "time 0.3.9", "tokio", "uncased", ] @@ -6527,6 +6623,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + [[package]] name = "rustc_version" version = "0.2.3" @@ -6636,7 +6738,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" dependencies = [ - "parking_lot", + "parking_lot 0.11.2", ] [[package]] @@ -6921,7 +7023,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5bcc41d18f7a1d50525d080fd3e953be87c4f9f1a974f3c21798ca00d54ec15" dependencies = [ "lazy_static", - "parking_lot", + "parking_lot 0.11.2", "serial_test_derive", ] @@ -6938,21 +7040,6 @@ dependencies = [ "syn", ] -[[package]] -name = "sha1" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" -dependencies = [ - "sha1_smol", -] - -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - [[package]] name = "sha2" version = "0.9.8" @@ -7212,12 +7299,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "spin" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" - [[package]] name = "spin" version = "0.5.2" @@ -7239,15 +7320,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check", -] - [[package]] name = "state" version = "0.5.3" @@ -7258,53 +7330,10 @@ dependencies = [ ] [[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version 0.2.3", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2", - "quote", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "strsim" @@ -7364,6 +7393,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempdir" version = "0.3.7" @@ -7483,21 +7518,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "time" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" -dependencies = [ - "const_fn", - "libc", - "standback", - "stdweb", - "time-macros 0.1.1", - "version_check", - "winapi", -] - [[package]] name = "time" version = "0.3.9" @@ -7507,17 +7527,7 @@ dependencies = [ "itoa 1.0.1", "libc", "num_threads", - "time-macros 0.2.4", -] - -[[package]] -name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", + "time-macros", ] [[package]] @@ -7526,19 +7536,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" -[[package]] -name = "time-macros-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn", -] - [[package]] name = "tiny-bip39" version = "0.8.2" @@ -7648,6 +7645,19 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-util" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" +dependencies = [ + "bytes 1.1.0", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.5.9" @@ -7762,6 +7772,18 @@ dependencies = [ "serde", ] +[[package]] +name = "uint" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "uname" version = "0.1.1" @@ -8077,6 +8099,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "winreg" version = "0.10.1" @@ -8086,6 +8151,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "wyz" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" +dependencies = [ + "tap", +] + [[package]] name = "x25519-dalek" version = "2.0.0-pre.2" diff --git a/Cargo.toml b/Cargo.toml index 36f08a4f6b..f01e9975bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -199,8 +199,8 @@ curve25519-dalek = { git = "https://github.com/mobilecoinfoundation/curve25519-d ed25519-dalek = { git = "https://github.com/mobilecoinfoundation/ed25519-dalek.git", rev = "4194e36abc75722e6fba7d552e719448fc38c51f" } # mbedtls patched to allow certificate verification with a profile -mbedtls = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } -mbedtls-sys-auto = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } +mbedtls = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } +mbedtls-sys-auto = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } # Override lmdb-rkv for a necessary bugfix (see https://github.com/mozilla/lmdb-rs/pull/80) lmdb-rkv = { git = "https://github.com/mozilla/lmdb-rs", rev = "df1c2f5" } diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index f61607f41b..37c3ea9ddd 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -11,7 +11,7 @@ mc-util-uri = { path = "../util/uri" } clap = { version = "3.1", features = ["derive", "env"] } grpcio = "0.10.2" -rocket = { version = "0.5.0-rc.1", features = ["json"] } +rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" diff --git a/admin-http-gateway/src/main.rs b/admin-http-gateway/src/main.rs index 1bda68980f..ffc539603f 100644 --- a/admin-http-gateway/src/main.rs +++ b/admin-http-gateway/src/main.rs @@ -46,8 +46,8 @@ struct State { } #[get("/")] -fn index() -> content::Html { - content::Html(include_str!("../templates/index.html").to_owned()) +fn index() -> content::RawHtml { + content::RawHtml(include_str!("../templates/index.html").to_owned()) } #[derive(Serialize)] @@ -144,9 +144,11 @@ async fn main() -> Result<(), rocket::Error> { .merge(("port", config.listen_port)) .merge(("address", config.listen_host.clone())); - rocket::custom(figment) + let _rocket = rocket::custom(figment) .mount("/", routes![index, info, set_rust_log, metrics]) .manage(State { admin_api_client }) .launch() - .await + .await?; + + Ok(()) } diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index df77880776..b0be21bec8 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -364,9 +364,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ "serde", "signature", @@ -615,7 +615,7 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "mbedtls" version = "0.8.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bitflags", "byteorder", @@ -627,14 +627,14 @@ dependencies = [ "rs-libc", "serde", "serde_derive", - "spin 0.4.10", + "spin 0.9.3", "yasna", ] [[package]] name = "mbedtls-sys-auto" version = "2.26.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bindgen", "cc", @@ -1625,15 +1625,15 @@ checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" [[package]] name = "spin" -version = "0.4.10" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.5.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" [[package]] name = "strsim" diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index 2265163d5f..d7df707b01 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -72,8 +72,8 @@ curve25519-dalek = { git = "https://github.com/mobilecoinfoundation/curve25519-d ed25519-dalek = { git = "https://github.com/mobilecoinfoundation/ed25519-dalek.git", rev = "4194e36abc75722e6fba7d552e719448fc38c51f" } # Our patches for newer bindgen, no-std -mbedtls = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } -mbedtls-sys-auto = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } +mbedtls = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } +mbedtls-sys-auto = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } # Fork and rename to use "OG" dalek-cryptography. schnorrkel-og = { git = "https://github.com/mobilecoinfoundation/schnorrkel.git", rev = "5c98ae068ee4652d6df6463b549fbf2d5d132faa" } diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index 99c0d76001..94bcbcd4d0 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -27,6 +27,7 @@ mc-util-parse = { path = "../../util/parse" } mc-util-uri = { path = "../../util/uri" } clap = { version = "3.1", features = ["derive", "env"] } +displaydoc = "0.2" grpcio = "0.10.2" hex = "0.4" pem = "1.0" diff --git a/consensus/mint-client/src/bin/main.rs b/consensus/mint-client/src/bin/main.rs index d6b7595678..b08ce9be30 100644 --- a/consensus/mint-client/src/bin/main.rs +++ b/consensus/mint-client/src/bin/main.rs @@ -10,8 +10,8 @@ use mc_consensus_api::{ empty::Empty, }; use mc_consensus_enclave_api::GovernorsSigner; -use mc_consensus_mint_client::{Commands, Config}; -use mc_crypto_keys::Ed25519Pair; +use mc_consensus_mint_client::{printers, Commands, Config, TxFile}; +use mc_crypto_keys::{Ed25519Pair, Signer}; use mc_crypto_multisig::MultiSig; use mc_transaction_core::{ constants::MAX_TOMBSTONE_BLOCKS, @@ -19,8 +19,7 @@ use mc_transaction_core::{ }; use mc_util_grpc::ConnectionUriGrpcioChannel; use protobuf::ProtobufEnum; -use serde::de::DeserializeOwned; -use std::{fs, path::PathBuf, process::exit, sync::Arc}; +use std::{fs, process::exit, sync::Arc}; fn main() { let (logger, _global_logger_guard) = create_app_logger(o!()); @@ -42,6 +41,10 @@ fn main() { }) .expect("failed creating tx"); + if tx.signature.signatures().is_empty() { + panic!("tx contains no signatures"); + } + let resp = client_api .propose_mint_config_tx(&(&tx).into()) .expect("propose tx"); @@ -58,9 +61,9 @@ fn main() { .try_into_mint_config_tx(|| panic!("missing tombstone block")) .expect("failed creating tx"); - let json = serde_json::to_string_pretty(&tx).expect("failed serializing tx"); - - fs::write(out, json).expect("failed writing output file"); + TxFile::from(tx) + .write_json(&out) + .expect("failed writing output file"); } Commands::HashMintConfigTx { params } => { @@ -78,7 +81,8 @@ fn main() { Commands::SubmitMintConfigTx { node, tx_filenames } => { // Load all txs. - let txs: Vec = load_json_files(&tx_filenames); + let txs = + TxFile::load_multiple::(&tx_filenames).expect("failed loading txs"); // All tx prefixes should be the same. if !txs.windows(2).all(|pair| pair[0].prefix == pair[1].prefix) { @@ -93,6 +97,9 @@ fn main() { .collect::>(); signatures.sort(); signatures.dedup(); + if signatures.is_empty() { + panic!("tx contains no signatures"); + } let merged_tx = MintConfigTx { prefix: txs[0].prefix.clone(), @@ -128,6 +135,11 @@ fn main() { last_block_info.index + MAX_TOMBSTONE_BLOCKS - 1 }) .expect("failed creating tx"); + + if tx.signature.signatures().is_empty() { + panic!("tx contains no signatures"); + } + let resp = client_api .propose_mint_tx(&(&tx).into()) .expect("propose tx"); @@ -144,9 +156,9 @@ fn main() { .try_into_mint_tx(|| panic!("missing tombstone block")) .expect("failed creating tx"); - let json = serde_json::to_string_pretty(&tx).expect("failed serializing tx"); - - fs::write(out, json).expect("failed writing output file"); + TxFile::from(tx) + .write_json(&out) + .expect("failed writing output file"); } Commands::HashMintTx { params } => { @@ -164,7 +176,7 @@ fn main() { Commands::SubmitMintTx { node, tx_filenames } => { // Load all txs. - let txs: Vec = load_json_files(&tx_filenames); + let txs = TxFile::load_multiple::(&tx_filenames).expect("failed loading txs"); // All tx prefixes should be the same. if !txs.windows(2).all(|pair| pair[0].prefix == pair[1].prefix) { @@ -179,6 +191,9 @@ fn main() { .collect::>(); signatures.sort(); signatures.dedup(); + if signatures.is_empty() { + panic!("tx contains no signatures"); + } let merged_tx = MintTx { prefix: txs[0].prefix.clone(), @@ -228,17 +243,68 @@ fn main() { fs::write(path, json_str).expect("failed writing output file"); } } - } -} -fn load_json_files(filenames: &[PathBuf]) -> Vec { - filenames - .iter() - .map(|filename| { - let json = fs::read_to_string(filename) - .unwrap_or_else(|err| panic!("Failed reading file {:?}: {}", filename, err)); - serde_json::from_str(&json) - .unwrap_or_else(|err| panic!("Failed parsing tx from file {:?}: {}", filename, err)) - }) - .collect() + Commands::Dump { tx_file } => match tx_file { + TxFile::MintConfigTx(tx) => { + printers::print_mint_config_tx(&tx, 0); + } + TxFile::MintTx(tx) => { + printers::print_mint_tx(&tx, 0); + } + }, + + Commands::Sign { + tx_file: tx_file_path, + signing_keys, + mut signatures, + } => { + let mut tx_file = + TxFile::from_json_file(&tx_file_path).expect("failed loading tx file"); + + // Append any existing signatures. + signatures.extend(match &tx_file { + TxFile::MintConfigTx(tx) => tx.signature.signatures().to_vec(), + TxFile::MintTx(tx) => tx.signature.signatures().to_vec(), + }); + + // The message we are signing. + let message = match &tx_file { + TxFile::MintConfigTx(tx) => tx.prefix.hash(), + TxFile::MintTx(tx) => tx.prefix.hash(), + }; + + // Append signatures using the keys provided. + signatures.extend( + signing_keys + .into_iter() + .map(|signer| { + Ed25519Pair::from(signer) + .try_sign(message.as_ref()) + .map_err(|e| format!("Failed to sign: {}", e)) + }) + .collect::, _>>() + .expect("failed signing"), + ); + + // De-dupe. + signatures.sort(); + signatures.dedup(); + + // Update the tx file signature. + let signature = MultiSig::new(signatures); + match &mut tx_file { + TxFile::MintConfigTx(ref mut tx) => { + tx.signature = signature; + } + TxFile::MintTx(ref mut tx) => { + tx.signature = signature; + } + } + + // Write the file. + tx_file + .write_json(&tx_file_path) + .expect("failed writing tx file"); + } + } } diff --git a/consensus/mint-client/src/config.rs b/consensus/mint-client/src/config.rs index c3d6958ba1..5afc0511ea 100644 --- a/consensus/mint-client/src/config.rs +++ b/consensus/mint-client/src/config.rs @@ -2,6 +2,7 @@ //! Command line configuration for the consensus mint client. +use crate::TxFile; use clap::{Args, Parser, Subcommand}; use hex::FromHex; use mc_account_keys::PublicAddress; @@ -87,7 +88,6 @@ pub struct MintConfigTxParams { long = "signing-key", use_value_delimiter = true, parse(try_from_str = load_key_from_pem), - required_unless_present = "signatures", env = "MC_MINTING_SIGNING_KEYS" )] signing_keys: Vec, @@ -96,7 +96,8 @@ pub struct MintConfigTxParams { #[clap( long = "signature", use_value_delimiter = true, - parse(try_from_str = load_or_parse_ed25519_signature), env = "MC_MINTING_SIGNATURES" + parse(try_from_str = load_or_parse_ed25519_signature), + env = "MC_MINTING_SIGNATURES" )] signatures: Vec, @@ -181,7 +182,6 @@ pub struct MintTxParams { long = "signing-key", use_value_delimiter = true, parse(try_from_str = load_key_from_pem), - required_unless_present = "signatures", env = "MC_MINTING_SIGNING_KEYS" )] signing_keys: Vec, @@ -264,12 +264,12 @@ pub enum Commands { node: ConsensusClientUri, /// Paths for the JSON-formatted mint configuration tx files, each - /// containing a serde-serialized MintConfigTx object. + /// containing a serde-serialized TxFile holding a MintConfigTx object. #[clap( - long = "tx", + long = "tx-file", required = true, use_value_delimiter = true, - env = "MC_MINTING_CONFIG_TXS" + env = "MC_MINTING_CONFIG_TX_FILES" )] tx_filenames: Vec, }, @@ -310,12 +310,12 @@ pub enum Commands { node: ConsensusClientUri, /// Paths for the JSON-formatted mint tx files, each containing a - /// serde-serialized MintTx object. + /// serde-serialized TxFile holding a MintTx object. #[clap( - long = "tx", + long = "tx-file", required = true, use_value_delimiter = true, - env = "MC_MINTING_TXS" + env = "MC_MINTING_TX_FILES" )] tx_filenames: Vec, }, @@ -338,6 +338,40 @@ pub enum Commands { #[clap(long, env = "MC_MINTING_OUTPUT_JSON")] output_json: Option, }, + + /// Load a previously-serialized file produced by this tool and print its + /// contents in a human-friendly way. + Dump { + /// The file to load + #[clap(long, parse(try_from_str = load_tx_file_from_path), env = "MC_MINTING_TX_FILE")] + tx_file: TxFile, + }, + + /// Sign a transaction file produced by this tool, rewriting the file with + /// the appended signature(s). + Sign { + /// The file to sign + #[clap(long, env = "MC_MINTING_TX_FILE")] + tx_file: PathBuf, + + /// The key(s) to sign the transaction with. + #[clap( + long = "signing-key", + required_unless_present = "signatures", + parse(try_from_str = load_key_from_pem), + env = "MC_MINTING_SIGNING_KEYS" + )] + signing_keys: Vec, + + /// Pre-generated signature(s) to use, either in hex format or a PEM + /// file. + #[clap( + long = "signature", + use_value_delimiter = true, + parse(try_from_str = load_or_parse_ed25519_signature), env = "MC_MINTING_SIGNATURES" + )] + signatures: Vec, + }, } #[derive(Parser)] @@ -472,3 +506,7 @@ fn get_or_generate_nonce(nonce: Option<[u8; NONCE_LENGTH]>) -> Vec { nonce }) } + +fn load_tx_file_from_path(path: &str) -> Result { + TxFile::from_json_file(path).map_err(|e| format!("failed loading file {:?}: {}", path, e)) +} diff --git a/consensus/mint-client/src/lib.rs b/consensus/mint-client/src/lib.rs index c4f1a9bbff..c8915c692d 100644 --- a/consensus/mint-client/src/lib.rs +++ b/consensus/mint-client/src/lib.rs @@ -1,5 +1,9 @@ // Copyright (c) 2018-2022 The MobileCoin Foundation mod config; +mod tx_file; + +pub mod printers; pub use config::{Commands, Config}; +pub use tx_file::TxFile; diff --git a/consensus/mint-client/src/printers.rs b/consensus/mint-client/src/printers.rs new file mode 100644 index 0000000000..17d10b6346 --- /dev/null +++ b/consensus/mint-client/src/printers.rs @@ -0,0 +1,119 @@ +// Copyright (c) 2018-2022 The MobileCoin Foundation + +//! Utility functions for printing objects in a human-friendly way. + +use mc_account_keys::PublicAddress; +use mc_api::printable::PrintableWrapper; +use mc_crypto_keys::{DistinguishedEncoding, Ed25519Public, Ed25519Signature}; +use mc_crypto_multisig::{MultiSig, SignerSet}; +use mc_transaction_core::mint::{ + MintConfig, MintConfigTx, MintConfigTxPrefix, MintTx, MintTxPrefix, +}; +use pem::Pem; + +const INDENT_STR: &str = " "; +const PEM_TAG_SIGNATURE: &str = "SIGNATURE"; +const PEM_TAG_PUBLIC_KEY: &str = "PUBLIC KEY"; + +pub fn print_mint_config_tx(tx: &MintConfigTx, indent: usize) { + let indent_str = INDENT_STR.repeat(indent); + println!("{}MintConfigTx:", indent_str); + print_mint_config_tx_prefix(&tx.prefix, indent + 1); + print_multi_sig(&tx.signature, indent + 1); +} + +pub fn print_mint_config_tx_prefix(prefix: &MintConfigTxPrefix, indent: usize) { + let mut indent_str = INDENT_STR.repeat(indent); + println!("{}MintConfigTxPrefix:", indent_str); + + indent_str.push_str(INDENT_STR); + println!( + "{}Configs ({} config(s)):", + indent_str, + prefix.configs.len() + ); + for config in &prefix.configs { + print_mint_config(config, indent + 2); + } + println!("{}Nonce: {}", indent_str, hex::encode(&prefix.nonce)); + println!("{}Tombstone block: {}", indent_str, prefix.tombstone_block); + println!( + "{}Total mint limit: {}", + indent_str, prefix.total_mint_limit + ); +} + +pub fn print_mint_config(mint_config: &MintConfig, indent: usize) { + let mut indent_str = INDENT_STR.repeat(indent); + println!("{}MintConfig:", indent_str); + + indent_str.push_str(INDENT_STR); + println!("{}Token id: {}", indent_str, mint_config.token_id); + println!("{}Mint limit: {}", indent_str, mint_config.mint_limit); + print_signer_set(&mint_config.signer_set, indent + 1); +} + +pub fn print_mint_tx(tx: &MintTx, indent: usize) { + let indent_str = INDENT_STR.repeat(indent); + println!("{}MintTx:", indent_str); + print_mint_tx_prefix(&tx.prefix, indent + 1); + print_multi_sig(&tx.signature, indent + 1); +} + +pub fn print_mint_tx_prefix(prefix: &MintTxPrefix, indent: usize) { + let recipient = PublicAddress::new(&prefix.spend_public_key, &prefix.view_public_key); + let mut wrapper = PrintableWrapper::new(); + wrapper.set_public_address((&recipient).into()); + let b58_recipient = wrapper.b58_encode().expect("failed encoding b58 address"); + + let mut indent_str = INDENT_STR.repeat(indent); + println!("{}MintTxPrefix:", indent_str); + indent_str.push_str(INDENT_STR); + println!("{}Token id: {}", indent_str, prefix.token_id); + println!("{}Mint amount: {}", indent_str, prefix.amount); + println!("{}View public key: {}", indent_str, prefix.view_public_key,); + println!( + "{}Spend public key: {}", + indent_str, prefix.spend_public_key + ); + println!("{}Recipient B58 address: {}", indent_str, b58_recipient); + println!("{}Nonce: {}", indent_str, hex::encode(&prefix.nonce)); + println!("{}Tombstone block: {}", indent_str, prefix.tombstone_block); +} + +pub fn print_signer_set(signer_set: &SignerSet, indent: usize) { + let mut indent_str = INDENT_STR.repeat(indent); + println!( + "{}Signer set ({} signer(s)):", + indent_str, + signer_set.signers().len() + ); + indent_str.push_str(INDENT_STR); + for signer in signer_set.signers() { + print_pem(signer, PEM_TAG_PUBLIC_KEY, indent + 2); + } + println!("{}Threshold: {}", indent_str, signer_set.threshold()); +} + +pub fn print_multi_sig(multi_sig: &MultiSig, indent: usize) { + let indent_str = INDENT_STR.repeat(indent); + println!( + "{}Multisig ({} signature(s)):", + indent_str, + multi_sig.signatures().len() + ); + for sig in multi_sig.signatures() { + print_pem(sig, PEM_TAG_SIGNATURE, indent + 1); + } +} + +pub fn print_pem(obj: &impl DistinguishedEncoding, tag: &str, indent: usize) { + let indent_str = INDENT_STR.repeat(indent); + let pem_str = pem::encode(&Pem { + tag: tag.into(), + contents: obj.to_der(), + }); + for line in pem_str.lines() { + println!("{}{}", indent_str, line); + } +} diff --git a/consensus/mint-client/src/tx_file.rs b/consensus/mint-client/src/tx_file.rs new file mode 100644 index 0000000000..65a0002d44 --- /dev/null +++ b/consensus/mint-client/src/tx_file.rs @@ -0,0 +1,114 @@ +// Copyright (c) 2018-2022 The MobileCoin Foundation + +//! A file format for serializing/deserializing objects used by by the mint +//! client. This is used instead of serializing/deserializing the actual objects +//! so that if the users confuses one file type with another we are guaranteed +//! to get a deserialization error. + +use displaydoc::Display; +use mc_transaction_core::mint::{MintConfigTx, MintTx}; +use serde::{Deserialize, Serialize}; +use serde_json::Error as JsonError; +use std::{ + convert::TryFrom, + fs, + io::Error as IoError, + path::{Path, PathBuf}, +}; + +/// An enum for holding all possible objects the mint client needs to store in a +/// file. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum TxFile { + MintConfigTx(MintConfigTx), + MintTx(MintTx), +} + +impl From for TxFile { + fn from(tx: MintConfigTx) -> Self { + Self::MintConfigTx(tx) + } +} + +impl TryFrom for MintConfigTx { + type Error = TxFileError; + + fn try_from(tx_file: TxFile) -> Result { + match tx_file { + TxFile::MintConfigTx(tx) => Ok(tx), + TxFile::MintTx(_) => Err(TxFileError::WrongFileContents("MintConfigTx", "MintTx")), + } + } +} + +impl From for TxFile { + fn from(tx: MintTx) -> Self { + Self::MintTx(tx) + } +} + +impl TryFrom for MintTx { + type Error = TxFileError; + + fn try_from(tx_file: TxFile) -> Result { + match tx_file { + TxFile::MintTx(tx) => Ok(tx), + TxFile::MintConfigTx(_) => { + Err(TxFileError::WrongFileContents("MintTx", "MintConfigTx")) + } + } + } +} + +impl TxFile { + /// Write the contents of this object to the given file. + pub fn write_json(&self, path: &impl AsRef) -> Result<(), TxFileError> { + let json = serde_json::to_string_pretty(&self)?; + fs::write(path, json)?; + Ok(()) + } + + /// Load a [TxFile] from a JSON file. + pub fn from_json_file>(path: P) -> Result { + let json = fs::read_to_string(path)?; + let tx = serde_json::from_str(&json)?; + Ok(tx) + } + + /// Attempt to load multiple files where all files contain a specific object + /// type. + pub fn load_multiple(filenames: &[PathBuf]) -> Result, TxFileError> + where + T: TryFrom, + { + filenames + .iter() + .map(|filename| T::try_from(TxFile::from_json_file(filename)?)) + .collect::, TxFileError>>() + } +} + +/// Error type for TxFile operations. +#[derive(Debug, Display)] +pub enum TxFileError { + /// IO error: {0} + Io(IoError), + + /// JSON error: {0} + Json(JsonError), + + /// Wrong file contents: Expected {0} but found {1} + WrongFileContents(&'static str, &'static str), +} + +impl From for TxFileError { + fn from(err: IoError) -> Self { + Self::Io(err) + } +} + +impl From for TxFileError { + fn from(err: JsonError) -> Self { + Self::Json(err) + } +} diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index 54d6f3c0b1..7941e3a851 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -2,7 +2,7 @@ name = "mc-consensus-scp" version = "1.3.0-pre0" authors = ["MobileCoin"] -edition = "2018" +edition = "2021" description = "Stellar Consensus Protocol" keywords = ["SCP", "Stellar Consensus Protocol", "Consensus", "Stellar", "Byzantine"] readme = "README.md" @@ -17,9 +17,9 @@ mc-crypto-keys = { path = "../../crypto/keys" } mc-util-from-random = { path = "../../util/from-random" } mc-util-serial = { path = "../../util/serial", features = ["std"] } -bigint = "4.4" maplit = "1.0.2" -mockall = "0.11.0" +mockall = "0.11.1" +primitive-types = "0.11.1" rand = "0.8" rand_hc = "0.3" serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } diff --git a/consensus/scp/src/slot.rs b/consensus/scp/src/slot.rs index e74a34fad8..d566313335 100644 --- a/consensus/scp/src/slot.rs +++ b/consensus/scp/src/slot.rs @@ -22,9 +22,11 @@ use mc_common::{ }; #[cfg(test)] use mockall::*; +use primitive_types::{U256, U512}; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeSet, HashMap, HashSet}, + convert::TryFrom, fmt::Display, sync::Arc, time::{Duration, Instant}, @@ -494,10 +496,11 @@ impl Slot { // weight256 is the node's weight, scaled to 0.. // (weight256 = * / ) let (num, denom) = self.weight(node_id); - let mut tmp = bigint::U512::from(bigint::U256::max_value()); - tmp = tmp.saturating_mul(bigint::U512::from(num)); - tmp = tmp.overflowing_div(bigint::U512::from(denom)).0; - let weight256 = bigint::U256::from(tmp); + let mut tmp = U512::from(U256::max_value()); + tmp = tmp.saturating_mul(U512::from(num)); + tmp /= U512::from(denom); + let weight256 = U256::try_from(tmp) + .expect("failure calculating weight (max_u256 * k -> 2^512) / n"); let gi_one = utils::slot_round_salted_keccak( slot_index, @@ -518,7 +521,7 @@ impl Slot { fn find_max_priority_peer(&self, round: u32) -> NodeID { let neighbors = self.neighbors(self.slot_index, round); let mut result = self.node_id.clone(); - let mut max_priority = bigint::U256::zero(); + let mut max_priority = U256::zero(); for node_id in neighbors.iter() { // NOTE: this deviates from the spec. Without doing this we may have nomination diff --git a/consensus/scp/src/utils.rs b/consensus/scp/src/utils.rs index 9a22b10f54..ce90f1fccd 100644 --- a/consensus/scp/src/utils.rs +++ b/consensus/scp/src/utils.rs @@ -1,8 +1,8 @@ // Copyright (c) 2018-2022 The MobileCoin Foundation use crate::core_types::SlotIndex; -use bigint::U256; use mc_common::fast_hash; +use primitive_types::U256; /// A "salted" Keccak hash function, parametrized by slot, round, and an extra /// value. diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 35cadc45f2..141d3c6fb7 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -635,7 +635,7 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "mbedtls" version = "0.8.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bitflags", "byteorder", @@ -647,14 +647,14 @@ dependencies = [ "rs-libc", "serde", "serde_derive", - "spin 0.4.10", + "spin 0.9.3", "yasna", ] [[package]] name = "mbedtls-sys-auto" version = "2.26.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bindgen", "cc", @@ -1730,15 +1730,15 @@ checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a" [[package]] name = "spin" -version = "0.4.10" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.5.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" [[package]] name = "strsim" diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index dc77881974..c322ea1143 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -77,8 +77,8 @@ curve25519-dalek = { git = "https://github.com/mobilecoinfoundation/curve25519-d ed25519-dalek = { git = "https://github.com/mobilecoinfoundation/ed25519-dalek.git", rev = "4194e36abc75722e6fba7d552e719448fc38c51f" } # Our patches for newer bindgen, no-std -mbedtls = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } -mbedtls-sys-auto = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } +mbedtls = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } +mbedtls-sys-auto = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } # Fork and rename to use "OG" dalek-cryptography. schnorrkel-og = { git = "https://github.com/mobilecoinfoundation/schnorrkel.git", rev = "5c98ae068ee4652d6df6463b549fbf2d5d132faa" } diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 2de2e5731e..a568c928cd 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -639,7 +639,7 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "mbedtls" version = "0.8.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bitflags", "byteorder", @@ -651,14 +651,14 @@ dependencies = [ "rs-libc", "serde", "serde_derive", - "spin 0.4.10", + "spin 0.9.3", "yasna", ] [[package]] name = "mbedtls-sys-auto" version = "2.26.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bindgen", "cc", @@ -1714,15 +1714,15 @@ checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" [[package]] name = "spin" -version = "0.4.10" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.5.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" [[package]] name = "strsim" diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index 0370610e16..908eaf5c0a 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -78,8 +78,8 @@ curve25519-dalek = { git = "https://github.com/mobilecoinfoundation/curve25519-d ed25519-dalek = { git = "https://github.com/mobilecoinfoundation/ed25519-dalek.git", rev = "4194e36abc75722e6fba7d552e719448fc38c51f" } # Our patches for newer bindgen, no-std -mbedtls = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } -mbedtls-sys-auto = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } +mbedtls = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } +mbedtls-sys-auto = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } # Fork and rename to use "OG" dalek-cryptography. schnorrkel-og = { git = "https://github.com/mobilecoinfoundation/schnorrkel.git", rev = "5c98ae068ee4652d6df6463b549fbf2d5d132faa" } diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index cd9eb3ec13..83482688d2 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -17,7 +17,7 @@ grpcio = "0.10.2" lazy_static = "1.4" prometheus = "0.13.0" retry = "1.3" -rocket = { version = "0.5.0-rc.1", features = ["json"] } +rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1" # mc diff --git a/fog/overseer/server/src/bin/main.rs b/fog/overseer/server/src/bin/main.rs index eabec6e9b4..9d82251806 100644 --- a/fog/overseer/server/src/bin/main.rs +++ b/fog/overseer/server/src/bin/main.rs @@ -42,5 +42,6 @@ async fn main() -> Result<(), rocket::Error> { .merge(("address", config.overseer_listen_host.clone())); let rocket = server::initialize_rocket_server(rocket_config, overseer_state); - rocket.launch().await + let _rocket = rocket.launch().await?; + Ok(()) } diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index c417dd0239..54025d355f 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -394,9 +394,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d916019f70ae3a1faa1195685e290287f39207d38e6dfee727197cffcc002214" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ "serde", "signature", @@ -645,7 +645,7 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "mbedtls" version = "0.8.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bitflags", "byteorder", @@ -657,14 +657,14 @@ dependencies = [ "rs-libc", "serde", "serde_derive", - "spin 0.4.10", + "spin 0.9.3", "yasna", ] [[package]] name = "mbedtls-sys-auto" version = "2.26.1" -source = "git+https://github.com/mobilecoinofficial/rust-mbedtls.git?rev=49a293a5f4b1ef571c71174e3fa1f301925f3915#49a293a5f4b1ef571c71174e3fa1f301925f3915" +source = "git+https://github.com/mobilecoinfoundation/rust-mbedtls.git?rev=ac6ee17a31e37311ce7f4fa0649c340e5d85258d#ac6ee17a31e37311ce7f4fa0649c340e5d85258d" dependencies = [ "bindgen", "cc", @@ -1749,15 +1749,15 @@ checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" [[package]] name = "spin" -version = "0.4.10" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.5.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" [[package]] name = "strsim" diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index 67b1acffdb..697d17fdd6 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -83,8 +83,8 @@ curve25519-dalek = { git = "https://github.com/mobilecoinfoundation/curve25519-d ed25519-dalek = { git = "https://github.com/mobilecoinfoundation/ed25519-dalek.git", rev = "4194e36abc75722e6fba7d552e719448fc38c51f" } # Our patches for newer bindgen, no-std -mbedtls = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } -mbedtls-sys-auto = { git = "https://github.com/mobilecoinofficial/rust-mbedtls.git", rev = "49a293a5f4b1ef571c71174e3fa1f301925f3915" } +mbedtls = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } +mbedtls-sys-auto = { git = "https://github.com/mobilecoinfoundation/rust-mbedtls.git", rev = "ac6ee17a31e37311ce7f4fa0649c340e5d85258d" } # Fork and rename to use "OG" dalek-cryptography. schnorrkel-og = { git = "https://github.com/mobilecoinfoundation/schnorrkel.git", rev = "5c98ae068ee4652d6df6463b549fbf2d5d132faa" } diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index c396ada83d..0ab23ea638 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -18,7 +18,7 @@ clap = { version = "3.1", features = ["derive", "env"] } grpcio = "0.10.2" hex = "0.4" protobuf = "2.27.1" -rocket = { version = "0.5.0-rc.1", features = ["json"] } +rocket = { version = "0.5.0-rc.2", features = ["json"] } serde = "1.0" serde_derive = "1.0" diff --git a/mobilecoind-json/src/bin/main.rs b/mobilecoind-json/src/bin/main.rs index 8f3b285dd2..8e2345de77 100644 --- a/mobilecoind-json/src/bin/main.rs +++ b/mobilecoind-json/src/bin/main.rs @@ -824,7 +824,7 @@ async fn main() -> Result<(), rocket::Error> { .merge(("port", config.listen_port)) .merge(("address", config.listen_host.clone())); - rocket::custom(figment) + let _rocket = rocket::custom(figment) .mount( "/", routes![ @@ -864,5 +864,6 @@ async fn main() -> Result<(), rocket::Error> { mobilecoind_api_client, }) .launch() - .await + .await?; + Ok(()) } From a7923603b53052782cf838d4389e14a040863891 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 19 May 2022 15:47:59 -0600 Subject: [PATCH 12/77] Make mobilecoind python able to load both root entropy and mnemonic accounts (#2013) We decided that we probably don't have to make it load the old non-b58 pub address file format, because we don't need it to be able to send to old accounts, only send from old accounts to new accounts. So we didn't change that. --- mobilecoind/strategies/accounts.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/mobilecoind/strategies/accounts.py b/mobilecoind/strategies/accounts.py index 39e72b4075..428723eb72 100644 --- a/mobilecoind/strategies/accounts.py +++ b/mobilecoind/strategies/accounts.py @@ -41,9 +41,17 @@ def connect(host, port): def register_account(key_data, stub) -> AccountData: # Generate an account key from this root entropy - resp = stub.GetAccountKeyFromMnemonic( - mobilecoind_api_pb2.GetAccountKeyFromMnemonicRequest( - mnemonic=key_data['mnemonic'])) + if 'mnemonic' in key_data: + resp = stub.GetAccountKeyFromMnemonic( + mobilecoind_api_pb2.GetAccountKeyFromMnemonicRequest( + mnemonic=key_data['mnemonic'])) + elif 'root_entropy' in key_data: + resp = stub.GetAccountKeyFromRootEntropy( + mobilecoind_api_pb2.GetAccountKeyFromRootEntropyRequest( + root_entropy=bytes(key_data['root_entropy']))) + else: + raise Exception('unknown key format') + account_key = resp.account_key # Add this account to the wallet From 0331a584eee53483f922f3e1bdf0932c3c415b95 Mon Sep 17 00:00:00 2001 From: Nick Santana Date: Thu, 19 May 2022 17:38:04 -0700 Subject: [PATCH 13/77] Feature/candidate 1 2 sgx 2 16 (#2018) * Feature/sgx 2 16 (#2011) * Update sgx to 2.16 * Update the docker image * Fix circle CI docker version * Update instruction in markdown Also add comment explaining order of command * Revert changelog entry Leveraging https://github.com/mobilecoinfoundation/mobilecoin/pull/2007 for the update --- .circleci/config.yml | 2 +- consensus/enclave/build.rs | 2 +- consensus/enclave/measurement/build.rs | 2 +- consensus/enclave/trusted/build.rs | 2 +- consensus/service/BUILD.md | 12 ++++++------ docker/Dockerfile-version | 2 +- docker/install_sgx.sh | 8 +++++--- fog/ingest/enclave/build.rs | 2 +- fog/ingest/enclave/measurement/build.rs | 2 +- fog/ingest/enclave/trusted/build.rs | 2 +- fog/ledger/enclave/build.rs | 2 +- fog/ledger/enclave/measurement/build.rs | 2 +- fog/ledger/enclave/trusted/build.rs | 2 +- fog/view/enclave/build.rs | 2 +- fog/view/enclave/measurement/build.rs | 2 +- fog/view/enclave/trusted/build.rs | 2 +- jenkins/build-pod.yaml | 2 +- ops/Dockerfile-consensus | 5 +++-- 18 files changed, 29 insertions(+), 26 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d192be9f7e..7cc3a88c30 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ version: 2.1 defaults: - builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_27 + builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_28 android-bindings-builder: &android-bindings-builder gcr.io/mobilenode-211420/android-bindings-builder:1_4 default-xcode-version: &default-xcode-version "12.0.0" diff --git a/consensus/enclave/build.rs b/consensus/enclave/build.rs index a87246f88a..052b7f7881 100644 --- a/consensus/enclave/build.rs +++ b/consensus/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/consensus/enclave/measurement/build.rs b/consensus/enclave/measurement/build.rs index 1443321dbb..8f98ae70b9 100644 --- a/consensus/enclave/measurement/build.rs +++ b/consensus/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; const CONSENSUS_ENCLAVE_PRODUCT_ID: u16 = 1; const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 3; diff --git a/consensus/enclave/trusted/build.rs b/consensus/enclave/trusted/build.rs index d91d3362a8..2ff60613e9 100644 --- a/consensus/enclave/trusted/build.rs +++ b/consensus/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/consensus/service/BUILD.md b/consensus/service/BUILD.md index c5f4f26255..81555f92e8 100644 --- a/consensus/service/BUILD.md +++ b/consensus/service/BUILD.md @@ -97,8 +97,8 @@ Recommended SDK and package installation: ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.15.100.3.bin" - wget "https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.0_2d2b795.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -108,12 +108,12 @@ wget -O- https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | \ gpg --dearmor > /etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg # Install the EPID/OOT kernel driver -chmod +x ./sgx_linux_x64_driver_2.11.0_2d2b795.bin -./sgx_linux_x64_driver_2.11.0_2d2b795.bin +chmod +x ./sgx_linux_x64_driver_2.11.054c9c4c.bin +./sgx_linux_x64_driver_2.11.054c9c4c.bin # Install the SDK to /opt/intel/sgxsdk -chmod +x ./sgx_linux_x64_sdk_2.15.100.3.bin -./sgx_linux_x64_sdk_2.15.100.3.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.16.100.4.bin +./sgx_linux_x64_sdk_2.16.100.4.bin --prefix=/opt/intel apt install libsgx-uae-service sgx-aesm-service diff --git a/docker/Dockerfile-version b/docker/Dockerfile-version index 9d6e30e0f8..0678f6effd 100644 --- a/docker/Dockerfile-version +++ b/docker/Dockerfile-version @@ -1 +1 @@ -1_27 +1_28 diff --git a/docker/install_sgx.sh b/docker/install_sgx.sh index e11d7982cb..7f39665521 100644 --- a/docker/install_sgx.sh +++ b/docker/install_sgx.sh @@ -24,7 +24,7 @@ cd /tmp ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.15.100.3.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -57,8 +57,10 @@ apt-get install -yq --no-install-recommends \ libsgx-uae-service \ sgx-aesm-service -chmod +x ./sgx_linux_x64_sdk_2.15.100.3.bin -./sgx_linux_x64_sdk_2.15.100.3.bin --prefix=/opt/intel +# Install *after* pkg-config so that they get registered correctly. +# pkg-config gets pulled in transitively via build-essential +chmod +x ./sgx_linux_x64_sdk_2.16.100.4.bin +./sgx_linux_x64_sdk_2.16.100.4.bin --prefix=/opt/intel # Update .bashrc to source sgxsdk echo 'source /opt/intel/sgxsdk/environment' >> /root/.bashrc diff --git a/fog/ingest/enclave/build.rs b/fog/ingest/enclave/build.rs index 1b29fe6200..26c06202d7 100644 --- a/fog/ingest/enclave/build.rs +++ b/fog/ingest/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/ingest/enclave/measurement/build.rs b/fog/ingest/enclave/measurement/build.rs index a553afcbee..d43097ebc6 100644 --- a/fog/ingest/enclave/measurement/build.rs +++ b/fog/ingest/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; const INGEST_ENCLAVE_PRODUCT_ID: u16 = 4; const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 2; diff --git a/fog/ingest/enclave/trusted/build.rs b/fog/ingest/enclave/trusted/build.rs index 7fb562241c..2622ad4ec6 100644 --- a/fog/ingest/enclave/trusted/build.rs +++ b/fog/ingest/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/build.rs b/fog/ledger/enclave/build.rs index f5e2f6fd4a..004600e660 100644 --- a/fog/ledger/enclave/build.rs +++ b/fog/ledger/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/measurement/build.rs b/fog/ledger/enclave/measurement/build.rs index 0f7552e6a8..60f8d390b6 100644 --- a/fog/ledger/enclave/measurement/build.rs +++ b/fog/ledger/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; const LEDGER_ENCLAVE_PRODUCT_ID: u16 = 2; const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 2; diff --git a/fog/ledger/enclave/trusted/build.rs b/fog/ledger/enclave/trusted/build.rs index ae51154dff..8509981de6 100644 --- a/fog/ledger/enclave/trusted/build.rs +++ b/fog/ledger/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/build.rs b/fog/view/enclave/build.rs index b4db347369..04748228e8 100644 --- a/fog/view/enclave/build.rs +++ b/fog/view/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/measurement/build.rs b/fog/view/enclave/measurement/build.rs index d8ba4e9dab..9fa7be5e2f 100644 --- a/fog/view/enclave/measurement/build.rs +++ b/fog/view/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; const VIEW_ENCLAVE_PRODUCT_ID: u16 = 3; const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 2; diff --git a/fog/view/enclave/trusted/build.rs b/fog/view/enclave/trusted/build.rs index 00d3b4f66a..b03145862c 100644 --- a/fog/view/enclave/trusted/build.rs +++ b/fog/view/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.15.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/jenkins/build-pod.yaml b/jenkins/build-pod.yaml index e4a8432039..9883127c08 100644 --- a/jenkins/build-pod.yaml +++ b/jenkins/build-pod.yaml @@ -20,7 +20,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: rust-builder-default - image: gcr.io/mobilenode-211420/builder-install:1_27 + image: gcr.io/mobilenode-211420/builder-install:1_28 env: - name: PATH value: "/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64" diff --git a/ops/Dockerfile-consensus b/ops/Dockerfile-consensus index 90dc45d739..3035f4e70a 100644 --- a/ops/Dockerfile-consensus +++ b/ops/Dockerfile-consensus @@ -19,8 +19,9 @@ RUN apt-get update -q -q && \ # Install SGX Ubuntu/Debian Repo RUN source /etc/os-release && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.0_2d2b795.bin" && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.15.100.3.bin" && \ + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" && \ + + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" && \ echo "deb [arch=amd64 signed-by=/usr/local/share/apt-keyrings/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list RUN mkdir -p /usr/local/share/apt-keyrings && \ From 8ca1fb533f0b093831eb09d2bcf1ad798b237d63 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 19 May 2022 21:56:06 -0600 Subject: [PATCH 14/77] make test-client and fog-distro able to read keyfiles in both formats (#2019) * make test-client and fog-distro able to read keyfiles in both formats * clippy --- fog/distribution/src/main.rs | 4 ++-- fog/test-client/src/config.rs | 2 +- util/keyfile/src/keygen.rs | 24 ++++++++++++++---------- util/keyfile/src/lib.rs | 30 ++++++++++++++++++++++++++---- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/fog/distribution/src/main.rs b/fog/distribution/src/main.rs index 02c348fb40..2ac3410eb8 100755 --- a/fog/distribution/src/main.rs +++ b/fog/distribution/src/main.rs @@ -122,12 +122,12 @@ fn main() { let config = Config::parse(); // Read account keys from disk - let src_accounts: Vec = mc_util_keyfile::keygen::read_default_mnemonics( + let src_accounts: Vec = mc_util_keyfile::keygen::read_default_keyfiles( config.sample_data_dir.join(Path::new("keys")), ) .expect("Could not read default mnemonics from keys"); - let dest_accounts: Vec = mc_util_keyfile::keygen::read_default_mnemonics( + let dest_accounts: Vec = mc_util_keyfile::keygen::read_default_keyfiles( config .sample_data_dir .join(Path::new(&config.fog_keys_subdir)), diff --git a/fog/test-client/src/config.rs b/fog/test-client/src/config.rs index a416480aca..ebd241bd03 100644 --- a/fog/test-client/src/config.rs +++ b/fog/test-client/src/config.rs @@ -140,7 +140,7 @@ impl TestClientConfig { // Load the key files log::info!(logger, "Loading account keys from {:?}", key_dir); - mc_util_keyfile::keygen::read_default_mnemonics(&key_dir) + mc_util_keyfile::keygen::read_default_keyfiles(&key_dir) .unwrap() .into_iter() .take(self.num_clients) diff --git a/util/keyfile/src/keygen.rs b/util/keyfile/src/keygen.rs index d958301320..e19acb05ca 100644 --- a/util/keyfile/src/keygen.rs +++ b/util/keyfile/src/keygen.rs @@ -112,8 +112,8 @@ pub fn read_default_pubfiles>(path: P) -> Result>(path: P) -> Result, Error> { +/// Get default keyfile paths +pub fn get_default_keyfile_paths>(path: P) -> Result, Error> { let mut entries = Vec::new(); for entry in fs::read_dir(path)? { let filename = entry?.path(); @@ -127,7 +127,7 @@ pub fn read_default_keyfiles>(path: P) -> Result, Er /// Read default mnemonic keyfiles pub fn read_default_mnemonics>(path: P) -> Result, Error> { - read_default_keyfiles(path)? + get_default_keyfile_paths(path)? .into_iter() .map(read_keyfile) .collect() @@ -136,12 +136,20 @@ pub fn read_default_mnemonics>(path: P) -> Result /// Read default root entropies #[deprecated] pub fn read_default_root_entropies>(path: P) -> Result, Error> { - read_default_keyfiles(path)? + get_default_keyfile_paths(path)? .into_iter() .map(read_root_entropy_keyfile) .collect() } +/// Read default key files in either format +pub fn read_default_keyfiles>(path: P) -> Result, Error> { + get_default_keyfile_paths(path)? + .into_iter() + .map(read_keyfile) + .collect() +} + // This comparator is used when sorting the files so that the i'th keyfile // written is also the i'th keyfile in the vector that is returned when reading // @@ -273,12 +281,8 @@ mod test { write_default_keyfiles(&dir1, 10, None, "", None, DEFAULT_SEED) .expect("Could not write example keyfiles"); - let mut actual = read_default_keyfiles(&dir1) - .expect("Could not read default keyfiles dir") - .into_iter() - .map(read_keyfile) - .collect::, Error>>() - .expect("Could not read keyfiles just written"); + let mut actual = + read_default_keyfiles(&dir1).expect("Could not read keyfiles just written"); actual.sort(); assert_eq!(expected, actual); diff --git a/util/keyfile/src/lib.rs b/util/keyfile/src/lib.rs index 6e6f5217a1..8dfc78b087 100644 --- a/util/keyfile/src/lib.rs +++ b/util/keyfile/src/lib.rs @@ -16,7 +16,7 @@ use bip39::Mnemonic; use mc_account_keys::{AccountKey, PublicAddress, RootIdentity}; use mc_api::printable::PrintableWrapper; use std::{ - convert::TryInto, + convert::{TryFrom, TryInto}, fs::File, io::{Read, Write}, path::Path, @@ -53,14 +53,36 @@ pub fn read_root_entropy_keyfile_data(buffer: R) -> Result(buffer)?.into()) } -/// Read user root identity from disk +/// Read user mnemonic from disk +pub fn read_mnemonic_keyfile>(path: P) -> Result { + read_mnemonic_keyfile_data(File::open(path)?) +} + +/// Read user root identity from any implementor of `Read` +pub fn read_mnemonic_keyfile_data(buffer: R) -> Result { + Ok(serde_json::from_reader::(buffer)?.try_into()?) +} + +/// Read an account either in the RootIdentity format or the mnemonic format +/// from disk pub fn read_keyfile>(path: P) -> Result { read_keyfile_data(File::open(path)?) } -/// Read user root identity from any implementor of `Read` +/// Read an account key file in either format pub fn read_keyfile_data(buffer: R) -> Result { - Ok(serde_json::from_reader::(buffer)?.try_into()?) + let value = serde_json::from_reader::(buffer)?; + let obj = value + .as_object() + .ok_or_else(|| Error::Json("Expected json object".to_string()))?; + if obj.contains_key("root_entropy") { + let root_identity_json: RootIdentityJson = serde_json::from_value(value)?; + let root_id = RootIdentity::from(root_identity_json); + Ok(AccountKey::from(&root_id)) + } else { + let mnemonic_json: UncheckedMnemonicAccount = serde_json::from_value(value)?; + Ok(AccountKey::try_from(mnemonic_json)?) + } } /// Write user public address to disk From 063ee079a3b5f476654e5d00891ec174363812de Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 20 May 2022 11:51:35 -0700 Subject: [PATCH 15/77] Bump enclave security versions. (#2022) --- consensus/enclave/measurement/build.rs | 2 +- fog/ingest/enclave/measurement/build.rs | 2 +- fog/ledger/enclave/measurement/build.rs | 2 +- fog/view/enclave/measurement/build.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/consensus/enclave/measurement/build.rs b/consensus/enclave/measurement/build.rs index 8f98ae70b9..41279130fd 100644 --- a/consensus/enclave/measurement/build.rs +++ b/consensus/enclave/measurement/build.rs @@ -13,7 +13,7 @@ use std::{env::var, path::PathBuf}; const SGX_VERSION: &str = "2.16.100.4"; const CONSENSUS_ENCLAVE_PRODUCT_ID: u16 = 1; -const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 3; +const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 4; const CONSENSUS_ENCLAVE_NAME: &str = "consensus-enclave"; const CONSENSUS_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/ingest/enclave/measurement/build.rs b/fog/ingest/enclave/measurement/build.rs index d43097ebc6..c978fc67e9 100644 --- a/fog/ingest/enclave/measurement/build.rs +++ b/fog/ingest/enclave/measurement/build.rs @@ -13,7 +13,7 @@ use std::{env::var, path::PathBuf}; const SGX_VERSION: &str = "2.16.100.4"; const INGEST_ENCLAVE_PRODUCT_ID: u16 = 4; -const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 2; +const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 3; const INGEST_ENCLAVE_NAME: &str = "ingest-enclave"; const INGEST_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/ledger/enclave/measurement/build.rs b/fog/ledger/enclave/measurement/build.rs index 60f8d390b6..46f7402fc0 100644 --- a/fog/ledger/enclave/measurement/build.rs +++ b/fog/ledger/enclave/measurement/build.rs @@ -13,7 +13,7 @@ use std::{env::var, path::PathBuf}; const SGX_VERSION: &str = "2.16.100.4"; const LEDGER_ENCLAVE_PRODUCT_ID: u16 = 2; -const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 2; +const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 3; const LEDGER_ENCLAVE_NAME: &str = "ledger-enclave"; const LEDGER_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/view/enclave/measurement/build.rs b/fog/view/enclave/measurement/build.rs index 9fa7be5e2f..0ce0f08c21 100644 --- a/fog/view/enclave/measurement/build.rs +++ b/fog/view/enclave/measurement/build.rs @@ -13,7 +13,7 @@ use std::{env::var, path::PathBuf}; const SGX_VERSION: &str = "2.16.100.4"; const VIEW_ENCLAVE_PRODUCT_ID: u16 = 3; -const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 2; +const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 3; const VIEW_ENCLAVE_NAME: &str = "view-enclave"; const VIEW_ENCLAVE_DIR: &str = "../trusted"; From f44789181c2865ec82f766fd0b5655814e29feac Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 20 May 2022 14:49:25 -0700 Subject: [PATCH 16/77] Update Changelog and Versions (#2007) * Update version to 1.2.0-pre0 * Update changelog for 1.2.0 * Merge in fog 1.1.3 changelog, make links work. * Apply suggestions from code review Co-authored-by: Eran Rundstein * Fix some links, Postgres vs. PostGRES * Address review comments. * Fiddle with a link. * Fix links * Update CHANGELOG.md Co-authored-by: Remoun Metyas * Apply suggestions from code review Co-authored-by: Chris Beck Co-authored-by: Remoun Metyas * Apply suggestions from code review (this will require a follow-up commit to fix links) Co-authored-by: Remoun Metyas * Fix links (and typo). Co-authored-by: Eran Rundstein Co-authored-by: Remoun Metyas Co-authored-by: Chris Beck --- CHANGELOG.md | 559 +++++++++++++++++--- Cargo.lock | 322 +++++------ account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- common/Cargo.toml | 2 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 ++-- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 ++-- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 ++-- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 ++-- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 2 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 2 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 177 files changed, 1027 insertions(+), 592 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ae311b43c..d599bbf11a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,78 +5,513 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The crates in this repository do not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) at this time. -## Unreleased -### Added -- Support env overrides for ~all command-line flags. - - Flags that take multiple values can be repeated on the command line, - or passed as comma-separated values via environment or command-line args. - -### Changed -### Rust Dependencies -* Updated `rust-toolchain` version to newer nightly - * enables use of [Generic Associated Types](https://github.com/rust-lang/rust/issues/44265) and [static async fn in traits](https://github.com/rust-lang/rust/issues/91611) -* Replaced `datatest` with a custom `test_with_data` macro. -* Replace `structopt` with `clap`. -* Updated grpcio from 0.9 to 0.10. - -## [1.2.0] +## [1.2.0-pre1] - 2022-05-20 ### Added - - Encrypted Memos ([MCIP #3](https://github.com/mobilecoinfoundation/mcips/pull/3)) - - Recoverable Transaction History ([MCIP #4](https://github.com/mobilecoinfoundation/mcips/pull/4)) - - Consensus/Fog repository merge +- Fog is now part of this repository +- Fog Ledger key image checks are now oblivious ([fog #101](https://github.com/mobilecoinfoundation/fog/pull/101)) +- Fog View OMAP size configurable via environment +- Fog Overseer utility for monitoring Fog Ingest instances +- Fog Ingest Client CLI now allows queries to the `get_ingress_key_record` API +- Block versioning / protocol evolution ([MCIP #26]) +- In Block Version 1 (to be enabled along with block version 2): + - Required Transaction Memos ([MCIP #3]) + - Recoverable Transaction History ([MCIP #4]) +- In Block Version 2 (to be enabled after network has been upgraded): + - Confidential Multi-Token Support ([MCIP #25]) + - Minting support for non-MOB tokens ([MCIP #37]) + - Verifiable burning for any token ([MCIP #35]) + - Standardized Addresses for common purposes ([MCIP #36]) +- In Block Version 3 (will be enabled in a future release): + - Require TxOuts to be sorted in TxProposal ([MCIP #34]). ### Changed - - Updated SGX to 2.15 - - Lock enclave no-debug mode when building for IAS production. - - Update Rust toolchain to `nightly-2021-07-21`. +- Enable `Bitcode` for `libmobilecoin`, reduce mobile artifact size by ~25% ([#1124]) +- mobilecoind will now exit on startup when a ledger migration is necessary, unless the new `--ledger-db-migrate` command line argument is used, in which case it will migrate automatically. This flag does not do anything if the Ledger DB does not exist. +- Bump SGX versions to 2.16. ([#1101], [#2018]) + +#### Python + +- Bump `ipython` from 7.8.0 to 7.16.3 ([#1333]) +- Bump `protobuf` from 3.10.0 to 3.15.0 ([#1477]) + +#### Rust + +- Upgrade rust toolchain to `nightly-2022-04-29` ([#1613], [#1888]) +- Replace `datatest` with a custom `test_with_data` attribute macro ([#1556]) +- Replace `structopt` with `clap`, and add support for env overrides for all flags ([#1541]) + +- Fork `bulletproofs` to `bulletproofs-og` to use dalek upstream, fix clippy issues from upstream. +- Fork `cpufeatures` to disable `CPUID` usage, use fork in enclaves (cargo bug prevents upstreaming) +- Fork `opentelemetry` to update some of its dependencies. ([#1918]) +- Fork `schnorrkel` to `schnorrkel-og`, to use dalek upstream +- Unfork `aes-gcm` and update to 0.9.2, use forked `mc-oblivious-aes-gcm` crate in the Fog hint decryption routines +- Unfork `cpuid-bool`, not used anymore +- Unfork `grpcio` and bump from 0.6 to 0.10.3. ([#1592], [#1717], [#1814]) +- Unfork `prost` from bump from 0.8.0 to 0.10.3 ([#898], [#1109], [#1728], [#1805], [#1806], [#1807], [#1808], [#1809], [#1926], [#1927], [#1929], [#1930]) +- Update `cmake` fork to git-5f89f90ee5d7789832963bffdb2dcb5939e6199c +- Update `curve25519-dalek` fork from 4.0.0-pre.0 to 4.0.0-pre.2 +- Update `ed25519-dalek` fork to support new rust nightlies +- Update `mbedtls`, `mbedtls-sys` forks to support newer rust nightlies, use newer `spin` +- Update `x25519-dalek` fork to support newer rust nightlies + +- Bump `aead` from 0.3.2 to 0.4.3 ([#1389]) +- Bump `aes-gcm` from 0.9.2 to 0.9.4 +- Bump `aes` from 0.7.4 to 0.7.5 +- Bump `anyhow` from 1.0.39 to 1.0.57 ([#1013], [#1146], [#1265], [#1341], [#1529], [#1578], [#1837]) +- Bump `arrayvec` from 0.5.2 to 0.7.1 ([#980]) +- Bump `assert_cmd` from 2.0.2 to 2.0.4 ([#1314]) +- Bump `backtrace` from 0.3.55 to 0.3.65 ([#982], [#1143], [#1392], [#1817]) +- Bump `base64` from 0.12.3 to 0.13.0 +- Bump `bincode` from 1.3.1 to 1.3.3 ([#1056]) +- Bump `bindgen` from 0.51.1 to 0.59.2 +- Bump `bitflags` from 1.2.1 to 1.3.2 ([#1016]) +- Bump `blake2` from 0.9.1 to 0.10.4 ([#1520]) +- Bump `bs58` from 0.3.1 to 0.4.0 ([#948]) +- Bump `cargo-emit` from 0.1.1 to 0.2.1 ([#1045], [#990], [#1000], [#937], [#968]) +- Bump `cargo_metadata` from 0.9.1 to 0.14.2 ([#949], [#1135], [#1502]) +- Bump `cbindgen` from 0.14.3 to 0.23.0 ([#1020], [#1702], [#1824], [#1836]) +- Bump `cc` from 1.0.66 to 1.0.73 ([#919], [#920], [#983], [#985], [#1094], [#1095], [#1096], [#1097], [#1099], [#1164], [#1165], [#1166], [#1167], [#1168], [#1497], [#1498], [#1499], [#1500], [#1501]) +- Bump `cfg-if` from 0.1.10 to 1.0.0 +- Bump `chrono` from 0.4.11 to 0.4.19 ([#959]) +- Bump `clap` from 3.1.6 to 3.1.18 ([#1762], [#1825], [#1847], [#1904], [#1957]) +- Bump `cookie` from 0.14.3 to 0.16.0 ([#1034], [#1271]) +- Bump `crc` from 1.8.1 to 2.0.0 ([#1018], [#1138], [#1857]) +- Bump `criterion` from 0.3.2 to 0.3.5 ([#1059]) +- Bump `crossbeam-channel` from 0.5.0 to 0.5.4 ([#1039], [#1313], [#1678]) +- Bump `diesel-derive-enum` from 1.1.1 to 1.1.2 ([#1311]) +- Bump `diesel` from 1.4.7 to 1.4.8 ([#1061]) +- Bump `digest` from 0.9.0 to 0.10.1 +- Bump `dirs` from 2.0.2 to 4.0.0 ([#1071]) +- Bump `displaydoc` from 0.2.0 to 0.2.3 ([#936], [#933], [#995]) +- Bump `ed25519` from 1.0.1 to 1.5.0 ([#1179], [#1679], [#1950]) +- Bump `futures` from 0.3.8 to 0.3.21 ([#1017], [#1262], [#1458]) +- Bump `generic-array` from 0.14.4 to 0.14.5 ([#1315]) +- Bump `getrandom` from 0.1.13, 0.2.2 to 0.2.6 ([#986], [#1052], [#1031], [#1310], [#1387], [#1532], [#1531], [#1714], [#1712]) +- Bump `ghash` from 0.4.2 to 0.4.4 +- Bump `hashbrown` from 0.6.3 to 0.12.1 ([#899], [#1915]) +- Bump `hex` from 0.4.2 to 0.4.3 ([#1006], [#923], [#909], [#975], [#913]) +- Bump `hkdf` from 0.9.0 to 0.12.3 ([#1345]) +- Bump `hmac` from 0.7.1 to 0.12.1 ([#660], [#1345]) +- Bump `hostname` from 0.1.5 to 0.3.1 ([#902]) +- Bump `itertools` from 0.10.1 to 0.10.3 ([#1200]) +- Bump `jni` from 0.16.0 to 0.19.0 ([#1012]) +- Bump `libc` from 0.2.97 to 0.2.125 ([#1007], [#1070], [#1112], [#1134], [#1141], [#1159], [#1239], [#1348], [#1365], [#1391], [#1492], [#1525], [#1676], [#1782], [#1826], [#1887]) +- Bump `libz-sys` from 1.1.4 to 1.1.6 ([#1591], [#1873]) +- Bump `link-cplusplus` from 1.0.5 to 1.0.6 ([#1171]) +- Bump `mockall` from 0.8.3 to 0.11.0 ([#956], [#1240]) +- Bump `more-asserts` from 0.2.1 to 0.2.2 ([#1174]) +- Bump `nix` from 0.18.0 to 0.22.1 ([#1022]) +- Bump `num_cpus` from 1.13.0 to 1.13.1 ([#1261]) +- Bump `once_cell` from 1.5.2 to 1.9.0 ([#998], [#1249]) +- Bump `packed_simd_2` from 0.3.4 to 0.3.7 +- Bump `pem` from 0.8.2 to 0.8.3 ([#957], [#1087], [#1131], [#1279]) +- Bump `pkg-config` from 0.3.17 to 0.3.25 ([#915], [#925], [#965], [#967], [#1033], [#1072], [#1066], [#1067], [#1068], [#1069], [#1125], [#1126], [#1127], [#1128], [#1133], [#1235], [#1236], [#1237], [#1238], [#1241], [#1750], [#1751], [#1752], [#1753], [#1755]) +- Bump `polyval` from 0.5.1 to 0.5.3 +- Bump `predicates` from 1.0.5 to 2.1.1 ([#1142], [#1306]) +- Bump `proc-macro2` from 1.0.24 to 1.0.38 ([#1104], [#1130], [#1268], [#1777], [#1938]) +- Bump `prometheus` from 0.9.0 to 0.13.0 ([#1002], [#1079]) +- Bump `proptest` from 0.10.1 to 1.0.0 ([#952]) +- Bump `protobuf` from 2.22.1 to 2.27.1 ([#1754]) +- Bump `quote` from 0.6.13 to 1.0.18 ([#1092], [#1355], [#1677], [#1716], [#1795]) +- Bump `rand_chacha` from 0.3.0 to 0.3.1 ([#1057]) +- Bump `rand_core` from 0.6.2 to 0.6.3 ([#921], [#930], [#947], [#977], [#1046]) +- Bump `rand_hc` from 0.3.0 to 0.3.1 ([#916], [#972], [#976], [#988], [#1019]) +- Bump `rand` from 0.8.3 to 0.8.5 ([#911], [#914], [#928], [#999], [#1041], [#1484], [#1485], [#1486], [#1487], [#1489]) +- Bump `rayon` from 1.3.0 to 1.5.2 ([#992], [#1050], [#1812], [#1812]) +- Bump `regex` from 1.3.7 to 1.5.5 ([#1432], [#1590]) +- Bump `reqwest` from 0.10.6 to 0.10.10 ([#1054], [#1622]) +- Bump `retry` from 1.2.0 to 1.3.0 ([#1036]) +- Bump `rocket` from 0.4.6 to 0.5.0-rc2 +- Bump `rusoto_s3` from 0.42 to 0.48. ([#1912]) +- Bump `secrecy` from 0.4.1 to 0.8.0 ([#950], [#1043]) +- Bump `semver` from 0.11.0 to 1.0.9 ([#1459], [#1528], [#1715], [#1900]) +- Bump `sentry` from 0.24.3 to 0.25.0 ([#1563]) +- Bump `serde_json` from 1.0.60 to 1.0.81 ([#1023], [#1155], [#1170], [#1278], [#1322], [#1344], [#1488], [#1916]) +- Bump `serde` from 1.0.118 to 1.0.137 ([#939], [#940], [#941], [#991], [#996], [#1273], [#1274], [#1275], [#1276], [#1277], [#1350], [#1351], [#1363], [#1383], [#1386], [#1894], [#1895], [#1897], [#1901], [#1903]) +- Bump `serial_test_derive` from 0.5.0 to 0.5.1 ([#1001]) +- Bump `serial_test` from 0.5.0 to 0.5.1 ([#1044]) +- Bump `sha2` from 0.8.1 to 0.10.2 ([#1512], [#1509]) +- Bump `sha3` from 0.9.1 to 0.10.0 +- Bump `signal-hook` from 0.3.4 to 0.3.13 ([#1008], [#1263]) +- Bump `signature` from 0.2.2 to 1.4.0 ([#1115]) +- Bump `siphasher` from 0.3.1 to 0.3.10 ([#942], [#1003], [#1321], [#1579]) +- Bump `slog-async` from 2.5.0 to 2.7.0 ([#1060]) +- Bump `slog-atomic` from 3.0.0 to 3.1.0 ([#1010]) +- Bump `slog-json` from 2.3.0 to 2.6.1 ([#978], [#1343], [#1757]) +- Bump `slog-json` from 2.3.0 to 2.4.0 +- Bump `slog-scope` from 4.3.0 to 4.4.0 ([#1049]) +- Bump `slog-stdlog` from 4.1.0 to 4.1.1 ([#1692]) +- Bump `slog-term` from 2.6.0 to 2.8.0 ([#1042], [#1524]) +- Bump `subtle` from 1.0.0 to 2.4.1 +- Bump `syn` from 0.15.44 to 1.0.94 ([#979], [#1064], [#1090], [#1098], [#1132], [#1291], [#1332], [#1642], [#1713], [#1776], [#1886], [#1956], [#1976]) +- Bump `tempfile` from 3.2.0 to 3.3.0 ([#1758]) +- Bump `tiny-bip39` from 0.8.0 to 0.8.2 ([#1053], [#1080]) +- Bump `toml` from 0.5.7 to 0.5.9 ([#1011], [#1815]) +- Bump `url` from 2.1.1 to 2.2.2 ([#951]) +- Bump `walkdir` from 2.3.1 to 2.3.2 ([#997], [#962], [#931], [#974], [#922]) +- Bump `yaml-rust` from 0.4.4 to 0.4.5 ([#993]) +- Bump `zeroize` from 1.2.0 to 1.5.5 ([#908], [#1027], [#1028], [#1029], [#1156], [#1360], [#1366], [#1656], [#1896], [#1898], [#1899], [#1902]) + +### Removed + +- The `slam` test utility, in favor of `fog-distribution` ([#1611]) +- Support for root entropy-based key derivation in test keys/ledgers ([#1893]) +- The `pretty_assertions` dependency ([#1055], [#1078], [#1431], [#1610], [#1657]) -#### Rust Dependencies +### Fixed + +- Fog ingest state file handling is more resilient ([#1358]) +- Fog services sometimes returned the wrong grpc error code for attestation failures +- Added retries for connectivity issues with Postgres database in Fog services + +### Security - - Update `aead` to 0.4.1. - - Update `aes-gcm` to 0.9.2. - - Update `base64` to 0.13.0. - - Update `bindgen` to 0.58.1. - - Update `blake2` to 0.9.2. - - Update `cc` to 1.0.70. - - Update `cfg-if` to 1.0.0. - - Update `cmake` to unreleased github with iOS fixes. - - Update `curve25519-dalek` to 4.0.0-pre1. - - Update `displaydoc` to 0.2.3. - - Update `hashbrown` to 0.11.2. - - Update `hmac` to 0.11.0. - - Update `hostname` to 0.3.1. - - Update `packed_simd_2` to unreleased github with nightly fixes. - - Update `proc-macros2` to 1.0.29. - - Update `quote` to 1.0.9. - - Update `rocket` to 0.4.10. - - Update `semver` to 1.0.4. - - Update `sha2` to 0.9.5. - - Update `subtle` to 2.4.1. - - Update `syn` to 1.0.67. - - Remove `failure` in favor of `displaydoc`. - -#### Rust Crate Forks - - - Fork `bulletproofs` to `bulletproofs-og` to use dalek upstream, fix clippy issues from upstream. - - Fork `cpufeatures` to disable `CPUID` usage, use fork in enclaves (cargo bug prevents upstreaming). - - Fork `schnorrkel` to `schnorrkel-og`, to use dalek upstream. - - Fork `aes-gcm` to `mc-oblivious-aes-gcm` for oblivious decryption support, use where necessary. - - - Update `cmake` fork to fix iOS builds. - - Update `datatest` to support newer rust nightlies. - - Update `ed25519-dalek` fork to support new rust nightlies. - - Update `grpcio` fork to 0.9 base. - - Update `mbedtls`, `mbedtls-sys` forks to support newer rust nightlies. - - Update `x25519-dalek` fork to support newer rust nightlies. - - - Unfork `aes-gcm` and update to 0.9.2, use forked `mc-oblivious-aes-gcm` crate in the Fog hint decryption routines. - - Unfork `cpuid-bool`, not used anymore - - Unfork `prost` and update to 0.8.0. +- Fixed a problem with data authentication in the Fog OCALL Oram Storage interface (Thanks to [@AmbitionXiang] for reporting!, [#1576]) + +[MCIP #3]: https://github.com/mobilecoinfoundation/mcips/blob/main/text/0003-encrypted-memos.md +[MCIP #4]: https://github.com/mobilecoinfoundation/mcips/blob/main/text/0004-recoverable-transaction-history.md +[MCIP #25]: https://github.com/mobilecoinfoundation/mcips/blob/main/text/0025-confidential-token-ids.md +[MCIP #26]: https://github.com/mobilecoinfoundation/mcips/blob/main/text/0026-block-version-based-protocol-evolution.md +[MCIP #34]: https://github.com/mobilecoinfoundation/mcips/blob/main/text/0034-sorted-transaction-outputs.md +[MCIP #35]: https://github.com/mobilecoinfoundation/mcips/blob/main/text/0035-verifiable-burning.md +[MCIP #36]: https://github.com/mobilecoinfoundation/mcips/blob/main/text/0036-reserved-subaddresses.md +[MCIP #37]: https://github.com/mobilecoinfoundation/mcips/blob/main/text/0036-reserved-subaddresses.md +[#660]: https://github.com/mobilecoinfoundation/mobilecoin/pull/660 +[#898]: https://github.com/mobilecoinfoundation/mobilecoin/pull/898 +[#899]: https://github.com/mobilecoinfoundation/mobilecoin/pull/899 +[#902]: https://github.com/mobilecoinfoundation/mobilecoin/pull/902 +[#908]: https://github.com/mobilecoinfoundation/mobilecoin/pull/908 +[#909]: https://github.com/mobilecoinfoundation/mobilecoin/pull/909 +[#911]: https://github.com/mobilecoinfoundation/mobilecoin/pull/911 +[#913]: https://github.com/mobilecoinfoundation/mobilecoin/pull/913 +[#914]: https://github.com/mobilecoinfoundation/mobilecoin/pull/914 +[#915]: https://github.com/mobilecoinfoundation/mobilecoin/pull/915 +[#916]: https://github.com/mobilecoinfoundation/mobilecoin/pull/916 +[#919]: https://github.com/mobilecoinfoundation/mobilecoin/pull/919 +[#920]: https://github.com/mobilecoinfoundation/mobilecoin/pull/920 +[#921]: https://github.com/mobilecoinfoundation/mobilecoin/pull/921 +[#922]: https://github.com/mobilecoinfoundation/mobilecoin/pull/922 +[#923]: https://github.com/mobilecoinfoundation/mobilecoin/pull/923 +[#925]: https://github.com/mobilecoinfoundation/mobilecoin/pull/925 +[#928]: https://github.com/mobilecoinfoundation/mobilecoin/pull/928 +[#930]: https://github.com/mobilecoinfoundation/mobilecoin/pull/930 +[#931]: https://github.com/mobilecoinfoundation/mobilecoin/pull/931 +[#933]: https://github.com/mobilecoinfoundation/mobilecoin/pull/933 +[#936]: https://github.com/mobilecoinfoundation/mobilecoin/pull/936 +[#937]: https://github.com/mobilecoinfoundation/mobilecoin/pull/937 +[#939]: https://github.com/mobilecoinfoundation/mobilecoin/pull/939 +[#940]: https://github.com/mobilecoinfoundation/mobilecoin/pull/940 +[#941]: https://github.com/mobilecoinfoundation/mobilecoin/pull/941 +[#942]: https://github.com/mobilecoinfoundation/mobilecoin/pull/942 +[#947]: https://github.com/mobilecoinfoundation/mobilecoin/pull/947 +[#948]: https://github.com/mobilecoinfoundation/mobilecoin/pull/948 +[#949]: https://github.com/mobilecoinfoundation/mobilecoin/pull/949 +[#950]: https://github.com/mobilecoinfoundation/mobilecoin/pull/950 +[#951]: https://github.com/mobilecoinfoundation/mobilecoin/pull/951 +[#952]: https://github.com/mobilecoinfoundation/mobilecoin/pull/952 +[#956]: https://github.com/mobilecoinfoundation/mobilecoin/pull/956 +[#957]: https://github.com/mobilecoinfoundation/mobilecoin/pull/957 +[#959]: https://github.com/mobilecoinfoundation/mobilecoin/pull/959 +[#962]: https://github.com/mobilecoinfoundation/mobilecoin/pull/962 +[#965]: https://github.com/mobilecoinfoundation/mobilecoin/pull/965 +[#967]: https://github.com/mobilecoinfoundation/mobilecoin/pull/967 +[#968]: https://github.com/mobilecoinfoundation/mobilecoin/pull/968 +[#972]: https://github.com/mobilecoinfoundation/mobilecoin/pull/972 +[#974]: https://github.com/mobilecoinfoundation/mobilecoin/pull/974 +[#975]: https://github.com/mobilecoinfoundation/mobilecoin/pull/975 +[#976]: https://github.com/mobilecoinfoundation/mobilecoin/pull/976 +[#977]: https://github.com/mobilecoinfoundation/mobilecoin/pull/977 +[#978]: https://github.com/mobilecoinfoundation/mobilecoin/pull/978 +[#979]: https://github.com/mobilecoinfoundation/mobilecoin/pull/979 +[#980]: https://github.com/mobilecoinfoundation/mobilecoin/pull/980 +[#982]: https://github.com/mobilecoinfoundation/mobilecoin/pull/982 +[#983]: https://github.com/mobilecoinfoundation/mobilecoin/pull/983 +[#985]: https://github.com/mobilecoinfoundation/mobilecoin/pull/985 +[#986]: https://github.com/mobilecoinfoundation/mobilecoin/pull/986 +[#988]: https://github.com/mobilecoinfoundation/mobilecoin/pull/988 +[#990]: https://github.com/mobilecoinfoundation/mobilecoin/pull/990 +[#991]: https://github.com/mobilecoinfoundation/mobilecoin/pull/991 +[#992]: https://github.com/mobilecoinfoundation/mobilecoin/pull/992 +[#993]: https://github.com/mobilecoinfoundation/mobilecoin/pull/993 +[#995]: https://github.com/mobilecoinfoundation/mobilecoin/pull/995 +[#996]: https://github.com/mobilecoinfoundation/mobilecoin/pull/996 +[#997]: https://github.com/mobilecoinfoundation/mobilecoin/pull/997 +[#998]: https://github.com/mobilecoinfoundation/mobilecoin/pull/998 +[#999]: https://github.com/mobilecoinfoundation/mobilecoin/pull/999 +[#1000]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1000 +[#1001]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1001 +[#1002]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1002 +[#1003]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1003 +[#1006]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1006 +[#1007]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1007 +[#1008]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1008 +[#1010]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1010 +[#1011]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1011 +[#1012]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1012 +[#1013]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1013 +[#1016]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1016 +[#1017]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1017 +[#1018]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1018 +[#1019]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1019 +[#1020]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1020 +[#1022]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1022 +[#1023]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1023 +[#1027]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1027 +[#1028]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1028 +[#1029]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1029 +[#1031]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1031 +[#1033]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1033 +[#1034]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1034 +[#1036]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1036 +[#1039]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1039 +[#1041]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1041 +[#1042]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1042 +[#1043]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1043 +[#1044]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1044 +[#1045]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1045 +[#1046]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1046 +[#1049]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1049 +[#1050]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1050 +[#1052]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1052 +[#1053]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1053 +[#1054]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1054 +[#1055]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1055 +[#1056]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1056 +[#1057]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1057 +[#1059]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1059 +[#1060]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1060 +[#1061]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1061 +[#1064]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1064 +[#1066]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1066 +[#1067]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1067 +[#1068]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1068 +[#1069]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1069 +[#1070]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1070 +[#1071]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1071 +[#1072]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1072 +[#1078]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1078 +[#1079]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1079 +[#1080]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1080 +[#1087]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1087 +[#1090]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1090 +[#1092]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1092 +[#1094]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1094 +[#1095]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1095 +[#1096]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1096 +[#1097]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1097 +[#1098]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1098 +[#1099]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1099 +[#1101]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1101 +[#1104]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1104 +[#1109]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1109 +[#1112]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1112 +[#1115]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1115 +[#1124]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1124 +[#1125]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1125 +[#1126]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1126 +[#1127]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1127 +[#1128]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1128 +[#1130]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1130 +[#1131]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1131 +[#1132]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1132 +[#1133]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1133 +[#1134]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1134 +[#1135]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1135 +[#1138]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1138 +[#1141]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1141 +[#1142]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1142 +[#1143]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1143 +[#1146]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1146 +[#1155]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1155 +[#1156]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1156 +[#1159]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1159 +[#1164]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1164 +[#1165]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1165 +[#1166]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1166 +[#1167]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1167 +[#1168]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1168 +[#1170]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1170 +[#1171]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1171 +[#1174]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1174 +[#1179]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1179 +[#1200]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1200 +[#1235]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1235 +[#1236]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1236 +[#1237]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1237 +[#1238]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1238 +[#1239]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1239 +[#1240]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1240 +[#1241]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1241 +[#1249]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1249 +[#1261]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1261 +[#1262]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1262 +[#1263]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1263 +[#1265]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1265 +[#1268]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1268 +[#1271]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1271 +[#1273]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1273 +[#1274]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1274 +[#1275]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1275 +[#1276]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1276 +[#1277]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1277 +[#1278]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1278 +[#1279]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1279 +[#1291]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1291 +[#1306]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1306 +[#1310]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1310 +[#1311]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1311 +[#1313]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1313 +[#1314]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1314 +[#1315]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1315 +[#1321]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1321 +[#1322]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1322 +[#1332]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1332 +[#1333]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1333 +[#1341]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1341 +[#1343]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1343 +[#1344]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1344 +[#1345]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1345 +[#1348]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1348 +[#1350]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1350 +[#1351]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1351 +[#1355]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1355 +[#1358]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1358 +[#1360]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1360 +[#1363]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1363 +[#1365]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1365 +[#1366]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1366 +[#1383]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1383 +[#1386]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1386 +[#1387]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1387 +[#1389]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1389 +[#1391]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1391 +[#1392]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1392 +[#1431]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1431 +[#1432]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1432 +[#1458]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1458 +[#1459]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1459 +[#1477]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1477 +[#1484]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1484 +[#1485]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1485 +[#1486]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1486 +[#1487]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1487 +[#1488]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1488 +[#1489]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1489 +[#1492]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1492 +[#1497]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1497 +[#1498]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1498 +[#1499]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1499 +[#1500]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1500 +[#1501]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1501 +[#1502]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1502 +[#1509]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1509 +[#1512]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1512 +[#1520]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1520 +[#1524]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1524 +[#1525]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1525 +[#1528]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1528 +[#1529]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1529 +[#1531]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1531 +[#1532]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1532 +[#1541]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1541 +[#1556]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1556 +[#1563]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1563 +[#1576]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1576 +[#1578]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1578 +[#1579]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1579 +[#1590]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1590 +[#1591]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1591 +[#1592]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1592 +[#1610]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1610 +[#1611]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1611 +[#1613]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1613 +[#1622]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1622 +[#1642]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1642 +[#1656]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1656 +[#1657]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1657 +[#1676]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1676 +[#1677]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1677 +[#1678]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1678 +[#1679]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1679 +[#1692]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1692 +[#1702]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1702 +[#1712]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1712 +[#1713]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1713 +[#1714]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1714 +[#1715]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1715 +[#1716]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1716 +[#1717]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1717 +[#1728]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1728 +[#1750]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1750 +[#1751]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1751 +[#1752]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1752 +[#1753]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1753 +[#1754]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1754 +[#1755]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1755 +[#1757]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1757 +[#1758]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1758 +[#1762]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1762 +[#1776]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1776 +[#1777]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1777 +[#1782]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1782 +[#1795]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1795 +[#1805]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1805 +[#1806]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1806 +[#1807]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1807 +[#1808]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1808 +[#1808]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1808 +[#1809]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1809 +[#1809]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1809 +[#1812]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1812 +[#1812]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1812 +[#1814]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1814 +[#1815]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1815 +[#1817]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1817 +[#1817]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1817 +[#1824]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1824 +[#1824]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1824 +[#1825]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1825 +[#1826]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1826 +[#1826]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1826 +[#1836]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1836 +[#1837]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1837 +[#1847]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1847 +[#1857]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1857 +[#1873]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1873 +[#1886]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1886 +[#1887]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1887 +[#1888]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1888 +[#1893]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1893 +[#1894]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1894 +[#1895]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1895 +[#1896]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1896 +[#1897]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1897 +[#1898]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1898 +[#1899]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1899 +[#1900]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1900 +[#1901]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1901 +[#1902]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1902 +[#1903]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1903 +[#1904]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1904 +[#1912]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1912 +[#1915]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1915 +[#1916]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1916 +[#1918]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1918 +[#1926]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1926 +[#1927]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1927 +[#1929]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1929 +[#1930]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1930 +[#1938]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1938 +[#1950]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1950 +[#1956]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1956 +[#1957]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1957 +[#1976]: https://github.com/mobilecoinfoundation/mobilecoin/pull/1976 +[#2018]: https://github.com/mobilecoinfoundation/mobilecoin/pull/2018 ## [1.1.1] - 2021-08-16 diff --git a/Cargo.lock b/Cargo.lock index 49881735a0..298a097fb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2015,7 +2015,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "cbindgen", @@ -2197,7 +2197,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "criterion", "curve25519-dalek", @@ -2225,7 +2225,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2241,7 +2241,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -2256,7 +2256,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "anyhow", @@ -2293,7 +2293,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "bs58", "cargo-emit", @@ -2329,7 +2329,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -2354,7 +2354,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -2372,7 +2372,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "bincode", @@ -2404,7 +2404,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2417,7 +2417,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2437,7 +2437,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -2448,7 +2448,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2458,7 +2458,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2483,7 +2483,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "backtrace", "binascii", @@ -2520,7 +2520,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "cookie", @@ -2549,7 +2549,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2560,7 +2560,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -2581,7 +2581,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2606,7 +2606,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "hex", @@ -2627,7 +2627,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2635,7 +2635,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "hex", @@ -2671,7 +2671,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2684,7 +2684,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2706,7 +2706,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2735,7 +2735,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "crossbeam-channel", "maplit", @@ -2758,7 +2758,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "mc-common", @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "chrono", @@ -2832,7 +2832,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -2857,7 +2857,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2877,7 +2877,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "digest 0.10.3", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2906,7 +2906,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -2915,7 +2915,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2923,7 +2923,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2932,7 +2932,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2940,7 +2940,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "blake2", "digest 0.10.3", @@ -2949,7 +2949,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -2982,7 +2982,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "displaydoc", @@ -2996,7 +2996,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3010,7 +3010,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -3031,7 +3031,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3042,7 +3042,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3055,7 +3055,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3067,7 +3067,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3078,7 +3078,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3089,7 +3089,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3153,7 +3153,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "cookie", @@ -3177,7 +3177,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3216,7 +3216,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "criterion", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3268,7 +3268,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3276,7 +3276,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3309,7 +3309,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3322,7 +3322,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "dirs", @@ -3379,7 +3379,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3395,7 +3395,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "grpcio", @@ -3416,7 +3416,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3445,7 +3445,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3463,7 +3463,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3471,7 +3471,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3507,7 +3507,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3560,7 +3560,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3576,7 +3576,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -3605,14 +3605,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3623,7 +3623,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -3640,7 +3640,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "lazy_static", "mc-common", @@ -3648,7 +3648,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3700,7 +3700,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -3719,7 +3719,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-util-serial", "prost", @@ -3728,7 +3728,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "binascii", @@ -3750,7 +3750,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "grpcio", @@ -3767,7 +3767,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3803,7 +3803,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3813,7 +3813,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3831,7 +3831,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3839,7 +3839,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3885,7 +3885,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3906,7 +3906,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3917,7 +3917,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3932,7 +3932,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "chrono", "clap 3.1.18", @@ -3965,7 +3965,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3996,7 +3996,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4027,7 +4027,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "crc", "displaydoc", @@ -4047,7 +4047,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-common", "mc-util-uri", @@ -4055,7 +4055,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "grpcio", "mc-attest-core", @@ -4075,7 +4075,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "criterion", @@ -4110,7 +4110,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4128,7 +4128,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4136,7 +4136,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4158,7 +4158,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4171,7 +4171,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4190,7 +4190,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -4213,7 +4213,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4263,7 +4263,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "lazy_static", @@ -4289,7 +4289,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "dirs", @@ -4311,7 +4311,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "mc-api", @@ -4322,7 +4322,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4335,7 +4335,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4366,7 +4366,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4399,7 +4399,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -4413,7 +4413,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4477,7 +4477,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -4495,7 +4495,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4602,7 +4602,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "grpcio", "hex", @@ -4625,7 +4625,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cc", "lazy_static", @@ -4635,7 +4635,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4643,7 +4643,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4652,7 +4652,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4660,7 +4660,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4669,21 +4669,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4694,7 +4694,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4710,7 +4710,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4720,18 +4720,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-urts" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-common", "mc-sgx-build", @@ -4742,7 +4742,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-account-keys", "mc-api", @@ -4764,7 +4764,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-util-test-vector", "serde", @@ -4773,7 +4773,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4788,7 +4788,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4810,7 +4810,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -4852,7 +4852,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4869,7 +4869,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4896,7 +4896,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -4905,7 +4905,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4921,7 +4921,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4929,7 +4929,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "json", @@ -4937,7 +4937,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -4948,7 +4948,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -4967,7 +4967,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "binascii", @@ -4979,18 +4979,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-util-from-random" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5009,7 +5009,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -5043,7 +5043,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -5054,7 +5054,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5065,11 +5065,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-util-keyfile" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -5097,7 +5097,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5107,7 +5107,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -5116,7 +5116,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5124,7 +5124,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "chrono", "grpcio", @@ -5137,7 +5137,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "itertools", "mc-sgx-css", @@ -5145,7 +5145,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "generic-array", "prost", @@ -5155,7 +5155,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5168,7 +5168,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "prost", "serde", @@ -5177,7 +5177,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5188,7 +5188,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "itertools", @@ -5202,7 +5202,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "serde", "serde_json", @@ -5210,7 +5210,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -5219,7 +5219,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "displaydoc", @@ -5237,7 +5237,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5281,7 +5281,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 8d32422ef2..74dfafc5aa 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index c6bbb5abff..7f4a8491b4 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index 37c3ea9ddd..735c4f1e43 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index b9e37b7caa..aac415a924 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/api/Cargo.toml b/api/Cargo.toml index 3d703d3a16..9036d5c2eb 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index bb5e791b82..a0da4ea396 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index ec623afcc3..c5e8584e04 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index d097c15728..47c96bc2c8 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index 1eb258eb63..649395b339 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index dce74ee9d8..3f1ad1fc71 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index 24b34a30d9..3136bf87df 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index a53b5170de..db7b6c410e 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index 4085a0559b..9c50a167f5 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/common/Cargo.toml b/common/Cargo.toml index a73f7db186..8abe7de47c 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/Cargo.toml b/connection/Cargo.toml index 4113610d94..6fb3c38a24 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index f546247b05..54920ff308 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index 201b07ba8d..ad0f2235d4 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index 2619b4685d..794a35ded1 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index 84414b977f..9ec51c84a9 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index c47c253143..38b39f4936 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index 131a1375f8..e478d46656 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index 8556e766ce..d0e0854824 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index 2cb69070c3..775ba0e034 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index b0be21bec8..c9bbfaf608 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-build" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-enclave-id" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-transaction-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index d7df707b01..7d421b7eb1 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index 94bcbcd4d0..f7c253bea6 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index 7941e3a851..a740bad08a 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index 61b843c1f6..7e357570d8 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index 15a0c768a6..b55ce790d8 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index 09391d200c..475d0b9ae6 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index 60586961df..c8c95eeab1 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index ec62a2dac5..850a45a76f 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index 31c84b146b..0dfc34c7b8 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index 9268b3477e..2fc2241265 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index a267ce1445..5e47d9bfe4 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index 3f21f1ecbd..715b18cc49 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index f4aad32248..616897e62d 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index 8c80bd31b4..96a9d5ed55 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index edea1a59a0..ff20beac10 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index 54f4d303ee..9b1db96174 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index 7146455bb3..ca6dbfaf68 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index f84395f456..8c70279142 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index 5b083bdfef..867ac76b51 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index a6fb5cbf55..7da6f30e97 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 28a1f839fb..5a4a283f23 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index 72b99a8ff4..fbecdb1a90 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index d38f2376f8..c47f881de3 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index ec202496bc..1fb6310eca 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index 8dd2f57c9e..94c7ba266f 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index b104063cc3..8d8d517aaa 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 7d271b657d..32ea55b91f 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index 4f75b2b903..4e8e1ca19c 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index 9fcec380d4..6f9435f3b2 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index 68d4e18f05..bb692cd578 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index 5cabd18fb0..ad1149b4c2 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index dbf16556a9..4e25821570 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 141d3c6fb7..7b79dbc8f0 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-build" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-transaction-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index c322ea1143..838fe62597 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index ad2611e08a..c3c5f6466a 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index a4d4e8a749..065540b110 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index a474889a32..876dfe1f39 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index c293db7d77..f99dee5fed 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index 604b7fa200..a6099fd472 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index 51cb29b21a..786159578b 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index c0cc40a903..d3b040fd5e 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index 0c9ddcf84f..e2b6aadf0f 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index a568c928cd..7f62caa27c 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-build" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-transaction-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index 908eaf5c0a..b5034647bc 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index 1d893a19f9..8ef6ea4f81 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index f51e6882e6..43d5c69e9f 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index db1b7d267f..d54dafea58 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index 55a8a7417f..8d0196567c 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index ccf837de5f..b39d3cd8f1 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index 43ff9bbc6b..4bb0685b63 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index 6ff29cbba8..09c4c054c6 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 83482688d2..21cafc9540 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index b2506b68ec..901aff6dcd 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index fceaf2da85..3619edfdbf 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index 5ecdca2781..7cd11ea4c8 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index ad7b77ecd9..79111a02db 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index 125a994744..f6ac46f2f4 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index ec496462f3..dbb09a5219 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index 3b872cce95..518a21cab2 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index 4a914b7bb6..0d0285c5d5 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index 420be58fc6..798140df77 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index dcdedce930..2ffaed77e4 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index 5de132a1d9..7d3b52b515 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index a8b9789b28..09c90cfce3 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index 8c1a3c2e31..cab75e7219 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index 9458b89b5e..c130884677 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 04eeedeabe..982dab205c 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index 54a87634a3..373ee62da4 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index ca6e1ce554..6a2d7514f4 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index 78093f2c76..0aa9ee8df2 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index 626ccaab1c..e08f638509 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index 08b0e19915..5f05687926 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index 0ddd255e4c..0a9ead9ead 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index 5747ff904b..c7ebcdbd28 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index 311c7d1bfd..d5a853e1c3 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index 75c2f3131b..02b70b4816 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index 54025d355f..cb288a2001 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-build" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" [[package]] name = "mc-transaction-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index 697d17fdd6..120e337056 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index 6f36df8d14..755a68d3d8 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index 44767eba86..7cd74da152 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index 8178e366b9..13d47b62d8 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index 05e7c53a30..c325cf738e 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index 1f6ca3d339..1efa145089 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index b3bd1d22bf..40ef8869a7 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index eabc9621d7..6b109e9c55 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index 2c00a4d675..574a63b70b 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index 5514129569..ef93f430e4 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index 75c9f6432c..40c580c21c 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index 999a66b0f9..14921fdce2 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index 0ab23ea638..da48a1be48 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index aff196978b..dececd7783 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index 1910fdbc0b..38a50628ba 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/peers/Cargo.toml b/peers/Cargo.toml index f4bef84016..55121aa55c 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index 2547b769dc..2a8487d014 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index 1b9692b032..5dafaa6042 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index bf3ea7fe2c..44923b3d7a 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index 059f410db2..9e4e4c4edf 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index 1b9c24bb4b..1a5515cd99 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index 0677929546..6c7f476d85 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index f8b9b8b966..476bc0b9d8 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index 1052f01753..016c80e00b 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index 5b9e3f6bb7..dbfeaa3074 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index ae4fdc4aab..65d5d0bb3f 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index 0f3763d5c0..232848092e 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index bc018a2f91..11e4a16adf 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index 6591099d22..442a07d49f 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index 12918e4682..0bf6c781ea 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index 5cd0c36103..8d0a27b73d 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index 01eee36e51..ae833779bf 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index 349c5a0ec4..a88438468e 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index ba8a4d6c4e..f38f8068fb 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index f71ee8ef64..ee89875d98 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "1.3.0-pre0" +version = "1.2.0-pre0" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index c0422fa45b..90a958a3d9 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index 100a41be1d..f5bf7ac1ac 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index 375c77bcdd..8009555f7f 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index 3cbe2050d0..c56aed595e 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index d4c65149b0..08f5484279 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index 1e4e884fcf..78b7101427 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index fa3aba171b..8374f8d213 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 499fc114c9..8dadfabc70 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index f5c73edf00..7802225086 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index 1a8d9693b5..d8b16d2d61 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index ec5f7d5893..775df54c0e 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index 1493c8d842..93efed78fd 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index aef683b378..ed8fa936f4 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index ced8e4429b..a01bd1579f 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index d8de901e23..2b596339c7 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index 69b731f45a..d199b5877a 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index 82c179c051..7863b10aee 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index 9a0df6c4dd..ffc3914235 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index 0bebe6acb4..f7b171a0c2 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index dd26a02a8f..b44ca0f92f 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index fd2ec3a803..373e0c41f5 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index b67d0b6847..6978bae066 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 755896fe87..4f9bf81d15 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index a52621effb..ee68242fe1 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index 57317ff79e..abfbf8b38b 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index 8d7d0304e4..92f6bec1c8 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index 73e6c0bc91..6c45d904b9 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index 31ebd452bb..6f27f80726 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index 7812d7d9d1..a6b8fccca1 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index fc3aa55a94..7ff8c5af18 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index adf9414ac1..24328b2e15 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index 2edbc21c45..aa2d127926 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index a75caa61ba..b3536fc4f0 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index 0ec4ed50a6..bb69b65757 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index 0c50a6a114..92d07585bc 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index c721f2c9c4..d3fbf5b7ac 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index 2fd83ea324..20781fa60a 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index 36dc13b6e5..b49fb2bd0f 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index 7f567e63b4..62eaa37666 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "1.3.0-pre0" +version = "1.2.0-pre0" authors = ["MobileCoin"] edition = "2018" From 307a5b98e994a9291a2290143259b3807826653f Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Mon, 23 May 2022 17:32:58 -0600 Subject: [PATCH 17/77] Make the read_pubfile tool able to create b58 encoded files optionally (#2037) This avoids the need to have another more complicated tool for this --- util/keyfile/src/bin/read_pubfile.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/util/keyfile/src/bin/read_pubfile.rs b/util/keyfile/src/bin/read_pubfile.rs index 378b17a6e5..9788f2cfe9 100644 --- a/util/keyfile/src/bin/read_pubfile.rs +++ b/util/keyfile/src/bin/read_pubfile.rs @@ -2,9 +2,10 @@ #![deny(missing_docs)] //! Utility to read .pub files. +//! Optionally, can transcribe them to the b58 format use clap::Parser; -use mc_util_keyfile::read_pubfile; +use mc_util_keyfile::{read_pubfile, write_b58pubfile}; use std::path::PathBuf; #[derive(Debug, Parser)] @@ -12,6 +13,11 @@ struct Config { /// Path to pubfile #[clap(long, env = "MC_PUBFILE")] pub pubfile: PathBuf, + + /// Optionally, a path at which to output b58 encoding of this public + /// address + #[clap(long, env = "MC_OUT_B58")] + pub out_b58: Option, } fn main() { @@ -43,4 +49,8 @@ fn main() { "Spend Public Bytes (hex): {:?}", hex::encode(pubaddress.spend_public_key().to_bytes()) ); + + if let Some(out) = config.out_b58.as_ref() { + write_b58pubfile(out, &pubaddress).expect("Could not write out-b58 file"); + } } From 66f24ff363a39a993ea8b85efaca5e75d2a01410 Mon Sep 17 00:00:00 2001 From: Eran Rundstein Date: Mon, 23 May 2022 18:10:45 -0700 Subject: [PATCH 18/77] fix a regression that prevented clients from re-attesting (#2038) (#2040) * fix a regression that prevented clients from re-attesting * rename method --- connection/src/thick.rs | 18 ++++++++++++++---- connection/src/traits.rs | 7 +++++-- fog/enclave_connection/src/error.rs | 6 +++++- fog/ingest/server/src/connection_error.rs | 6 +++++- peers/src/error.rs | 6 +++++- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/connection/src/thick.rs b/connection/src/thick.rs index f296d7acbe..f77777718f 100644 --- a/connection/src/thick.rs +++ b/connection/src/thick.rs @@ -114,7 +114,11 @@ impl AuthenticationError for ThickClientAttestationError { } } -impl AttestationError for ThickClientAttestationError {} +impl AttestationError for ThickClientAttestationError { + fn should_reattest(&self) -> bool { + matches!(self, Self::Grpc(_) | Self::Ake(_) | Self::Cipher(_)) + } +} /// A connection from a client to a consensus enclave. pub struct ThickClient { @@ -182,7 +186,7 @@ impl ThickClient { // Make the actual RPC call. let result = func(self, self.call_option()?); if let Err(err) = &result { - self.reset_if_unauthenticated(err); + self.handle_rpc_error(err); } // Block on the call, and update cookies before passing on the response. @@ -205,7 +209,7 @@ impl ThickClient { }) .map_err(|err| { let err = ThickClientAttestationError::from(err); - self.reset_if_unauthenticated(&err); + self.handle_rpc_error(&err); err }) } @@ -242,12 +246,18 @@ impl ThickClient { Ok(CallOption::default().headers(metadata_builder.build())) } - fn reset_if_unauthenticated(&mut self, err: &impl AuthenticationError) { + fn handle_rpc_error(&mut self, err: &(impl AuthenticationError + AttestationError)) { // If the call failed due to authentication (credentials) error, reset creds so // that it gets re-created on the next call. if err.is_unauthenticated() { self.credentials_provider.clear(); } + + // If the call failed due to attestation error, reset attestation so that we + // re-attest on the next call. + if err.should_reattest() { + self.deattest(); + } } } diff --git a/connection/src/traits.rs b/connection/src/traits.rs index ae8613a81c..91ca4c579e 100644 --- a/connection/src/traits.rs +++ b/connection/src/traits.rs @@ -26,9 +26,12 @@ pub trait Connection: Display + Eq + Hash + Ord + PartialEq + PartialOrd + Send fn uri(&self) -> Self::Uri; } -/// A marker trait used to encapsulate connection-impl-specific attestation +/// A trait used to encapsulate connection-impl-specific attestation /// errors. -pub trait AttestationError: Debug + Display + Send + Sync {} +pub trait AttestationError: Debug + Display + Send + Sync { + /// Should the error result in re-attestation? + fn should_reattest(&self) -> bool; +} pub trait AttestedConnection: Connection { type Error: AttestationError + From; diff --git a/fog/enclave_connection/src/error.rs b/fog/enclave_connection/src/error.rs index 37650dcc53..388716f1a1 100644 --- a/fog/enclave_connection/src/error.rs +++ b/fog/enclave_connection/src/error.rs @@ -29,7 +29,11 @@ impl Error { } } -impl AttestationError for Error {} +impl AttestationError for Error { + fn should_reattest(&self) -> bool { + matches!(self, Self::Rpc(_) | Self::Ake(_) | Self::Cipher(_)) + } +} impl From for Error { fn from(err: grpcio::Error) -> Self { diff --git a/fog/ingest/server/src/connection_error.rs b/fog/ingest/server/src/connection_error.rs index ad94e1de97..a84cecc642 100644 --- a/fog/ingest/server/src/connection_error.rs +++ b/fog/ingest/server/src/connection_error.rs @@ -114,4 +114,8 @@ impl From for PeerAttestationError { } } -impl AttestationError for PeerAttestationError {} +impl AttestationError for PeerAttestationError { + fn should_reattest(&self) -> bool { + true + } +} diff --git a/peers/src/error.rs b/peers/src/error.rs index 2cd4b62ebb..d615b0022f 100644 --- a/peers/src/error.rs +++ b/peers/src/error.rs @@ -152,4 +152,8 @@ impl From for PeerAttestationError { } } -impl AttestationError for PeerAttestationError {} +impl AttestationError for PeerAttestationError { + fn should_reattest(&self) -> bool { + true + } +} From 85f9def5574e8c035b52bbd26e49cf574e338ab7 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 24 May 2022 13:36:57 -0600 Subject: [PATCH 19/77] make mobilecoind-json integration test work with root entropy accounts (#2043) * make mobilecoind-json integration test work with mnemonics * fix mistakes * remoun improvement * derp * simplify --- mobilecoind-json/tests/integration_test.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mobilecoind-json/tests/integration_test.py b/mobilecoind-json/tests/integration_test.py index c1901f5256..d3f7f4cfdd 100644 --- a/mobilecoind-json/tests/integration_test.py +++ b/mobilecoind-json/tests/integration_test.py @@ -57,8 +57,20 @@ def get_monitor(self, monitor_id): def get_ledger_local(self): return self.request(f"ledger/local") - def account_key_from_mnemonic(self, mnemonic): - return self.request("account-key-from-mnemonic", {"mnemonic": mnemonic}) + # Takes the json loaded from a private key file, tests if it is mnemnonic or root entropy + # + # If it is mnemonic, we pass the mnemonic to `account-key-from-mnemonic` route + # Otherwise, we hit the `entropy/{root_entropy}` route. + # Both return Json account key response. + def account_key_from_json(self, obj): + if "mnemonic" in obj: + return self.request("account-key-from-mnemonic", {"mnemonic": obj["mnemonic"]}) + elif "root_entropy" in obj: + # Take the integer array in obj["root_entropy"], convert it to builtin bytes, then + # get hex string of that. + return self.request("entropy/{}".format(bytes(obj["root_entropy"]).hex())) + else: + raise Exception("unknown key format", obj) def get_public_address(self, monitor_id, subaddress_index=0): return self.request(f"monitors/{monitor_id}/subaddresses/{subaddress_index}/public-address") @@ -113,7 +125,7 @@ def run_test(mobilecoind_json_url, keys_dir, max_seconds): # Add two monitors and wait for them to sync monitor_ids = [] for i in range(2): - account_key = client.account_key_from_mnemonic(keys[i]["mnemonic"]) + account_key = client.account_key_from_json(keys[i]) monitor = client.create_monitor(account_key) logging.info(f"{i}: Monitor created: {monitor}, waiting to sync...") monitor_id = monitor["monitor_id"] From de384720f63bff4145d787bdfd81c30e413bda48 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 24 May 2022 19:14:13 -0600 Subject: [PATCH 20/77] make drain accounts script handle defragmentation errors (#2035) (#2045) * make drain accounts script handle defragmentation errors * make it subtract fee from sending amount after successful defragmentation * Update mobilecoind/strategies/drain-accounts.py Co-authored-by: Mike Turner * Update mobilecoind/strategies/drain-accounts.py Co-authored-by: Mike Turner * Update mobilecoind/strategies/drain-accounts.py Co-authored-by: Mike Turner * fix indentation * fix syntax Co-authored-by: Mike Turner Co-authored-by: Mike Turner --- mobilecoind/strategies/drain-accounts.py | 64 ++++++++++++++++++------ 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/mobilecoind/strategies/drain-accounts.py b/mobilecoind/strategies/drain-accounts.py index 8330cb413a..88b6cffe64 100644 --- a/mobilecoind/strategies/drain-accounts.py +++ b/mobilecoind/strategies/drain-accounts.py @@ -85,20 +85,56 @@ def run_test(stub, amount, monitor_id, dest, max_seconds, token_id): mobilecoind_api_pb2.GetBalanceRequest(monitor_id=monitor_id, token_id=token_id)) starting_balance = resp.balance logging.info("Starting balance prior to transfer: %s", starting_balance) - tx_resp = stub.SendPayment( - mobilecoind_api_pb2.SendPaymentRequest( - sender_monitor_id=monitor_id, - sender_subaddress=0, - outlay_list=[ - mobilecoind_api_pb2.Outlay( - value=amount, - receiver=dest, - ) - ], - fee=0, - tombstone=0, - token_id=token_id, - )) + + # Try building a payment that sends all of our balance + # We may get a defragmentation error -- if we do, then submit optimization Tx outs + # until we don't get that error anymore + while True: + try: + tx_resp = stub.SendPayment( + mobilecoind_api_pb2.SendPaymentRequest( + sender_monitor_id=monitor_id, + sender_subaddress=0, + outlay_list=[ + mobilecoind_api_pb2.Outlay( + value=amount, + receiver=dest, + ) + ], + fee=0, + tombstone=0, + token_id=token_id, + )) + break + except grpc.RpcError as e: + if "insufficient funds due to utxo fragmentation" in e.details.lower(): + logging.info("Got defragmentation error, building an optimization transaction") + opt_tx = stub.GenerateOptimizationTx( + mobilecoind_api_pb2.GenerateOptimizationTxRequest( + monitor_id=monitor_id, + subaddress=0, + fee=0, + token_id=token_id, + )) + tx_resp = stub.SubmitTx( + mobilecoind_api_pb2.SubmitTxRequest( + tx_proposal=opt_tx.tx_proposal + )) + tx_stats[0] = { + 'start': time.time(), + 'time_delta': None, + 'tombstone': tx_resp.sender_tx_receipt.tombstone, + 'block_delta': None, + 'status': TransferStatus.pending, + 'receipt': tx_resp, + } + stats = poll(monitor_id, tx_stats, stub) + # Subtract fee from amount, so that we don't get an insufficient funds error + # in the next cycle (since it costs us a fee to defragment) + amount = amount - opt_tx.tx_proposal.fee + else: + logging.error("RPC Error encountered") + raise tx_stats[0] = { 'start': time.time(), From c3963f3af62ba820675401a30b5856cee2b5de2c Mon Sep 17 00:00:00 2001 From: Adam Mork Date: Wed, 25 May 2022 15:30:39 -0700 Subject: [PATCH 21/77] iOS - TxOutContext, Amount -> MaskedAmount, Value -> Amount (#2046) * Added TxOutContext to the iOS Bindings * Converted Amount struct to MaskedAmount * Converted UInt64 "value" to Amount struct that has a tokenId * LTO false for mobile-release, to fix possible issues with bitcode support. ### Motivation Need these ffi/binding changes to support the 1.2 / BlockVersion == 2 release. --- Cargo.toml | 1 + libmobilecoin/include/transaction.h | 51 +++------ libmobilecoin/libmobilecoin_cbindgen.h | 58 ++++------- libmobilecoin/src/transaction.rs | 137 ++++++++++--------------- libmobilecoin/toolchain-config.env | 7 +- 5 files changed, 89 insertions(+), 165 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f01e9975bc..7617453996 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -182,6 +182,7 @@ lto = true [profile.mobile-release] inherits = "mobile" codegen-units = 1 +lto = false # Skip the need for LD_LIBRARY_PATH in `cargo test` [profile.test] diff --git a/libmobilecoin/include/transaction.h b/libmobilecoin/include/transaction.h index 0c5f2a2810..a75c2e8960 100644 --- a/libmobilecoin/include/transaction.h +++ b/libmobilecoin/include/transaction.h @@ -17,6 +17,12 @@ extern "C" { typedef struct { uint64_t masked_value; + const McBuffer* MC_NONNULL masked_token_id; +} McTxOutMaskedAmount; + +typedef struct { + uint64_t value; + uint64_t token_id; } McTxOutAmount; typedef struct _McTransactionBuilderRing McTransactionBuilderRing; @@ -34,7 +40,7 @@ typedef struct _McTxOutMemoBuilder McTxOutMemoBuilder; /// * `LibMcError::InvalidInput` /// * `LibMcError::TransactionCrypto` bool mc_tx_out_reconstruct_commitment( - const McTxOutAmount* MC_NONNULL tx_out_amount, + const McTxOutMaskedAmount* MC_NONNULL tx_out_masked_amount, const McBuffer* MC_NONNULL tx_out_public_key, const McBuffer* MC_NONNULL view_private_key, McMutableBuffer* MC_NONNULL out_commitment, @@ -42,17 +48,6 @@ bool mc_tx_out_reconstruct_commitment( ) MC_ATTRIBUTE_NONNULL(1, 2, 3, 4); -/// # Preconditions -/// -/// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. -bool mc_tx_out_matches_any_subaddress( - const McTxOutAmount* MC_NONNULL tx_out_amount, - const McBuffer* MC_NONNULL tx_out_public_key, - const McBuffer* MC_NONNULL view_private_key, - bool* MC_NONNULL out_matches -) -MC_ATTRIBUTE_NONNULL(1, 2, 3, 4); - /// # Preconditions /// /// * `tx_out_commitment` - must be a valid CompressedCommitment @@ -105,11 +100,11 @@ MC_ATTRIBUTE_NONNULL(1, 2, 3, 4); /// /// * `LibMcError::InvalidInput` /// * `LibMcError::TransactionCrypto` -bool mc_tx_out_get_value( - const McTxOutAmount* MC_NONNULL tx_out_amount, +bool mc_tx_out_get_amount( + const McTxOutMaskedAmount* MC_NONNULL tx_out_masked_amount, const McBuffer* MC_NONNULL tx_out_public_key, const McBuffer* MC_NONNULL view_private_key, - uint64_t* MC_NONNULL out_value, + McTxOutAmount* MC_NONNULL out_amount, McError* MC_NULLABLE * MC_NULLABLE out_error ) MC_ATTRIBUTE_NONNULL(1, 2, 3, 4); @@ -169,11 +164,13 @@ MC_ATTRIBUTE_NONNULL(1, 2, 3); McTransactionBuilder* MC_NULLABLE mc_transaction_builder_create( uint64_t fee, + uint64_t token_id, uint64_t tombstone_block, const McFogResolver* MC_NULLABLE fog_resolver, McTxOutMemoBuilder* MC_NONNULL memo_builder, uint32_t block_version ); +MC_ATTRIBUTE_NONNULL(5); void mc_transaction_builder_free( McTransactionBuilder* MC_NULLABLE transaction_builder @@ -241,29 +238,7 @@ McData* MC_NULLABLE mc_transaction_builder_add_change_output( McMutableBuffer* MC_NONNULL out_tx_out_shared_secret, McError* MC_NULLABLE * MC_NULLABLE out_error ) -MC_ATTRIBUTE_NONNULL(1, 2, 4, 5, 6); - -/// # Preconditions -/// -/// * `transaction_builder` - must not have been previously consumed by a call to `build`. -/// * `recipient_address` - must be a valid `PublicAddress`. -/// * `fog_hint_address` - must be a valid `PublicAddress` with `fog_info`. -/// * `out_tx_out_confirmation_number` - length must be >= 32. -/// -/// # Errors -/// -/// * `LibMcError::AttestationVerification` -/// * `LibMcError::InvalidInput` -McData* MC_NULLABLE mc_transaction_builder_add_output_with_fog_hint_address( - McTransactionBuilder* MC_NONNULL transaction_builder, - uint64_t amount, - const McPublicAddress* MC_NONNULL recipient_address, - const McPublicAddress* MC_NONNULL fog_hint_address, - McRngCallback* MC_NULLABLE rng_callback, - McMutableBuffer* MC_NONNULL out_tx_out_confirmation_number, - McError* MC_NULLABLE * MC_NULLABLE out_error -) -MC_ATTRIBUTE_NONNULL(1, 3, 4, 5, 7); +MC_ATTRIBUTE_NONNULL(1, 2, 4, 6); /// # Preconditions /// diff --git a/libmobilecoin/libmobilecoin_cbindgen.h b/libmobilecoin/libmobilecoin_cbindgen.h index 67cea067d3..d2fa919643 100644 --- a/libmobilecoin/libmobilecoin_cbindgen.h +++ b/libmobilecoin/libmobilecoin_cbindgen.h @@ -138,11 +138,22 @@ typedef struct McAccountKey { FfiOptRefPtr fog_info; } McAccountKey; -typedef struct McTxOutAmount { +typedef struct McTxOutMaskedAmount { /** * 32-byte `CompressedCommitment` */ uint64_t masked_value; + /** + * `masked_token_id = token_id XOR_8 Blake2B(token_id_mask | + * shared_secret)` 8 bytes long when used, 0 bytes for older amounts + * that don't have this. + */ + FfiRefPtr masked_token_id; +} McTxOutMaskedAmount; + +typedef struct McTxOutAmount { + uint64_t value; + uint64_t token_id; } McTxOutAmount; typedef struct Option_TransactionBuilder_FogResolver McTransactionBuilder; @@ -617,7 +628,7 @@ bool mc_slip10_account_private_keys_from_mnemonic(FfiStr mnemonic, * * * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. */ -bool mc_tx_out_reconstruct_commitment(FfiRefPtr tx_out_amount, +bool mc_tx_out_reconstruct_commitment(FfiRefPtr tx_out_masked_amount, FfiRefPtr tx_out_public_key, FfiRefPtr view_private_key, FfiMutPtr out_tx_out_commitment, @@ -636,16 +647,6 @@ bool mc_tx_out_commitment_crc32(FfiRefPtr tx_out_commitment, FfiMutPtr out_crc32, FfiOptMutPtr> out_error); -/** - * # Preconditions - * - * * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. - */ -bool mc_tx_out_matches_any_subaddress(FfiRefPtr _tx_out_amount, - FfiRefPtr tx_out_public_key, - FfiRefPtr view_private_key, - FfiMutPtr out_matches); - /** * # Preconditions * @@ -685,11 +686,11 @@ bool mc_tx_out_get_subaddress_spend_public_key(FfiRefPtr tx_out_target * * `LibMcError::InvalidInput` * * `LibMcError::TransactionCrypto` */ -bool mc_tx_out_get_value(FfiRefPtr tx_out_amount, - FfiRefPtr tx_out_public_key, - FfiRefPtr view_private_key, - FfiMutPtr out_value, - FfiOptMutPtr> out_error); +bool mc_tx_out_get_amount(FfiRefPtr tx_out_masked_amount, + FfiRefPtr tx_out_public_key, + FfiRefPtr view_private_key, + FfiMutPtr out_amount, + FfiOptMutPtr> out_error); /** * # Preconditions @@ -738,6 +739,7 @@ bool mc_transaction_builder_ring_add_element(FfiMutPtr FfiRefPtr membership_proof_proto_bytes); FfiOptOwnedPtr mc_transaction_builder_create(uint64_t fee, + uint64_t token_id, uint64_t tombstone_block, FfiOptRefPtr fog_resolver, FfiMutPtr memo_builder, @@ -810,28 +812,6 @@ FfiOptOwnedPtr mc_transaction_builder_add_change_output(FfiRefPtr out_tx_out_shared_secret, FfiOptMutPtr> out_error); -/** - * # Preconditions - * - * * `transaction_builder` - must not have been previously consumed by a call - * to `build`. - * * `recipient_address` - must be a valid `PublicAddress`. - * * `fog_hint_address` - must be a valid `PublicAddress` with `fog_info`. - * * `out_tx_out_confirmation_number` - length must be >= 32. - * - * # Errors - * - * * `LibMcError::AttestationVerification` - * * `LibMcError::InvalidInput` - */ -FfiOptOwnedPtr mc_transaction_builder_add_output_with_fog_hint_address(FfiMutPtr _transaction_builder, - uint64_t _amount, - FfiRefPtr _recipient_address, - FfiRefPtr _fog_hint_address, - FfiOptMutPtr _rng_callback, - FfiMutPtr _out_tx_out_confirmation_number, - FfiOptMutPtr> _out_error); - /** * # Preconditions * diff --git a/libmobilecoin/src/transaction.rs b/libmobilecoin/src/transaction.rs index d6c3779120..ac386b6114 100644 --- a/libmobilecoin/src/transaction.rs +++ b/libmobilecoin/src/transaction.rs @@ -17,9 +17,8 @@ use mc_transaction_core::{ get_tx_out_shared_secret, onetime_keys::{recover_onetime_private_key, recover_public_subaddress_spend_key}, ring_signature::KeyImage, - tokens::Mob, tx::{TxOut, TxOutConfirmationNumber, TxOutMembershipProof}, - Amount, BlockVersion, CompressedCommitment, EncryptedMemo, MaskedAmount, Token, + Amount, BlockVersion, CompressedCommitment, EncryptedMemo, MaskedAmount, TokenId, }; use mc_transaction_std::{ @@ -33,9 +32,30 @@ use mc_util_ffi::*; /* ==== TxOut ==== */ #[repr(C)] -pub struct McTxOutAmount { +pub struct McTxOutMaskedAmount<'a> { /// 32-byte `CompressedCommitment` masked_value: u64, + + /// `masked_token_id = token_id XOR_8 Blake2B(token_id_mask | + /// shared_secret)` 8 bytes long when used, 0 bytes for older amounts + /// that don't have this. + masked_token_id: FfiRefPtr<'a, McBuffer<'a>>, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct McTxOutAmount { + value: u64, + token_id: u64, +} + +impl From for McTxOutAmount { + fn from(amount: Amount) -> Self { + McTxOutAmount { + value: amount.value, + token_id: *amount.token_id, + } + } } pub type McTxOutMemoBuilder = Option>; @@ -46,7 +66,7 @@ impl_into_ffi!(Option>); /// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. #[no_mangle] pub extern "C" fn mc_tx_out_reconstruct_commitment( - tx_out_amount: FfiRefPtr, + tx_out_masked_amount: FfiRefPtr, tx_out_public_key: FfiRefPtr, view_private_key: FfiRefPtr, out_tx_out_commitment: FfiMutPtr, @@ -59,10 +79,11 @@ pub extern "C" fn mc_tx_out_reconstruct_commitment( let shared_secret = get_tx_out_shared_secret(&view_private_key, &tx_out_public_key); - // FIXME #1596: McTxOutAmount should include the masked_token_id bytes, which - // are 0 or 4 bytes For now zero to avoid breaking changes to FFI - let (masked_amount, _) = - MaskedAmount::reconstruct(tx_out_amount.masked_value, &[], &shared_secret)?; + let (masked_amount, _) = MaskedAmount::reconstruct( + tx_out_masked_amount.masked_value, + &tx_out_masked_amount.masked_token_id, + &shared_secret, + )?; let out_tx_out_commitment = out_tx_out_commitment .into_mut() @@ -95,32 +116,6 @@ pub extern "C" fn mc_tx_out_commitment_crc32( }) } -/// # Preconditions -/// -/// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. -#[no_mangle] -pub extern "C" fn mc_tx_out_matches_any_subaddress( - _tx_out_amount: FfiRefPtr, - tx_out_public_key: FfiRefPtr, - view_private_key: FfiRefPtr, - out_matches: FfiMutPtr, -) -> bool { - ffi_boundary(|| { - let _view_private_key = RistrettoPrivate::try_from_ffi(&view_private_key) - .expect("view_private_key is not a valid RistrettoPrivate"); - - let mut matches = false; - if let Ok(_public_key) = RistrettoPublic::try_from_ffi(&tx_out_public_key) { - // FIXME #1596: This function doesn't make sense unless we have access to the - // amount.commitment from the TxOut, or the commitment_crc32 from the fog tx - // out, so that we have some way to check if we recovered the - // correct commitment. - matches = true; - } - *out_matches.into_mut() = matches; - }) -} - /// # Preconditions /// /// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. @@ -199,11 +194,11 @@ pub extern "C" fn mc_tx_out_get_subaddress_spend_public_key( /// * `LibMcError::InvalidInput` /// * `LibMcError::TransactionCrypto` #[no_mangle] -pub extern "C" fn mc_tx_out_get_value( - tx_out_amount: FfiRefPtr, +pub extern "C" fn mc_tx_out_get_amount( + tx_out_masked_amount: FfiRefPtr, tx_out_public_key: FfiRefPtr, view_private_key: FfiRefPtr, - out_value: FfiMutPtr, + out_amount: FfiMutPtr, out_error: FfiOptMutPtr>, ) -> bool { ffi_boundary_with_error(out_error, || { @@ -211,11 +206,13 @@ pub extern "C" fn mc_tx_out_get_value( let view_private_key = RistrettoPrivate::try_from_ffi(&view_private_key)?; let shared_secret = get_tx_out_shared_secret(&view_private_key, &tx_out_public_key); - let (_masked_amount, amount) = - MaskedAmount::reconstruct(tx_out_amount.masked_value, &[], &shared_secret)?; + let (_masked_amount, amount) = MaskedAmount::reconstruct( + tx_out_masked_amount.masked_value, + &tx_out_masked_amount.masked_token_id, + &shared_secret, + )?; - // FIXME #1596: This should also return the amount.token_id - *out_value.into_mut() = amount.value; + *out_amount.into_mut() = McTxOutAmount::from(amount); Ok(()) }) } @@ -347,6 +344,7 @@ impl_into_ffi!(Option>); #[no_mangle] pub extern "C" fn mc_transaction_builder_create( fee: u64, + token_id: u64, tombstone_block: u64, fog_resolver: FfiOptRefPtr, memo_builder: FfiMutPtr, @@ -369,12 +367,8 @@ pub extern "C" fn mc_transaction_builder_create( .into_mut() .take() .expect("McTxOutMemoBuilder has already been used to build a Tx"); - // FIXME: block version should be a parameter, it should be the latest - // version that fog ledger told us about, or that we got from ledger-db - //let block_version = BlockVersion::ZERO; - // TODO #1596: Support token id other than Mob (but not in this release) - let fee_amount = Amount::new(fee, Mob::ID); + let fee_amount = Amount::new(fee, TokenId::from(token_id)); let mut transaction_builder = TransactionBuilder::new_with_box( block_version, @@ -492,22 +486,23 @@ pub extern "C" fn mc_transaction_builder_add_output( let recipient_address = PublicAddress::try_from_ffi(&recipient_address).expect("recipient_address is invalid"); let mut rng = SdkRng::from_ffi(rng_callback); + let out_tx_out_confirmation_number = out_tx_out_confirmation_number .into_mut() .as_slice_mut_of_len(TxOutConfirmationNumber::size()) .expect("out_tx_out_confirmation_number length is insufficient"); - let tx_out_context = - transaction_builder.add_output(amount, &recipient_address, &mut rng)?; - - out_tx_out_confirmation_number.copy_from_slice(tx_out_context.confirmation.as_ref()); - let out_tx_out_shared_secret = out_tx_out_shared_secret .into_mut() .as_slice_mut_of_len(RistrettoPublic::size()) .expect("out_tx_out_shared_secret length is insufficient"); + let tx_out_context = + transaction_builder.add_output(amount, &recipient_address, &mut rng)?; + + out_tx_out_confirmation_number.copy_from_slice(tx_out_context.confirmation.as_ref()); out_tx_out_shared_secret.copy_from_slice(&tx_out_context.shared_secret.to_bytes()); + Ok(mc_util_serial::encode(&tx_out_context.tx_out)) }) } @@ -543,55 +538,27 @@ pub extern "C" fn mc_transaction_builder_add_change_output( .expect("McTransactionBuilder instance has already been used to build a Tx"); let change_destination = ChangeDestination::from(&account_key_obj); let mut rng = SdkRng::from_ffi(rng_callback); + let out_tx_out_confirmation_number = out_tx_out_confirmation_number .into_mut() .as_slice_mut_of_len(TxOutConfirmationNumber::size()) .expect("out_tx_out_confirmation_number length is insufficient"); - let tx_out_context = - transaction_builder.add_change_output(amount, &change_destination, &mut rng)?; - - out_tx_out_confirmation_number.copy_from_slice(tx_out_context.confirmation.as_ref()); - let out_tx_out_shared_secret = out_tx_out_shared_secret .into_mut() .as_slice_mut_of_len(RistrettoPublic::size()) .expect("out_tx_out_shared_secret length is insufficient"); + let tx_out_context = + transaction_builder.add_change_output(amount, &change_destination, &mut rng)?; + + out_tx_out_confirmation_number.copy_from_slice(tx_out_context.confirmation.as_ref()); out_tx_out_shared_secret.copy_from_slice(&tx_out_context.shared_secret.to_bytes()); + Ok(mc_util_serial::encode(&tx_out_context.tx_out)) }) } -/// # Preconditions -/// -/// * `transaction_builder` - must not have been previously consumed by a call -/// to `build`. -/// * `recipient_address` - must be a valid `PublicAddress`. -/// * `fog_hint_address` - must be a valid `PublicAddress` with `fog_info`. -/// * `out_tx_out_confirmation_number` - length must be >= 32. -/// -/// # Errors -/// -/// * `LibMcError::AttestationVerification` -/// * `LibMcError::InvalidInput` -#[no_mangle] -pub extern "C" fn mc_transaction_builder_add_output_with_fog_hint_address( - _transaction_builder: FfiMutPtr, - _amount: u64, - _recipient_address: FfiRefPtr, - _fog_hint_address: FfiRefPtr, - _rng_callback: FfiOptMutPtr, - _out_tx_out_confirmation_number: FfiMutPtr, - _out_error: FfiOptMutPtr>, -) -> FfiOptOwnedPtr { - // FIXME(chris): The SDK should probably stop binding to this function, I don't - // believe that there is legitimate use for this. - // It should bind "add_change_output" instead. - // Please speak to me if you disagree. - unimplemented!("TransactionBuilder::add_output_with_fog_hint_address was removed, please use add_change_output"); -} - /// # Preconditions /// /// * `transaction_builder` - must not have been previously consumed by a call diff --git a/libmobilecoin/toolchain-config.env b/libmobilecoin/toolchain-config.env index e3ba4a31e5..ca17591fe0 100644 --- a/libmobilecoin/toolchain-config.env +++ b/libmobilecoin/toolchain-config.env @@ -3,7 +3,8 @@ # Storing seperately so they can be checksummed # and used as a cache key in circleci # -export RUST_BITCODE_COMMIT="241fb1df0170598653e7311d4616cb0193167b69" -export RUST_COMMIT="bfe15646761a75f0259e204cab071565eed2b1e5" -export RUST_COMMIT_NAME="nightly-2022-01-22" + +export RUST_BITCODE_COMMIT="930417098692ef88060ad35ed5f94baf50b8953b" +export RUST_COMMIT="05c07386b45fbc540ec8cdc1bc41ae9c062b453b" +export RUST_COMMIT_NAME="nightly-2022-04-29" export SWIFT_VERSION="5.5" From 51fdac4085cd5fb6946a61797193bbe94e7d9a27 Mon Sep 17 00:00:00 2001 From: James Cape Date: Thu, 26 May 2022 11:25:52 -0700 Subject: [PATCH 22/77] Bump all versions to 1.2.0-pre1 (#2039) --- Cargo.lock | 322 ++++++++++---------- account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- common/Cargo.toml | 2 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 +++--- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 +++---- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 +++--- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 +++---- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 2 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 2 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 176 files changed, 530 insertions(+), 530 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 298a097fb8..45f3bf5200 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2015,7 +2015,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "cbindgen", @@ -2197,7 +2197,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "criterion", "curve25519-dalek", @@ -2225,7 +2225,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2241,7 +2241,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "grpcio", @@ -2256,7 +2256,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "anyhow", @@ -2293,7 +2293,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "bs58", "cargo-emit", @@ -2329,7 +2329,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "aes-gcm", @@ -2354,7 +2354,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "cargo-emit", @@ -2372,7 +2372,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "bincode", @@ -2404,7 +2404,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2417,7 +2417,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2437,7 +2437,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -2448,7 +2448,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2458,7 +2458,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2483,7 +2483,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "backtrace", "binascii", @@ -2520,7 +2520,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "cookie", @@ -2549,7 +2549,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2560,7 +2560,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "futures", @@ -2581,7 +2581,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2606,7 +2606,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "hex", @@ -2627,7 +2627,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2635,7 +2635,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "hex", @@ -2671,7 +2671,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2684,7 +2684,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2706,7 +2706,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2735,7 +2735,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "crossbeam-channel", "maplit", @@ -2758,7 +2758,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "mc-common", @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "chrono", @@ -2832,7 +2832,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "clap 3.1.18", @@ -2857,7 +2857,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2877,7 +2877,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "digest 0.10.3", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2906,7 +2906,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "proc-macro2", "quote", @@ -2915,7 +2915,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2923,7 +2923,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2932,7 +2932,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2940,7 +2940,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "blake2", "digest 0.10.3", @@ -2949,7 +2949,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "curve25519-dalek", @@ -2982,7 +2982,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "displaydoc", @@ -2996,7 +2996,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3010,7 +3010,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "aes-gcm", @@ -3031,7 +3031,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3042,7 +3042,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3055,7 +3055,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3067,7 +3067,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3078,7 +3078,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3089,7 +3089,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "displaydoc", @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3153,7 +3153,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "cookie", @@ -3177,7 +3177,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3216,7 +3216,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "criterion", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -3268,7 +3268,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3276,7 +3276,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3309,7 +3309,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3322,7 +3322,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "dirs", @@ -3379,7 +3379,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3395,7 +3395,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "grpcio", @@ -3416,7 +3416,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3445,7 +3445,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -3463,7 +3463,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3471,7 +3471,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3507,7 +3507,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3560,7 +3560,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3576,7 +3576,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "grpcio", @@ -3605,14 +3605,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3623,7 +3623,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "aligned-cmov", @@ -3640,7 +3640,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "lazy_static", "mc-common", @@ -3648,7 +3648,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -3700,7 +3700,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "futures", @@ -3719,7 +3719,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-util-serial", "prost", @@ -3728,7 +3728,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "binascii", @@ -3750,7 +3750,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "grpcio", @@ -3767,7 +3767,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3803,7 +3803,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3813,7 +3813,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-account-keys", @@ -3831,7 +3831,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3839,7 +3839,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3885,7 +3885,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-account-keys", @@ -3906,7 +3906,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3917,7 +3917,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -3932,7 +3932,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "chrono", "clap 3.1.18", @@ -3965,7 +3965,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3996,7 +3996,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4027,7 +4027,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "crc", "displaydoc", @@ -4047,7 +4047,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-common", "mc-util-uri", @@ -4055,7 +4055,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "grpcio", "mc-attest-core", @@ -4075,7 +4075,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "criterion", @@ -4110,7 +4110,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -4128,7 +4128,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4136,7 +4136,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4158,7 +4158,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4171,7 +4171,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "grpcio", @@ -4190,7 +4190,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-account-keys", @@ -4213,7 +4213,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4263,7 +4263,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "lazy_static", @@ -4289,7 +4289,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "dirs", @@ -4311,7 +4311,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "mc-api", @@ -4322,7 +4322,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4335,7 +4335,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4366,7 +4366,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4399,7 +4399,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "futures", @@ -4413,7 +4413,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4477,7 +4477,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "futures", @@ -4495,7 +4495,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "grpcio", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4602,7 +4602,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "grpcio", "hex", @@ -4625,7 +4625,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cc", "lazy_static", @@ -4635,7 +4635,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4643,7 +4643,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4652,7 +4652,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4660,7 +4660,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4669,21 +4669,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -4694,7 +4694,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -4710,7 +4710,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4720,18 +4720,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-urts" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-common", "mc-sgx-build", @@ -4742,7 +4742,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "hex", "mc-account-keys", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-account-keys", "mc-api", @@ -4764,7 +4764,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-util-test-vector", "serde", @@ -4773,7 +4773,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "hex", "mc-account-keys", @@ -4788,7 +4788,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "hex", "mc-account-keys", @@ -4810,7 +4810,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "bulletproofs-og", @@ -4852,7 +4852,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4869,7 +4869,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4896,7 +4896,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "hex", @@ -4905,7 +4905,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4921,7 +4921,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4929,7 +4929,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "json", @@ -4937,7 +4937,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "displaydoc", @@ -4948,7 +4948,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cc", @@ -4967,7 +4967,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "binascii", @@ -4979,18 +4979,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-util-from-random" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "hex", @@ -5009,7 +5009,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "clap 3.1.18", @@ -5043,7 +5043,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "grpcio", @@ -5054,7 +5054,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "hex", @@ -5065,11 +5065,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-util-keyfile" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "clap 3.1.18", @@ -5097,7 +5097,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5107,7 +5107,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "proc-macro2", "quote", @@ -5116,7 +5116,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5124,7 +5124,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "chrono", "grpcio", @@ -5137,7 +5137,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "itertools", "mc-sgx-css", @@ -5145,7 +5145,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "generic-array", "prost", @@ -5155,7 +5155,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "hex", @@ -5168,7 +5168,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "prost", "serde", @@ -5177,7 +5177,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5188,7 +5188,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "itertools", @@ -5202,7 +5202,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "serde", "serde_json", @@ -5210,7 +5210,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "proc-macro2", "quote", @@ -5219,7 +5219,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "displaydoc", @@ -5237,7 +5237,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5281,7 +5281,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 74dfafc5aa..6b17d80fa5 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index 7f4a8491b4..2e81156d9b 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index 735c4f1e43..ae0da88d90 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index aac415a924..369db4c619 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/api/Cargo.toml b/api/Cargo.toml index 9036d5c2eb..5efbf4495b 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index a0da4ea396..1a5527fb9d 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index c5e8584e04..6ad6ca0b84 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index 47c96bc2c8..c5b62e2dc5 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index 649395b339..f2706b741d 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index 3f1ad1fc71..ac4b73ffe6 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index 3136bf87df..789be9a4fd 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index db7b6c410e..25a058bc44 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index 9c50a167f5..a9e203304b 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/common/Cargo.toml b/common/Cargo.toml index 8abe7de47c..6ad81280d6 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/Cargo.toml b/connection/Cargo.toml index 6fb3c38a24..8cc80b51f8 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index 54920ff308..66ccdce1c2 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index ad0f2235d4..6831034085 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index 794a35ded1..ba3d6f7cfd 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index 9ec51c84a9..60a7c0255b 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index 38b39f4936..b867c8d087 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index e478d46656..0d8e64b84c 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index d0e0854824..3169d18ff0 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index 775ba0e034..c99346f035 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index c9bbfaf608..ea7297f860 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-build" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-transaction-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index 7d421b7eb1..51fc6dd709 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index f7c253bea6..9f2c8cd353 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index a740bad08a..b7db57613b 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index 7e357570d8..4de4a8d410 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index b55ce790d8..66b049087b 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index 475d0b9ae6..1bb070b430 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index c8c95eeab1..6a5e661a47 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index 850a45a76f..f0b996a1be 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index 0dfc34c7b8..ddb7b90f88 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index 2fc2241265..cd0f0114c0 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index 5e47d9bfe4..1162e6fa9d 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index 715b18cc49..ae1160422a 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index 616897e62d..d1fc4edba5 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index 96a9d5ed55..0393a85668 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index ff20beac10..de5c5dd2ad 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index 9b1db96174..1ae75f3849 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index ca6dbfaf68..6ef9716e94 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index 8c70279142..ef0ff91d6b 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index 867ac76b51..d880306e00 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index 7da6f30e97..552aee3640 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 5a4a283f23..12803ebd8f 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index fbecdb1a90..0627ed6719 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index c47f881de3..066d15b0a5 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index 1fb6310eca..36c6d16195 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index 94c7ba266f..ecd69cd1d5 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index 8d8d517aaa..fff2a4f5b3 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 32ea55b91f..5864eb2ffa 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index 4e8e1ca19c..50ed3a73f7 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index 6f9435f3b2..6d507972a7 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index bb692cd578..6a54ba4b49 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index ad1149b4c2..e9763914fd 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index 4e25821570..c413600eb4 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 7b79dbc8f0..3124c993bb 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-build" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-transaction-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index 838fe62597..7d5838d229 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index c3c5f6466a..9223f3be63 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index 065540b110..0b61e2d0d7 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index 876dfe1f39..4967a3eb95 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index f99dee5fed..25bd207f9a 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index a6099fd472..5c8912864f 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index 786159578b..fefc595207 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index d3b040fd5e..4c4ddff0d2 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index e2b6aadf0f..963528ecfb 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 7f62caa27c..5977ac1993 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-build" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-transaction-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index b5034647bc..5c044ec328 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index 8ef6ea4f81..9d644af734 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index 43d5c69e9f..61fd4253cd 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index d54dafea58..f64f65db3f 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index 8d0196567c..2e182f0e4d 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index b39d3cd8f1..05ed53eddd 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index 4bb0685b63..37aa010bf0 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index 09c4c054c6..29958f8567 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 21cafc9540..4ffe187ca8 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index 901aff6dcd..532b579957 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index 3619edfdbf..3ae9281c63 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index 7cd11ea4c8..25959ec5cd 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index 79111a02db..40fa6ae31d 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index f6ac46f2f4..a081c409b6 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index dbb09a5219..8c94172a09 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index 518a21cab2..a7112b36ce 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index 0d0285c5d5..83e617941e 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index 798140df77..744450d11d 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index 2ffaed77e4..ce39cefca2 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index 7d3b52b515..ab981a8882 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index 09c90cfce3..5cb4b63872 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index cab75e7219..959cddbe33 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index c130884677..9e13621aa2 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 982dab205c..8360826050 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index 373ee62da4..b420ff26da 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index 6a2d7514f4..ea0330c703 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index 0aa9ee8df2..a991a9baf5 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index e08f638509..b2a2bcdfd6 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index 5f05687926..b3fcc076dd 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index 0a9ead9ead..2d3569cfd6 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index c7ebcdbd28..d64a7c8e6b 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index d5a853e1c3..78b25ea74e 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index 02b70b4816..aaed4f8425 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index cb288a2001..e93d4348ae 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-build" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" [[package]] name = "mc-transaction-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index 120e337056..080b59cd9b 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index 755a68d3d8..e251080711 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index 7cd74da152..24847d557d 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index 13d47b62d8..5c0c0a4ab2 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index c325cf738e..c4271c68c4 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index 1efa145089..b267b7c510 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index 40ef8869a7..98238886e2 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index 6b109e9c55..9ca5c95a60 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index 574a63b70b..f8835b5050 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index ef93f430e4..f07527f2e6 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index 40c580c21c..ab439b2287 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index 14921fdce2..d0725de812 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index da48a1be48..3af943cbb9 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index dececd7783..f01b3c0062 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index 38a50628ba..224e1e6124 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/peers/Cargo.toml b/peers/Cargo.toml index 55121aa55c..c6dbba1b6b 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index 2a8487d014..7aba7ee781 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index 5dafaa6042..3c43712528 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index 44923b3d7a..2f966affd6 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index 9e4e4c4edf..53b5a4ded8 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index 1a5515cd99..8bba101275 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index 6c7f476d85..e5d1de8957 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index 476bc0b9d8..40645a898f 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index 016c80e00b..0aa49038aa 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index dbfeaa3074..15c54c3153 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index 65d5d0bb3f..691fd511e3 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index 232848092e..ce49f7142a 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index 11e4a16adf..614462c427 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index 442a07d49f..8b7a54f863 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index 0bf6c781ea..12ad04acad 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index 8d0a27b73d..a7f61994ac 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index ae833779bf..13a931cacc 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index a88438468e..866eeb1647 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index f38f8068fb..11309b7158 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index ee89875d98..f6a9e2c45f 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "1.2.0-pre0" +version = "1.2.0-pre1" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index 90a958a3d9..0a45b92541 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index f5bf7ac1ac..9eab65ba6a 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index 8009555f7f..02ec18f05f 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index c56aed595e..e90df4645c 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index 08f5484279..f58b5cbd21 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index 78b7101427..94535bec43 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index 8374f8d213..ebd25143c7 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 8dadfabc70..741cbb43f7 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index 7802225086..6681465222 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index d8b16d2d61..48dfa4ea6f 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index 775df54c0e..f8b37cc3f9 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index 93efed78fd..72c74a0f81 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index ed8fa936f4..d129f216a1 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index a01bd1579f..d50d008f65 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index 2b596339c7..5a465d0689 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index d199b5877a..6fefbf71b8 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index 7863b10aee..3325000cc6 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index ffc3914235..7826092a9a 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index f7b171a0c2..9aa93e34bb 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index b44ca0f92f..f6c3754d3e 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index 373e0c41f5..c4f54a8bb8 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index 6978bae066..c44beb8d99 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 4f9bf81d15..283f2adb9b 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index ee68242fe1..58b5706d2f 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index abfbf8b38b..ed4d62b91d 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index 92f6bec1c8..4a5f861b10 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index 6c45d904b9..f8e21dc766 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index 6f27f80726..72f832b797 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index a6b8fccca1..e276275322 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index 7ff8c5af18..6b8a6edbcf 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index 24328b2e15..ea7b393724 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index aa2d127926..675b05955a 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index b3536fc4f0..dd26c4c312 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index bb69b65757..a94275327a 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index 92d07585bc..cd90849450 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index d3fbf5b7ac..6cd3d5d10b 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index 20781fa60a..b904e3e9e7 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index b49fb2bd0f..61ce29aa4d 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index 62eaa37666..c4ce4aa2a5 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "1.2.0-pre0" +version = "1.2.0-pre1" authors = ["MobileCoin"] edition = "2018" From d2718bca690c9156505b79cea6940aa0ae31c6db Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Thu, 26 May 2022 14:18:48 -0500 Subject: [PATCH 23/77] CD for dynamic development environments (#2054) CD for dynamic development environments --- .dockerignore | 1 - .github/actionlint.yaml | 5 + .../action.yaml | 31 + .../mobilecoin-cache-go-binaries/action.yaml | 29 + .../action.yaml | 33 + .../mobilecoin-cache-seeds/action.yaml | 27 + .../android-bindings-dispatch.yml} | 0 .github/workflows/mobilecoin-dev-cd.yaml | 568 ++++++++++++++++++ .github/workflows/mobilecoin-dev-delete.yaml | 35 ++ .../mobilecoin-dispatch-dev-delete.yaml | 34 +- .../mobilecoin-dispatch-dev-deploy.yaml | 80 ++- .../mobilecoin-dispatch-dev-reset.yaml | 20 +- .../mobilecoin-dispatch-dev-test.yaml | 50 +- ...ilecoin-dispatch-dev-update-consensus.yaml | 63 +- .../mobilecoin-workflow-dev-deploy.yaml | 383 ++++++++++++ .../mobilecoin-workflow-dev-reset.yaml | 100 +++ .../mobilecoin-workflow-dev-test.yaml | 348 +++++++++++ ...ilecoin-workflow-dev-update-consensus.yaml | 177 ++++++ .gitignore | 10 + .internal-ci/README.md | 116 ++++ .../docker/Dockerfile.bootstrap-tools | 67 +++ .internal-ci/docker/Dockerfile.fog-ledger | 35 ++ .../docker/Dockerfile.fog-test-client | 58 ++ .internal-ci/docker/Dockerfile.fogingest | 34 ++ .internal-ci/docker/Dockerfile.fogreport | 29 + .internal-ci/docker/Dockerfile.fogview | 33 + .../docker/Dockerfile.go-grpc-gateway | 16 + .internal-ci/docker/Dockerfile.mobilecoind | 48 ++ .internal-ci/docker/Dockerfile.node_hw | 44 ++ .internal-ci/docker/Dockerfile.runtime-base | 41 ++ .internal-ci/docker/Dockerfile.watcher | 17 + .../docker/entrypoints/bootstrap-tools.sh | 6 + .../docker/entrypoints/fog-test-client.sh | 56 ++ .../docker/entrypoints/go-grpc-gateway.sh | 19 + .../support/intel-sgx-archive-keyring.gpg | Bin 0 -> 362 bytes .../helm/consensus-node-config/.helmignore | 23 + .../helm/consensus-node-config/Chart.yaml | 7 + .../consensus-node-config/templates/NOTES.txt | 5 + .../templates/_helpers.tpl | 70 +++ .../templates/node-config-configmap.yaml | 11 + .../node-ledger-distribution-secret.yaml | 17 + .../templates/node-msg-signer-key-secret.yaml | 10 + .../node-network-config-configmap.yaml | 39 ++ .../node-tokens-config-configmap.yaml | 12 + .../helm/consensus-node-config/values.yaml | 58 ++ .internal-ci/helm/consensus-node/Chart.yaml | 18 + .internal-ci/helm/consensus-node/README.md | 26 + .../helm/consensus-node/templates/NOTES.txt | 17 + .../consensus-node/templates/_helpers.tpl | 111 ++++ .../templates/client-grpc-ingress.yaml | 46 ++ .../templates/gateway-deployment.yaml | 36 ++ .../templates/gateway-ingress.yaml | 25 + .../templates/gateway-service.yaml | 17 + .../templates/node-certificate.yaml | 23 + .../templates/node-data-volume.yaml | 11 + .../templates/node-deployment.yaml | 218 +++++++ .../templates/node-service.yaml | 25 + .../templates/node-servicemonitor.yaml | 23 + .../templates/peer-grpc-ingress.yaml | 53 ++ .../supervisor-admin-gateway-configmap.yaml | 21 + ...upervisor-consensus-service-configmap.yaml | 31 + .../supervisor-daemon-configmap.yaml | 11 + ...ervisor-ledger-distribution-configmap.yaml | 23 + .../templates/supervisor-sgx-configmap.yaml | 17 + .internal-ci/helm/consensus-node/values.yaml | 208 +++++++ .../helm/fog-ingest-config/.helmignore | 23 + .../helm/fog-ingest-config/Chart.yaml | 7 + .../fog-ingest-config/templates/NOTES.txt | 1 + .../fog-ingest-config/templates/_helpers.tpl | 70 +++ .../templates/fog-ingest-configmap.yaml | 9 + .../fog-recovery-postgresql-configmap.yaml | 23 + .../fog-recovery-postgresql-secret.yaml | 18 + .../helm/fog-ingest-config/values.yaml | 29 + .internal-ci/helm/fog-ingest/.helmignore | 23 + .internal-ci/helm/fog-ingest/Chart.yaml | 18 + .internal-ci/helm/fog-ingest/README.md | 153 +++++ .../helm/fog-ingest/templates/NOTES.txt | 17 + .../helm/fog-ingest/templates/_helpers.tpl | 73 +++ .../templates/fog-ingest-service.yaml | 25 + .../templates/fog-ingest-servicmonitor.yaml | 21 + .../templates/fog-ingest-statefulset.yaml | 206 +++++++ .../supervisord-admin-configmap.yaml | 21 + .../supervisord-daemon-configmap.yaml | 11 + .../supervisord-fog-ingest-configmap.yaml | 30 + .../templates/supervisord-sgx-configmap.yaml | 17 + .../templates/toolbox-deployment.yaml | 132 ++++ .internal-ci/helm/fog-ingest/values.yaml | 128 ++++ .../helm/fog-services-config/.helmignore | 23 + .../helm/fog-services-config/Chart.yaml | 7 + .../fog-services-config/templates/NOTES.txt | 1 + .../templates/_helpers.tpl | 121 ++++ .../templates/fog-ledger-configmap.yaml | 9 + .../fog-ledger-grpc-cookie-secret.yaml | 10 + .../fog-ledger-http-cookie-secret.yaml | 10 + .../templates/fog-public-fqdn-configmap.yaml | 10 + .../fog-recovery-postgresql-secret.yaml | 18 + ...ecovery-reader-0-postgresql-configmap.yaml | 23 + .../templates/fog-report-configmap.yaml | 9 + .../fog-report-signing-cert-secret.yaml | 11 + .../templates/fog-view-configmap.yaml | 9 + .../fog-view-grpc-cookie-secret.yaml | 10 + .../fog-view-http-cookie-secret.yaml | 10 + .../helm/fog-services-config/values.yaml | 75 +++ .internal-ci/helm/fog-services/.helmignore | 23 + .internal-ci/helm/fog-services/Chart.yaml | 18 + .internal-ci/helm/fog-services/README.md | 221 +++++++ .../helm/fog-services/templates/NOTES.txt | 20 + .../helm/fog-services/templates/_helpers.tpl | 152 +++++ .../templates/fog-ledger-grpc-ingress.yaml | 47 ++ .../templates/fog-ledger-http-ingress.yaml | 47 ++ .../templates/fog-ledger-service.yaml | 23 + .../templates/fog-ledger-servicmonitor.yaml | 21 + .../templates/fog-ledger-statefulset.yaml | 189 ++++++ .../templates/fog-report-deployment.yaml | 192 ++++++ .../templates/fog-report-grpc-ingress.yaml | 31 + .../templates/fog-report-http-ingress.yaml | 31 + .../templates/fog-report-service.yaml | 23 + .../templates/fog-report-servicmonitor.yaml | 21 + .../templates/fog-view-deployment.yaml | 204 +++++++ .../templates/fog-view-grpc-ingress.yaml | 26 + .../templates/fog-view-http-ingress.yaml | 26 + .../templates/fog-view-service.yaml | 23 + .../templates/fog-view-servicmonitor.yaml | 22 + .../supervisord-admin-configmap.yaml | 21 + .../supervisord-daemon-configmap.yaml | 11 + .../supervisord-fog-ledger-configmap.yaml | 30 + .../supervisord-fog-report-configmap.yaml | 23 + .../supervisord-fog-view-configmap.yaml | 28 + .../templates/supervisord-sgx-configmap.yaml | 17 + .internal-ci/helm/fog-services/values.yaml | 249 ++++++++ .internal-ci/helm/fog-test-client/.helmignore | 23 + .internal-ci/helm/fog-test-client/Chart.yaml | 7 + .internal-ci/helm/fog-test-client/README.md | 37 ++ .../helm/fog-test-client/scripts/apply-k8s.sh | 26 + .../scripts/download_sigstruct.sh | 32 + .../fog-test-client/scripts/generate-k8s.sh | 74 +++ .../helm/fog-test-client/scripts/setup.sh | 102 ++++ .../helm/fog-test-client/templates/NOTES.txt | 16 + .../fog-test-client/templates/_helpers.tpl | 75 +++ .../templates/fog-test-client-deployment.yaml | 132 ++++ .../templates/fog-test-client-service.yaml | 17 + .../fog-test-client-serviceMonitor.yaml | 23 + .internal-ci/helm/fog-test-client/values.yaml | 72 +++ .../helm/mc-core-common-config/.helmignore | 23 + .../helm/mc-core-common-config/Chart.yaml | 7 + .../mc-core-common-config/templates/NOTES.txt | 1 + .../templates/_helpers.tpl | 71 +++ .../templates/client-auth-token-secret.yaml | 10 + ...fog-supervisord-mobilecoind-configmap.yaml | 26 + .../templates/ias-secret.yaml | 11 + .../templates/ipinfo-secret.yaml | 10 + .../mobilecoin-network-configmap.yaml | 10 + ...ind-supervisord-mobilecoind-configmap.yaml | 27 + .../templates/sentry-configmap.yaml | 9 + .../helm/mc-core-common-config/values.yaml | 36 ++ .../helm/mc-core-dev-env-setup/Chart.yaml | 48 ++ .../helm/mc-core-dev-env-setup/README.md | 26 + .../mc-core-dev-env-setup/templates/NOTES.txt | 0 .../templates/_helpers.tpl | 45 ++ .../helm/mc-core-dev-env-setup/values.yaml | 129 ++++ .internal-ci/helm/mobilecoind/Chart.yaml | 13 + .../helm/mobilecoind/templates/_helpers.tpl | 57 ++ .../templates/mint-auditor-service.yaml | 16 + .../templates/mobilecoind-deployment.yaml | 131 ++++ .../templates/mobilecoind-json-service.yaml | 16 + .../templates/mobilecoind-service.yaml | 16 + .../supervisord-daemon-configmap.yaml | 11 + .../supervisord-mint-auditor-configmap.yaml | 20 + ...upervisord-mobilecoind-json-configmap.yaml | 18 + .internal-ci/helm/mobilecoind/values.yaml | 76 +++ .internal-ci/helm/watcher/Chart.yaml | 7 + .../helm/watcher/templates/_helpers.tpl | 97 +++ .../templates/watcher-backup-scripts.yaml | 94 +++ .../watcher/templates/watcher-config.yaml | 19 + .../watcher/templates/watcher-deployment.yaml | 159 +++++ .../watcher-s3-credentials-secret.yaml | 16 + .../watcher/templates/watcher-service.yaml | 18 + .../watcher/templates/watcher-volume.yaml | 19 + .internal-ci/helm/watcher/values.yaml | 37 ++ .internal-ci/sample_data/ledger/.keep | 1 + .internal-ci/test/fog-distribution-test.sh | 28 + .internal-ci/test/fog-test-client.sh | 72 +++ .internal-ci/test/mint-auditor-test.sh | 93 +++ .internal-ci/test/minting-config-tx-test.sh | 60 ++ .internal-ci/test/minting-tx-test.sh | 78 +++ .../test/mobilecoind-integration-test.sh | 65 ++ .../test/mobilecoind-json-integration-test.sh | 91 +++ .internal-ci/util/copy_account_keys.sh | 74 +++ .internal-ci/util/drain_accounts.sh | 113 ++++ .internal-ci/util/generate_dev_values.sh | 102 ++++ .internal-ci/util/generate_ed25519_keys.sh | 54 ++ .internal-ci/util/generate_minting_keys.sh | 50 ++ .internal-ci/util/generate_origin_data.sh | 98 +++ .internal-ci/util/generate_tokens_config.sh | 45 ++ .internal-ci/util/generate_wallet_seeds.sh | 95 +++ .../util/manual_republish_existing_build.sh | 90 +++ .internal-ci/util/metadata.sh | 90 +++ .internal-ci/util/print_details.sh | 126 ++++ .internal-ci/util/sample-keys.1.1.3 | Bin 0 -> 6443408 bytes .internal-ci/util/tokens.base.json | 17 + 200 files changed, 10351 insertions(+), 31 deletions(-) create mode 100644 .github/actionlint.yaml create mode 100644 .github/actions/mobilecoin-cache-cargo-package/action.yaml create mode 100644 .github/actions/mobilecoin-cache-go-binaries/action.yaml create mode 100644 .github/actions/mobilecoin-cache-rust-binaries/action.yaml create mode 100644 .github/actions/mobilecoin-cache-seeds/action.yaml rename .github/{.workflow/android-bindings.yml => workflows/android-bindings-dispatch.yml} (100%) create mode 100644 .github/workflows/mobilecoin-dev-cd.yaml create mode 100644 .github/workflows/mobilecoin-dev-delete.yaml create mode 100644 .github/workflows/mobilecoin-workflow-dev-deploy.yaml create mode 100644 .github/workflows/mobilecoin-workflow-dev-reset.yaml create mode 100644 .github/workflows/mobilecoin-workflow-dev-test.yaml create mode 100644 .github/workflows/mobilecoin-workflow-dev-update-consensus.yaml create mode 100644 .internal-ci/README.md create mode 100644 .internal-ci/docker/Dockerfile.bootstrap-tools create mode 100644 .internal-ci/docker/Dockerfile.fog-ledger create mode 100644 .internal-ci/docker/Dockerfile.fog-test-client create mode 100644 .internal-ci/docker/Dockerfile.fogingest create mode 100644 .internal-ci/docker/Dockerfile.fogreport create mode 100644 .internal-ci/docker/Dockerfile.fogview create mode 100644 .internal-ci/docker/Dockerfile.go-grpc-gateway create mode 100644 .internal-ci/docker/Dockerfile.mobilecoind create mode 100644 .internal-ci/docker/Dockerfile.node_hw create mode 100644 .internal-ci/docker/Dockerfile.runtime-base create mode 100644 .internal-ci/docker/Dockerfile.watcher create mode 100755 .internal-ci/docker/entrypoints/bootstrap-tools.sh create mode 100755 .internal-ci/docker/entrypoints/fog-test-client.sh create mode 100755 .internal-ci/docker/entrypoints/go-grpc-gateway.sh create mode 100644 .internal-ci/docker/support/intel-sgx-archive-keyring.gpg create mode 100644 .internal-ci/helm/consensus-node-config/.helmignore create mode 100644 .internal-ci/helm/consensus-node-config/Chart.yaml create mode 100644 .internal-ci/helm/consensus-node-config/templates/NOTES.txt create mode 100644 .internal-ci/helm/consensus-node-config/templates/_helpers.tpl create mode 100644 .internal-ci/helm/consensus-node-config/templates/node-config-configmap.yaml create mode 100644 .internal-ci/helm/consensus-node-config/templates/node-ledger-distribution-secret.yaml create mode 100644 .internal-ci/helm/consensus-node-config/templates/node-msg-signer-key-secret.yaml create mode 100644 .internal-ci/helm/consensus-node-config/templates/node-network-config-configmap.yaml create mode 100644 .internal-ci/helm/consensus-node-config/templates/node-tokens-config-configmap.yaml create mode 100644 .internal-ci/helm/consensus-node-config/values.yaml create mode 100644 .internal-ci/helm/consensus-node/Chart.yaml create mode 100644 .internal-ci/helm/consensus-node/README.md create mode 100644 .internal-ci/helm/consensus-node/templates/NOTES.txt create mode 100644 .internal-ci/helm/consensus-node/templates/_helpers.tpl create mode 100644 .internal-ci/helm/consensus-node/templates/client-grpc-ingress.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/gateway-deployment.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/gateway-ingress.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/gateway-service.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/node-certificate.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/node-data-volume.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/node-deployment.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/node-service.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/node-servicemonitor.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/peer-grpc-ingress.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-admin-gateway-configmap.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-consensus-service-configmap.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-daemon-configmap.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-ledger-distribution-configmap.yaml create mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-sgx-configmap.yaml create mode 100644 .internal-ci/helm/consensus-node/values.yaml create mode 100644 .internal-ci/helm/fog-ingest-config/.helmignore create mode 100644 .internal-ci/helm/fog-ingest-config/Chart.yaml create mode 100644 .internal-ci/helm/fog-ingest-config/templates/NOTES.txt create mode 100644 .internal-ci/helm/fog-ingest-config/templates/_helpers.tpl create mode 100644 .internal-ci/helm/fog-ingest-config/templates/fog-ingest-configmap.yaml create mode 100644 .internal-ci/helm/fog-ingest-config/templates/fog-recovery-postgresql-configmap.yaml create mode 100644 .internal-ci/helm/fog-ingest-config/templates/fog-recovery-postgresql-secret.yaml create mode 100644 .internal-ci/helm/fog-ingest-config/values.yaml create mode 100644 .internal-ci/helm/fog-ingest/.helmignore create mode 100644 .internal-ci/helm/fog-ingest/Chart.yaml create mode 100644 .internal-ci/helm/fog-ingest/README.md create mode 100644 .internal-ci/helm/fog-ingest/templates/NOTES.txt create mode 100644 .internal-ci/helm/fog-ingest/templates/_helpers.tpl create mode 100644 .internal-ci/helm/fog-ingest/templates/fog-ingest-service.yaml create mode 100644 .internal-ci/helm/fog-ingest/templates/fog-ingest-servicmonitor.yaml create mode 100644 .internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml create mode 100644 .internal-ci/helm/fog-ingest/templates/supervisord-admin-configmap.yaml create mode 100644 .internal-ci/helm/fog-ingest/templates/supervisord-daemon-configmap.yaml create mode 100644 .internal-ci/helm/fog-ingest/templates/supervisord-fog-ingest-configmap.yaml create mode 100644 .internal-ci/helm/fog-ingest/templates/supervisord-sgx-configmap.yaml create mode 100644 .internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml create mode 100644 .internal-ci/helm/fog-ingest/values.yaml create mode 100644 .internal-ci/helm/fog-services-config/.helmignore create mode 100644 .internal-ci/helm/fog-services-config/Chart.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/NOTES.txt create mode 100644 .internal-ci/helm/fog-services-config/templates/_helpers.tpl create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-ledger-configmap.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-ledger-grpc-cookie-secret.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-ledger-http-cookie-secret.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-public-fqdn-configmap.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-recovery-postgresql-secret.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-recovery-reader-0-postgresql-configmap.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-report-configmap.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-report-signing-cert-secret.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-view-configmap.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-view-grpc-cookie-secret.yaml create mode 100644 .internal-ci/helm/fog-services-config/templates/fog-view-http-cookie-secret.yaml create mode 100644 .internal-ci/helm/fog-services-config/values.yaml create mode 100644 .internal-ci/helm/fog-services/.helmignore create mode 100644 .internal-ci/helm/fog-services/Chart.yaml create mode 100644 .internal-ci/helm/fog-services/README.md create mode 100644 .internal-ci/helm/fog-services/templates/NOTES.txt create mode 100644 .internal-ci/helm/fog-services/templates/_helpers.tpl create mode 100644 .internal-ci/helm/fog-services/templates/fog-ledger-grpc-ingress.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-ledger-http-ingress.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-ledger-service.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-ledger-servicmonitor.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-report-deployment.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-report-grpc-ingress.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-report-http-ingress.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-report-service.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-report-servicmonitor.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-view-deployment.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-view-grpc-ingress.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-view-http-ingress.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-view-service.yaml create mode 100644 .internal-ci/helm/fog-services/templates/fog-view-servicmonitor.yaml create mode 100644 .internal-ci/helm/fog-services/templates/supervisord-admin-configmap.yaml create mode 100644 .internal-ci/helm/fog-services/templates/supervisord-daemon-configmap.yaml create mode 100644 .internal-ci/helm/fog-services/templates/supervisord-fog-ledger-configmap.yaml create mode 100644 .internal-ci/helm/fog-services/templates/supervisord-fog-report-configmap.yaml create mode 100644 .internal-ci/helm/fog-services/templates/supervisord-fog-view-configmap.yaml create mode 100644 .internal-ci/helm/fog-services/templates/supervisord-sgx-configmap.yaml create mode 100644 .internal-ci/helm/fog-services/values.yaml create mode 100644 .internal-ci/helm/fog-test-client/.helmignore create mode 100644 .internal-ci/helm/fog-test-client/Chart.yaml create mode 100644 .internal-ci/helm/fog-test-client/README.md create mode 100755 .internal-ci/helm/fog-test-client/scripts/apply-k8s.sh create mode 100755 .internal-ci/helm/fog-test-client/scripts/download_sigstruct.sh create mode 100755 .internal-ci/helm/fog-test-client/scripts/generate-k8s.sh create mode 100755 .internal-ci/helm/fog-test-client/scripts/setup.sh create mode 100644 .internal-ci/helm/fog-test-client/templates/NOTES.txt create mode 100644 .internal-ci/helm/fog-test-client/templates/_helpers.tpl create mode 100644 .internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml create mode 100644 .internal-ci/helm/fog-test-client/templates/fog-test-client-service.yaml create mode 100644 .internal-ci/helm/fog-test-client/templates/fog-test-client-serviceMonitor.yaml create mode 100644 .internal-ci/helm/fog-test-client/values.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/.helmignore create mode 100644 .internal-ci/helm/mc-core-common-config/Chart.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/templates/NOTES.txt create mode 100644 .internal-ci/helm/mc-core-common-config/templates/_helpers.tpl create mode 100644 .internal-ci/helm/mc-core-common-config/templates/client-auth-token-secret.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/templates/fog-supervisord-mobilecoind-configmap.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/templates/ias-secret.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/templates/ipinfo-secret.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/templates/mobilecoin-network-configmap.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/templates/mobilecoind-supervisord-mobilecoind-configmap.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/templates/sentry-configmap.yaml create mode 100644 .internal-ci/helm/mc-core-common-config/values.yaml create mode 100644 .internal-ci/helm/mc-core-dev-env-setup/Chart.yaml create mode 100644 .internal-ci/helm/mc-core-dev-env-setup/README.md create mode 100644 .internal-ci/helm/mc-core-dev-env-setup/templates/NOTES.txt create mode 100644 .internal-ci/helm/mc-core-dev-env-setup/templates/_helpers.tpl create mode 100644 .internal-ci/helm/mc-core-dev-env-setup/values.yaml create mode 100644 .internal-ci/helm/mobilecoind/Chart.yaml create mode 100644 .internal-ci/helm/mobilecoind/templates/_helpers.tpl create mode 100644 .internal-ci/helm/mobilecoind/templates/mint-auditor-service.yaml create mode 100644 .internal-ci/helm/mobilecoind/templates/mobilecoind-deployment.yaml create mode 100644 .internal-ci/helm/mobilecoind/templates/mobilecoind-json-service.yaml create mode 100644 .internal-ci/helm/mobilecoind/templates/mobilecoind-service.yaml create mode 100644 .internal-ci/helm/mobilecoind/templates/supervisord-daemon-configmap.yaml create mode 100644 .internal-ci/helm/mobilecoind/templates/supervisord-mint-auditor-configmap.yaml create mode 100644 .internal-ci/helm/mobilecoind/templates/supervisord-mobilecoind-json-configmap.yaml create mode 100644 .internal-ci/helm/mobilecoind/values.yaml create mode 100644 .internal-ci/helm/watcher/Chart.yaml create mode 100644 .internal-ci/helm/watcher/templates/_helpers.tpl create mode 100644 .internal-ci/helm/watcher/templates/watcher-backup-scripts.yaml create mode 100644 .internal-ci/helm/watcher/templates/watcher-config.yaml create mode 100644 .internal-ci/helm/watcher/templates/watcher-deployment.yaml create mode 100644 .internal-ci/helm/watcher/templates/watcher-s3-credentials-secret.yaml create mode 100644 .internal-ci/helm/watcher/templates/watcher-service.yaml create mode 100644 .internal-ci/helm/watcher/templates/watcher-volume.yaml create mode 100644 .internal-ci/helm/watcher/values.yaml create mode 100644 .internal-ci/sample_data/ledger/.keep create mode 100755 .internal-ci/test/fog-distribution-test.sh create mode 100755 .internal-ci/test/fog-test-client.sh create mode 100755 .internal-ci/test/mint-auditor-test.sh create mode 100755 .internal-ci/test/minting-config-tx-test.sh create mode 100755 .internal-ci/test/minting-tx-test.sh create mode 100755 .internal-ci/test/mobilecoind-integration-test.sh create mode 100755 .internal-ci/test/mobilecoind-json-integration-test.sh create mode 100755 .internal-ci/util/copy_account_keys.sh create mode 100755 .internal-ci/util/drain_accounts.sh create mode 100755 .internal-ci/util/generate_dev_values.sh create mode 100755 .internal-ci/util/generate_ed25519_keys.sh create mode 100755 .internal-ci/util/generate_minting_keys.sh create mode 100755 .internal-ci/util/generate_origin_data.sh create mode 100755 .internal-ci/util/generate_tokens_config.sh create mode 100755 .internal-ci/util/generate_wallet_seeds.sh create mode 100755 .internal-ci/util/manual_republish_existing_build.sh create mode 100755 .internal-ci/util/metadata.sh create mode 100755 .internal-ci/util/print_details.sh create mode 100755 .internal-ci/util/sample-keys.1.1.3 create mode 100644 .internal-ci/util/tokens.base.json diff --git a/.dockerignore b/.dockerignore index 26ab753bae..ef27703789 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,2 @@ .git/ cargo/ -target/ diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 0000000000..5826c623c5 --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,5 @@ +self-hosted-runner: + # Labels of self-hosted runner in array of string + labels: + - small + - large diff --git a/.github/actions/mobilecoin-cache-cargo-package/action.yaml b/.github/actions/mobilecoin-cache-cargo-package/action.yaml new file mode 100644 index 0000000000..91e7b1f0d2 --- /dev/null +++ b/.github/actions/mobilecoin-cache-cargo-package/action.yaml @@ -0,0 +1,31 @@ +name: Mobilecoin Cargo Package Cache +description: Standardized rust cargo package cache setup + +inputs: + cache_buster: + description: "string to make cache unique" + required: false + path: + description: "path to mount cache" + required: false + default: | + /opt/cargo/git + /opt/cargo/registry/index + /opt/cargo/registry/cache + +outputs: + cache-hit: + description: "did we get a cache hit?" + value: ${{ steps.rust_artifact_cache.outputs.cache-hit }} + +runs: + using: composite + steps: + - name: Cache rust build binaries + id: rust_artifact_cache + uses: actions/cache@v3 + with: + path: ${{ inputs.path }} + # Key is a hash of all the .rs, .proto and Cargo.toml files. + # if code changes, invalidate cache and rebuild + key: ${{ inputs.cache_buster }}-${{ runner.os }}-${{ hashFiles('**/Cargo.toml') }}-cargo-cache diff --git a/.github/actions/mobilecoin-cache-go-binaries/action.yaml b/.github/actions/mobilecoin-cache-go-binaries/action.yaml new file mode 100644 index 0000000000..21923b36a6 --- /dev/null +++ b/.github/actions/mobilecoin-cache-go-binaries/action.yaml @@ -0,0 +1,29 @@ +name: Mobilecoin Go Binaries Cache +description: Standardized go binary cache setup + +inputs: + cache_buster: + description: "string to make cache unique" + required: false + path: + description: "path to mount cache" + required: false + default: | + go_build_artifacts + +outputs: + cache-hit: + description: "did we get a cache hit?" + value: ${{ steps.rust_artifact_cache.outputs.cache-hit }} + +runs: + using: composite + steps: + - name: Cache rust build binaries + id: rust_artifact_cache + uses: actions/cache@v3 + with: + path: ${{ inputs.path }} + # Key is a hash of all the .go, .proto and go. files. + # if code changes, invalidate cache and rebuild + key: ${{ inputs.cache_buster }}-${{ runner.os }}-${{ hashFiles('go-grpc-gateway/**/*.go', 'go-grpc-gateway/go.*', '**/*.proto') }}-go-build-artifacts diff --git a/.github/actions/mobilecoin-cache-rust-binaries/action.yaml b/.github/actions/mobilecoin-cache-rust-binaries/action.yaml new file mode 100644 index 0000000000..59faba9bf5 --- /dev/null +++ b/.github/actions/mobilecoin-cache-rust-binaries/action.yaml @@ -0,0 +1,33 @@ +name: Mobilecoin Rust Binary Cache +description: Standardized rust binary cache setup + +inputs: + cache_buster: + description: "string to make cache unique" + required: false + path: + description: "path to mount cache" + required: false + default: | + rust_build_artifacts + # hash_files: + # description: "list of files/globs to hash" + # required: false + # default: "'**/*.rs', '**/*.proto', '**/Cargo.toml'" + +outputs: + cache-hit: + description: "did we get a cache hit?" + value: ${{ steps.rust_artifact_cache.outputs.cache-hit }} + +runs: + using: composite + steps: + - name: Cache rust build binaries + id: rust_artifact_cache + uses: actions/cache@v3 + with: + path: ${{ inputs.path }} + # Key is a hash of all the .rs, .proto and Cargo.toml files. + # if code changes, invalidate cache and rebuild + key: ${{ inputs.cache_buster }}-${{ runner.os }}-${{ hashFiles('**/*.rs', '**/*.proto', '**/Cargo.toml') }}-rust-build-artifacts diff --git a/.github/actions/mobilecoin-cache-seeds/action.yaml b/.github/actions/mobilecoin-cache-seeds/action.yaml new file mode 100644 index 0000000000..39acf0451a --- /dev/null +++ b/.github/actions/mobilecoin-cache-seeds/action.yaml @@ -0,0 +1,27 @@ +name: Mobilecoin Seeds Cache +description: Standardized cache setup for seeds + +inputs: + path: + description: "path to mount cache" + required: false + default: | + .tmp/seeds + cache_buster: + description: "string to make cache unique" + required: false + +outputs: + cache-hit: + description: "did we get a cache hit?" + value: ${{ steps.wallet_seeds.outputs.cache-hit }} + +runs: + using: composite + steps: + - name: Cache wallet seeds + id: wallet_seeds + uses: actions/cache@v3 + with: + path: ${{ inputs.path }} + key: ${{ inputs.cache_buster }}-${{ github.ref_name }}-seeds diff --git a/.github/.workflow/android-bindings.yml b/.github/workflows/android-bindings-dispatch.yml similarity index 100% rename from .github/.workflow/android-bindings.yml rename to .github/workflows/android-bindings-dispatch.yml diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml new file mode 100644 index 0000000000..242e059dcc --- /dev/null +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -0,0 +1,568 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Build, deploy to development. + +name: mobilecoin-dev-cd + +env: + CHART_REPO: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + DOCKER_ORG: mobilecoin + PREVIOUS_RELEASE: v1.1.3-dev + +on: + push: + branches: + - release/v[0-9]+.[0-9]+.[0-9]+ + - feature/* + - develop + +jobs: +############################################ +# Generate environment information +############################################ + generate-metadata: + name: 👾 Environment Info 👾 + runs-on: [self-hosted, Linux, small] + outputs: + branch: ${{ steps.meta.outputs.branch }} + namespace: ${{ steps.meta.outputs.namespace }} + tag: ${{ steps.meta.outputs.tag }} + docker_tag: ${{ steps.meta.outputs.docker_tag }} + docker_org: ${{ env.DOCKER_ORG }} + chart_repo: ${{ env.CHART_REPO }} + previous_release: ${{ env.PREVIOUS_RELEASE }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Generate version metadata + id: meta + shell: bash + run: | + .internal-ci/util/metadata.sh + + - name: 👾 Print Environment Details 👾 + shell: bash + env: + CHART_REPO: ${{ env.CHART_REPO }} + NAMESPACE: ${{ steps.meta.outputs.namespace }} + VERSION: ${{ steps.meta.outputs.tag }} + run: | + .internal-ci/util/print_details.sh + +######################################### +# Build binaries +######################################### + build-rust-hardware-projects: + runs-on: [self-hosted, Linux, large] + container: + image: mobilecoin/rust-sgx-base@sha256:6e9ec00ee70045392599cc3c25e74184e072e3d5a5d7abdd713c25207043afda + env: + ENCLAVE_SIGNING_KEY_PATH: ${{ github.workspace }}/.tmp/enclave_signing.pem + MINTING_TRUST_ROOT_PUBLIC_KEY_PEM: ${{ github.workspace }}/.tmp/minting_trust_root.public.pem + steps: + - name: Checkout + if: "! contains(github.event.head_commit.message, '[skip build]')" + uses: actions/checkout@v3 + + - name: Write environment values + if: "! contains(github.event.head_commit.message, '[skip build]')" + env: + ENCLAVE_SIGNING_KEY: ${{ secrets.DEV_ENCLAVE_SIGNING_KEY }} + MINTING_TRUST_ROOT_PUBLIC: ${{ secrets.DEV_MINTING_TRUST_ROOT_PUBLIC }} + run: | + mkdir -p "${GITHUB_WORKSPACE}/.tmp" + echo "${ENCLAVE_SIGNING_KEY}" > "${ENCLAVE_SIGNING_KEY_PATH}" + echo "${MINTING_TRUST_ROOT_PUBLIC}" > "${MINTING_TRUST_ROOT_PUBLIC_KEY_PEM}" + + - name: Cache rust build binaries + if: "! contains(github.event.head_commit.message, '[skip build]')" + id: rust_artifact_cache + uses: ./.github/actions/mobilecoin-cache-rust-binaries + with: + cache_buster: ${{ secrets.CACHE_BUSTER }} + + - name: Cache cargo packages + # We don't need cargo packages if we already have binaries. + if: | + steps.rust_artifact_cache.outputs.cache-hit != 'true' && + ! contains(github.event.head_commit.message, '[skip build]') + uses: ./.github/actions/mobilecoin-cache-cargo-package + with: + cache_buster: ${{ secrets.CACHE_BUSTER }} + + - name: Build rust hardware projects + if: | + steps.rust_artifact_cache.outputs.cache-hit != 'true' && + ! contains(github.event.head_commit.message, '[skip build]') + env: + IAS_MODE: DEV + SGX_MODE: HW + RUST_BACKTRACE: full + MOB_RELEASE: 1 + CONSENSUS_ENCLAVE_PRIVKEY: ${{ env.ENCLAVE_SIGNING_KEY_PATH }} + LEDGER_ENCLAVE_PRIVKEY: ${{ env.ENCLAVE_SIGNING_KEY_PATH }} + VIEW_ENCLAVE_PRIVKEY: ${{ env.ENCLAVE_SIGNING_KEY_PATH }} + INGEST_ENCLAVE_PRIVKEY: ${{ env.ENCLAVE_SIGNING_KEY_PATH }} + run: | + ls -al "${ENCLAVE_SIGNING_KEY_PATH}" + cargo build --release \ + -p mc-admin-http-gateway \ + -p mc-consensus-mint-client \ + -p mc-consensus-service \ + -p mc-fog-distribution \ + -p mc-fog-ingest-server \ + -p mc-fog-ingest-client \ + -p mc-fog-ledger-server \ + -p mc-fog-report-cli \ + -p mc-fog-report-server \ + -p mc-fog-sql-recovery-db \ + -p mc-fog-test-client \ + -p mc-fog-view-server \ + -p mc-ledger-distribution \ + -p mc-ledger-from-archive \ + -p mc-ledger-migration \ + -p mc-mint-auditor \ + -p mc-mobilecoind \ + -p mc-mobilecoind-json \ + -p mc-util-generate-sample-ledger \ + -p mc-util-grpc-admin-tool \ + -p mc-util-grpc-token-generator \ + -p mc-util-keyfile \ + -p mc-util-seeded-ed25519-key-gen \ + -p mc-watcher + + - name: Copy artifacts to cache + if: | + steps.rust_artifact_cache.outputs.cache-hit != 'true' && + ! contains(github.event.head_commit.message, '[skip build]') + run: | + mkdir -p rust_build_artifacts + find target/release -maxdepth 1 -executable -type f -exec cp "{}" rust_build_artifacts/ \; + find target/release -maxdepth 1 -name "*.signed.so" -exec cp "{}" rust_build_artifacts/ \; + + - name: Create css measurements + if: | + steps.rust_artifact_cache.outputs.cache-hit != 'true' && + ! contains(github.event.head_commit.message, '[skip build]') + shell: bash + run: | + cd rust_build_artifacts + for i in *.signed.so + do + css=$(echo -n "${i}" | sed -r 's/(.*)\.signed\.so/\1/') + sgx_sign dump -enclave "${i}" -dumpfile /dev/null -cssfile ${css}.css + done + + - name: Check artifacts + if: "! contains(github.event.head_commit.message, '[skip build]')" + run: | + ls -alR rust_build_artifacts + + - name: Upload artifacts + if: "! contains(github.event.head_commit.message, '[skip build]')" + uses: actions/upload-artifact@v3 + with: + name: rust-binaries + path: rust_build_artifacts/ + + build-go-projects: + runs-on: [self-hosted, Linux, large] + container: + image: golang:1.16.4 + steps: + - name: Checkout + if: "! contains(github.event.head_commit.message, '[skip build]')" + uses: actions/checkout@v3 + + - name: Add protobuf-compiler + if: "! contains(github.event.head_commit.message, '[skip build]')" + run: | + apt update + apt install -y protobuf-compiler zstd + + - name: Cache go build binaries + if: "! contains(github.event.head_commit.message, '[skip build]')" + id: go_artifact_cache + uses: ./.github/actions/mobilecoin-cache-go-binaries + with: + cache_buster: ${{ secrets.CACHE_BUSTER }} + + - name: Build go-grpc-gateway + if: | + steps.go_artifact_cache.outputs.cache-hit != 'true' && + ! contains(github.event.head_commit.message, '[skip build]') + run: | + cd go-grpc-gateway + ./install_tools.sh + ./build.sh + mkdir -p ../go_build_artifacts + cp grpc-proxy ../go_build_artifacts/ + + - name: check artifacts + if: "! contains(github.event.head_commit.message, '[skip build]')" + run: | + ls -alR go_build_artifacts + + - name: Upload Artifacts + if: "! contains(github.event.head_commit.message, '[skip build]')" + uses: actions/upload-artifact@v3 + with: + name: go-binaries + path: go_build_artifacts/ + +######################################## +# Create/Refresh base runtime image +######################################## + docker-base: + runs-on: [self-hosted, Linux, small] + steps: + - name: Checkout + if: "! contains(github.event.head_commit.message, '[skip docker]')" + uses: actions/checkout@v3 + + - name: Generate Docker Tags + if: "! contains(github.event.head_commit.message, '[skip docker]')" + id: docker_meta + uses: docker/metadata-action@v3 + with: + images: ${{ env.DOCKER_ORG }}/runtime-base + flavor: | + latest=true + tags: | + type=sha + + - name: Set up Docker Buildx + if: "! contains(github.event.head_commit.message, '[skip docker]')" + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + if: "! contains(github.event.head_commit.message, '[skip docker]')" + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Publish to DockerHub + if: "! contains(github.event.head_commit.message, '[skip docker]')" + id: docker_publish_dockerhub + uses: docker/build-push-action@v2 + with: + build-args: | + REPO_ORG=${{ env.DOCKER_ORG }} + context: . + file: .internal-ci/docker/Dockerfile.runtime-base + labels: ${{ steps.docker_meta.outputs.labels }} + push: true + tags: ${{ steps.docker_meta.outputs.tags }} + +######################################### +# Build/Publish public artifacts +######################################### + docker: + runs-on: [self-hosted, Linux, small] + needs: + - build-go-projects + - build-rust-hardware-projects + - docker-base + - generate-metadata + strategy: + matrix: + image: + - bootstrap-tools + - fogingest + - fog-ledger + - fogreport + - fog-test-client + - fogview + - go-grpc-gateway + - node_hw + - mobilecoind + - watcher + steps: + - name: Checkout + if: "! contains(github.event.head_commit.message, '[skip docker]')" + uses: actions/checkout@v3 + + - name: Cache rust build binaries + if: "! contains(github.event.head_commit.message, '[skip docker]')" + id: rust_artifact_cache + uses: ./.github/actions/mobilecoin-cache-rust-binaries + with: + cache_buster: ${{ secrets.CACHE_BUSTER }} + + - name: Cache go build binaries + if: "! contains(github.event.head_commit.message, '[skip docker]')" + id: go_artifact_cache + uses: ./.github/actions/mobilecoin-cache-go-binaries + with: + cache_buster: ${{ secrets.CACHE_BUSTER }} + + - name: Generate Docker Tags + if: "! contains(github.event.head_commit.message, '[skip docker]')" + id: docker_meta + uses: docker/metadata-action@v3 + with: + images: ${{ env.DOCKER_ORG }}/${{ matrix.image }} + tags: ${{ needs.generate-metadata.outputs.docker_tag }} + + - name: Set up Docker Buildx + if: "! contains(github.event.head_commit.message, '[skip docker]')" + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + if: "! contains(github.event.head_commit.message, '[skip docker]')" + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Publish to DockerHub + if: "! contains(github.event.head_commit.message, '[skip docker]')" + id: docker_publish_dockerhub + uses: docker/build-push-action@v2 + with: + build-args: | + REPO_ORG=${{ env.DOCKER_ORG }} + RUST_BIN_PATH=rust_build_artifacts + GO_BIN_PATH=go_build_artifacts + cache-from: type=registry,ref=${{ env.DOCKER_ORG }}/${{ matrix.image }}:buildcache-${{ needs.generate-metadata.outputs.branch }} + cache-to: type=registry,ref=${{ env.DOCKER_ORG }}/${{ matrix.image }}:buildcache-${{ needs.generate-metadata.outputs.branch }} + context: . + file: .internal-ci/docker/Dockerfile.${{ matrix.image }} + labels: ${{ steps.docker_meta.outputs.labels }} + push: true + tags: ${{ steps.docker_meta.outputs.tags }} + + charts: + runs-on: [self-hosted, Linux, small] + needs: + - docker + - generate-metadata + strategy: + matrix: + chart: + - consensus-node + - consensus-node-config + - fog-ingest + - fog-ingest-config + - fog-services + - fog-services-config + - fog-test-client + - mc-core-common-config + - mc-core-dev-env-setup + - mobilecoind + - watcher + steps: + - name: Checkout + if: "! contains(github.event.head_commit.message, '[skip charts]')" + uses: actions/checkout@v3 + + - name: Package and publish chart + if: "! contains(github.event.head_commit.message, '[skip charts]')" + uses: mobilecoinofficial/gha-k8s-toolbox@a89efdf4305f3b926b1bb61a59f267532406e653 + with: + action: helm-publish + chart_repo_username: ${{ secrets.HARBOR_USERNAME }} + chart_repo_password: ${{ secrets.HARBOR_PASSWORD }} + chart_repo: ${{ env.CHART_REPO }} + chart_app_version: ${{ needs.generate-metadata.outputs.tag }} + chart_version: ${{ needs.generate-metadata.outputs.tag }} + chart_path: .internal-ci/helm/${{ matrix.chart }} + +################################# +# Reset existing namespace +################################# + dev-reset: + runs-on: [self-hosted, Linux, small] + needs: + - generate-metadata + steps: + - name: Reset development namespace + if: "! contains(github.event.head_commit.message, '[skip dev-reset]')" + uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 + with: + workflow: mobilecoin-dispatch-dev-reset + token: ${{ secrets.ACTIONS_TOKEN }} + wait-for-completion: true + wait-for-completion-timeout: 30m + wait-for-completion-interval: 30s + display-workflow-run-url-interval: 30s + inputs: | + { + "namespace": "${{ needs.generate-metadata.outputs.namespace }}" + } + +####################################### +# Deploy previous release to namespace +####################################### + previous-release-deploy: + runs-on: [self-hosted, Linux, small] + needs: + - dev-reset + - generate-metadata + steps: + - name: Deploy Release + if: "! contains(github.event.head_commit.message, '[skip previous-release-deploy]')" + uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 + with: + workflow: mobilecoin-dispatch-dev-deploy + token: ${{ secrets.ACTIONS_TOKEN }} + wait-for-completion: true + wait-for-completion-timeout: 30m + wait-for-completion-interval: 30s + display-workflow-run-url-interval: 30s + inputs: | + { + "block_version": "0", + "chart_repo": "${{ needs.generate-metadata.outputs.chart_repo }}", + "docker_image_org": "${{ needs.generate-metadata.outputs.docker_org }}", + "minting_config_enabled": "false", + "ingest_color": "blue", + "namespace": "${{ needs.generate-metadata.outputs.namespace }}", + "version": "${{ needs.generate-metadata.outputs.previous_release }}", + "client_auth_enabled": "false", + "use_static_wallet_seeds": "true" + } + + previous-release-test: + runs-on: [self-hosted, Linux, small] + needs: + - previous-release-deploy + - generate-metadata + steps: + - name: Run MobileCoin integration tests + if: "! contains(github.event.head_commit.message, '[skip previous-release-test]')" + uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 + with: + workflow: mobilecoin-dispatch-dev-test + token: ${{ secrets.ACTIONS_TOKEN }} + wait-for-completion: true + wait-for-completion-timeout: 30m + wait-for-completion-interval: 30s + display-workflow-run-url-interval: 30s + inputs: | + { + "ingest_color": "blue", + "namespace": "${{ needs.generate-metadata.outputs.namespace }}", + "fog_distribution": "true", + "testing_1_1": "true", + "testing_1_2": "false", + "client_auth_enabled": "false" + } + +############################################### +# Deploy current version to namespace block v0 +############################################### + current-release-v0-deploy: + runs-on: [self-hosted, Linux, small] + needs: + - previous-release-test + - generate-metadata + - charts + steps: + - name: Deploy Release + if: "! contains(github.event.head_commit.message, '[skip current-release-v0-deploy]')" + uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 + with: + workflow: mobilecoin-dispatch-dev-deploy + token: ${{ secrets.ACTIONS_TOKEN }} + wait-for-completion: true + wait-for-completion-timeout: 30m + wait-for-completion-interval: 30s + display-workflow-run-url-interval: 30s + inputs: | + { + "block_version": "0", + "chart_repo": "${{ needs.generate-metadata.outputs.chart_repo }}", + "docker_image_org": "${{ needs.generate-metadata.outputs.docker_org }}", + "minting_config_enabled": "true", + "ingest_color": "green", + "namespace": "${{ needs.generate-metadata.outputs.namespace }}", + "version": "${{ needs.generate-metadata.outputs.tag }}", + "client_auth_enabled": "false", + "use_static_wallet_seeds": "true" + } + + current-release-v0-test: + runs-on: [self-hosted, Linux, small] + needs: + - current-release-v0-deploy + - generate-metadata + steps: + - name: Run MobileCoin integration tests + if: "! contains(github.event.head_commit.message, '[skip current-release-v0-test]')" + uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 + with: + workflow: mobilecoin-dispatch-dev-test + token: ${{ secrets.ACTIONS_TOKEN }} + wait-for-completion: true + wait-for-completion-timeout: 30m + wait-for-completion-interval: 30s + display-workflow-run-url-interval: 30s + inputs: | + { + "namespace": "${{ needs.generate-metadata.outputs.namespace }}", + "ingest_color": "green", + "fog_distribution": "false", + "testing_1_1": "true", + "testing_1_2": "false", + "client_auth_enabled": "false" + } + +################################################# +# Update current consensus to namespace block v1 +################################################# + current-release-v2-update: + runs-on: [self-hosted, Linux, small] + needs: + - current-release-v0-test + - generate-metadata + steps: + - name: Update consensus config + if: "! contains(github.event.head_commit.message, '[skip current-release-v2-update]')" + uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 + with: + workflow: mobilecoin-dispatch-dev-update-consensus + token: ${{ secrets.ACTIONS_TOKEN }} + wait-for-completion: true + wait-for-completion-timeout: 30m + wait-for-completion-interval: 30s + display-workflow-run-url-interval: 30s + inputs: | + { + "block_version": "2", + "client_auth_enabled": "false", + "minting_config_enabled": "true", + "docker_image_org": "${{ needs.generate-metadata.outputs.docker_org }}", + "chart_repo": "${{ needs.generate-metadata.outputs.chart_repo }}", + "namespace": "${{ needs.generate-metadata.outputs.namespace }}", + "version": "${{ needs.generate-metadata.outputs.tag }}" + } + + current-release-v2-test: + runs-on: [self-hosted, Linux, small] + needs: + - current-release-v2-update + - generate-metadata + steps: + - name: Run MobileCoin integration tests + if: "! contains(github.event.head_commit.message, '[skip current-release-v2-test]')" + uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 + with: + workflow: mobilecoin-dispatch-dev-test + token: ${{ secrets.ACTIONS_TOKEN }} + wait-for-completion: true + wait-for-completion-timeout: 30m + wait-for-completion-interval: 30s + display-workflow-run-url-interval: 30s + inputs: | + { + "namespace": "${{ needs.generate-metadata.outputs.namespace }}", + "ingest_color": "green", + "fog_distribution": "false", + "testing_1_1": "true", + "testing_1_2": "true", + "client_auth_enabled": "false" + } diff --git a/.github/workflows/mobilecoin-dev-delete.yaml b/.github/workflows/mobilecoin-dev-delete.yaml new file mode 100644 index 0000000000..d309f0fa1b --- /dev/null +++ b/.github/workflows/mobilecoin-dev-delete.yaml @@ -0,0 +1,35 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Delete development namespaces when branch is removed. + +name: mobilecoin-dev-delete + +on: + delete: {} + +jobs: + delete: + if: startsWith(github.ref, 'refs/branch/feature/') + runs-on: [self-hosted, Linux, small] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Generate version metadata + id: meta + run: | + .internal-ci/util/metadata.sh + + - name: Delete branch namespace + uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 + with: + workflow: mobilecoin-dispatch-dev-delete + token: ${{ secrets.ACTIONS_TOKEN }} + wait-for-completion: true + wait-for-completion-timeout: 30m + wait-for-completion-interval: 30s + display-workflow-run-url-interval: 30s + inputs: | + { + "namespace": "${{ steps.meta.outputs.namespace }}" + } diff --git a/.github/workflows/mobilecoin-dispatch-dev-delete.yaml b/.github/workflows/mobilecoin-dispatch-dev-delete.yaml index 7982f7ec57..e4041ae21f 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-delete.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-delete.yaml @@ -1,3 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Dispatch (manual) Job - Delete target dev namespace and all of its components. + name: mobilecoin-dispatch-dev-delete on: @@ -8,11 +12,29 @@ on: type: string required: true - jobs: - list-values: - runs-on: [self-hosted, small, Linux] + reset: + uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml + with: + namespace: ${{ github.event.inputs.namespace }} + secrets: + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + + delete: + runs-on: [self-hosted, Linux, small] + needs: + - reset steps: - - name: values - run: | - echo namespace ${{ github.event.inputs.namespace }} + - name: Delete namespace + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: namespace-delete + namespace: ${{ github.event.inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + diff --git a/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml b/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml index 6088a589b7..c9cb6ad695 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml @@ -1,3 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Dispatch (manual) Job - Deploy core apps to the development namespace. + name: mobilecoin-dispatch-dev-deploy on: @@ -7,11 +11,75 @@ on: description: "Target Namespace" type: string required: true + version: + description: "Chart Version" + type: string + required: true + chart_repo: + description: "Chart Repo URL" + type: string + required: true + default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + docker_image_org: + description: "Docker Image Org" + type: string + required: true + default: docker.io/mobilecoin + ingest_color: + description: "Fog Ingest blue/green" + type: string + required: true + default: blue + minting_config_enabled: + description: "Enable minting config" + type: boolean + required: true + default: false + block_version: + description: "Consensus block_version" + type: string + required: true + client_auth_enabled: + description: "Enable client token auth" + type: boolean + required: true + default: false + # true: use GHA secret values, false: generate random seeds + use_static_wallet_seeds: + description: "Use static wallet seeds" + type: boolean + required: true + default: false jobs: - list-values: - runs-on: [self-hosted, small, Linux] - steps: - - name: values - run: | - echo namespace ${{ github.event.inputs.namespace }} + deploy: + uses: ./.github/workflows/mobilecoin-workflow-dev-deploy.yaml + with: + namespace: ${{ github.event.inputs.namespace }} + version: ${{ github.event.inputs.version }} + docker_image_org: ${{ github.event.inputs.docker_image_org }} + chart_repo: ${{ github.event.inputs.chart_repo }} + ingest_color: ${{ github.event.inputs.ingest_color }} + minting_config_enabled: ${{ github.event.inputs.minting_config_enabled }} + block_version: ${{ github.event.inputs.block_version }} + secrets: + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + IAS_KEY: ${{ secrets.DEV_IAS_KEY }} + IAS_SPID: ${{ secrets.DEV_IAS_SPID }} + FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} + FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} + FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} + MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} + CLIENT_AUTH_TOKEN: ${{ github.event.inputs.client_auth_enabled == 'true' && secrets.DEV_CLIENT_AUTH_TOKEN || '' }} + CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} + INITIAL_KEYS_SEED: ${{ github.event.inputs.use_static_wallet_seeds == 'true' && secrets.DEV_INITIAL_KEYS_SEED || '' }} + FOG_KEYS_SEED: ${{ github.event.inputs.use_static_wallet_seeds == 'true' && secrets.DEV_FOG_KEYS_SEED || '' }} + MNEMONIC_KEYS_SEED: ${{ github.event.inputs.use_static_wallet_seeds == 'true' && secrets.DEV_MNEMONIC_KEYS_SEED || '' }} + MNEMONIC_FOG_KEYS_SEED: ${{ github.event.inputs.use_static_wallet_seeds == 'true' && secrets.DEV_MNEMONIC_FOG_KEYS_SEED || '' }} diff --git a/.github/workflows/mobilecoin-dispatch-dev-reset.yaml b/.github/workflows/mobilecoin-dispatch-dev-reset.yaml index 9f73fe890c..0e0c0cfcd6 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-reset.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-reset.yaml @@ -1,3 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Dispatch (manual) Job - Reset/remove all components from a development namespace. + name: mobilecoin-dispatch-dev-reset on: @@ -9,9 +13,13 @@ on: required: true jobs: - list-values: - runs-on: [self-hosted, small, Linux] - steps: - - name: values - run: | - echo namespace ${{ github.event.inputs.namespace }} + reset: + uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml + with: + namespace: ${{ github.event.inputs.namespace }} + secrets: + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/mobilecoin-dispatch-dev-test.yaml b/.github/workflows/mobilecoin-dispatch-dev-test.yaml index 6871654296..bfef097326 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-test.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-test.yaml @@ -1,3 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Dispatch (manual) Job - Run integration tests in a development namespace. + name: mobilecoin-dispatch-dev-test on: @@ -7,11 +11,45 @@ on: description: "Target Namespace" type: string required: true + ingest_color: + description: "Fog Ingest blue/green" + type: string + required: true + default: blue + fog_distribution: + description: "Run fog-distribution test" + type: boolean + required: false + default: true + testing_1_1: + description: "Run v1.1.x tests (block_version 0)" + type: boolean + required: false + default: true + testing_1_2: + description: "Run v1.2.x tests (block_version 0/2)" + type: boolean + required: false + default: true + client_auth_enabled: + description: "Is client auth enabled?" + type: boolean + required: false + default: false jobs: - list-values: - runs-on: [self-hosted, small, Linux] - steps: - - name: values - run: | - echo namespace ${{ github.event.inputs.namespace }} + test: + uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml + with: + namespace: ${{ github.event.inputs.namespace }} + ingest_color: ${{ github.event.inputs.ingest_color }} + fog_distribution: ${{ github.event.inputs.fog_distribution == 'true' && 'true' || 'false' }} + testing_1_1 : ${{ github.event.inputs.testing_1_1 == 'true' && 'true' || 'false' }} + testing_1_2: ${{ github.event.inputs.testing_1_2 == 'true' && 'true' || 'false' }} + secrets: + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} + CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} + CLIENT_AUTH_USER_VALUE: ${{ github.event.inputs.client_auth_enabled == 'true' && secrets.DEV_CLIENT_AUTH_USER_VALUE || '' }} diff --git a/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml b/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml index 544d3d712a..e7a22a9d21 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml @@ -1,3 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Dispatch (manual) Job - Update consensus nodes in a development namespace. + name: mobilecoin-dispatch-dev-update-consensus on: @@ -7,11 +11,58 @@ on: description: "Target Namespace" type: string required: true + version: + description: "Chart Version" + type: string + required: true + chart_repo: + description: "Chart Repo URL" + type: string + required: true + default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + docker_image_org: + description: "Docker Image Org" + type: string + required: true + default: docker.io/mobilecoin + minting_config_enabled: + description: "Enable minting config" + type: boolean + required: true + default: true + block_version: + description: "Block Version" + type: string + required: true + default: '2' + client_auth_enabled: + description: "additional shared token for client auth" + type: boolean + required: true + default: false jobs: - list-values: - runs-on: [self-hosted, small, Linux] - steps: - - name: values - run: | - echo namespace ${{ github.event.inputs.namespace }} + update-consensus-block-version: + uses: ./.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml + with: + namespace: ${{ github.event.inputs.namespace }} + version: ${{ github.event.inputs.version }} + docker_image_org: ${{ github.event.inputs.docker_image_org }} + chart_repo: ${{ github.event.inputs.chart_repo }} + minting_config_enabled: ${{ github.event.inputs.minting_config_enabled }} + block_version: "${{ github.event.inputs.block_version }}" + secrets: + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + IAS_KEY: ${{ secrets.DEV_IAS_KEY }} + IAS_SPID: ${{ secrets.DEV_IAS_SPID }} + FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} + FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} + MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} + CLIENT_AUTH_TOKEN: ${{ github.event.inputs.client_auth_enabled == 'true' && secrets.DEV_CLIENT_AUTH_TOKEN || '' }} diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml new file mode 100644 index 0000000000..f09940158f --- /dev/null +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -0,0 +1,383 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Reusable Workflow - Deploy core apps to to the development namespace. + +name: mobilecoin-workflow-dev-deploy + +on: + workflow_call: + inputs: + namespace: + description: "Target Namespace" + type: string + required: true + version: + description: "Chart Version" + type: string + required: true + docker_image_org: + description: "Docker Image Org" + type: string + required: true + default: docker.io/mobilecoin + chart_repo: + description: "Chart Repo URL" + type: string + required: true + default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + ingest_color: + description: "Fog Ingest blue/green" + type: string + required: true + minting_config_enabled: + description: "Enable minting config" + type: string + default: 'false' + required: true + block_version: + description: "block_version" + type: string + required: true + secrets: + RANCHER_CLUSTER: + description: "Rancher cluster name" + required: true + RANCHER_URL: + description: "Rancher server URL" + required: true + RANCHER_TOKEN: + description: "Rancher access token" + required: true + LEDGER_AWS_ACCESS_KEY_ID: + description: "Ledger AWS S3 access" + required: true + LEDGER_AWS_SECRET_ACCESS_KEY: + description: "Ledger AWS S3 access" + required: true + IAS_KEY: + description: "IAS" + required: true + IAS_SPID: + description: "IAS" + required: true + FOG_REPORT_SIGNING_CERT: + description: "Fog Report signing cert pem" + required: true + FOG_REPORT_SIGNING_CERT_KEY: + description: "Fog Report signing cert key" + required: true + FOG_REPORT_SIGNING_CA_CERT: + description: "Fog Report signing CA cert" + required: true + MINTING_TRUST_ROOT_PRIVATE: + description: "Root private key for singing the tokens config" + required: false + DOCKERHUB_TOKEN: + description: "Docker hub creds" + required: false + DOCKERHUB_USERNAME: + description: "Docker hub creds" + required: false + IP_INFO_TOKEN: + description: "ipinfo.io token for authenticated access" + required: true + CLIENT_AUTH_TOKEN: + description: "shared token for client auth" + required: false + CACHE_BUSTER: + description: "string to make cache unique" + required: false + INITIAL_KEYS_SEED: + description: "static wallet seed" + required: false + FOG_KEYS_SEED: + description: "static wallet seed" + required: false + MNEMONIC_KEYS_SEED: + description: "static wallet seed" + required: false + MNEMONIC_FOG_KEYS_SEED: + description: "static wallet seed" + required: false + +jobs: + list-values: + name: 👾 Environment Info 👾 + runs-on: [self-hosted, Linux, small] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: List input values + run: | + echo namespace ${{ inputs.namespace }} + echo version ${{ inputs.version }} + echo docker_image_org ${{ inputs.docker_image_org }} + echo ingest_color ${{ inputs.ingest_color }} + echo minting_config_enabled ${{ inputs.minting_config_enabled }} + echo chart_repo ${{ inputs.chart_repo }} + + - name: 👾 Print Environment Details 👾 + env: + CHART_REPO: ${{ inputs.chart_repo }} + NAMESPACE: ${{ inputs.namespace }} + VERSION: ${{ inputs.version }} + run: | + .internal-ci/util/print_details.sh + + setup-environment: + runs-on: [self-hosted, Linux, small] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Create namespace + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: namespace-create + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + - name: Cache wallet seeds .tmp/seeds + uses: ./.github/actions/mobilecoin-cache-seeds + with: + cache_buster: ${{ secrets.CACHE_BUSTER }} + + # use static keys if provided. + - name: Generate Wallet Seed + env: + INITIAL_KEYS_SEED: ${{ secrets.INITIAL_KEYS_SEED }} + FOG_KEYS_SEED: ${{ secrets.FOG_KEYS_SEED }} + MNEMONIC_KEYS_SEED: ${{ secrets.MNEMONIC_KEYS_SEED }} + MNEMONIC_FOG_KEYS_SEED: ${{ secrets.MNEMONIC_FOG_KEYS_SEED }} + run: | + .internal-ci/util/generate_wallet_seeds.sh + + # write this to the seeds dir and set the path that toolbox will find it at. + - name: Write fog-report signing CA cert + env: + FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.FOG_REPORT_SIGNING_CA_CERT }} + run: | + mkdir -p .tmp/seeds + echo -n "${FOG_REPORT_SIGNING_CA_CERT}" > .tmp/seeds/FOG_REPORT_SIGNING_CA_CERT + echo -n "/wallet-seeds/FOG_REPORT_SIGNING_CA_CERT" > .tmp/seeds/FOG_REPORT_SIGNING_CA_CERT_PATH + + - name: Create wallet key secrets + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: secrets-create-from-file + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + object_name: sample-keys-seeds + src: .tmp/seeds + + - name: Create minting keys + if: inputs.minting_config_enabled == 'true' + env: + MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.MINTING_TRUST_ROOT_PRIVATE }} + run: | + .internal-ci/util/generate_minting_keys.sh + + - name: Login to DockerHub + if: inputs.minting_config_enabled == 'true' + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + # CBB: create a minimal image with just mc-consensus-mint-client binary. + - name: Generate and sign tokens config + if: inputs.minting_config_enabled == 'true' + id: tokens_config + run: | + docker run \ + -v ${{ github.workspace }}:/workspace \ + --network none \ + --workdir /workspace \ + ${{ inputs.docker_image_org }}/bootstrap-tools:${{ inputs.version }} \ + .internal-ci/util/generate_tokens_config.sh + + - name: Create minting key secrets + if: inputs.minting_config_enabled == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: secrets-create-from-file + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + object_name: consensus-minting-secrets + src: .tmp/seeds/minting + + - name: Generate environment values file + env: + IAS_KEY: ${{ secrets.IAS_KEY }} + IAS_SPID: ${{ secrets.IAS_SPID }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.LEDGER_AWS_SECRET_ACCESS_KEY }} + FOG_REPORT_SIGNING_CERT: ${{ secrets.FOG_REPORT_SIGNING_CERT }} + FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.FOG_REPORT_SIGNING_CERT_KEY }} + IP_INFO_TOKEN: ${{ secrets.IP_INFO_TOKEN }} + CLIENT_AUTH_TOKEN: ${{ secrets.CLIENT_AUTH_TOKEN }} + run: | + mkdir -p .tmp/values/ + .internal-ci/util/generate_dev_values.sh > .tmp/values/mc-core-dev-env-values.yaml + + - name: Deploy environment setup + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: ${{ inputs.chart_repo }} + chart_name: mc-core-dev-env-setup + chart_version: ${{ inputs.version }} + chart_values: .tmp/values/mc-core-dev-env-values.yaml + chart_set: | + --set=global.node.nodeConfig.blockVersion=${{ inputs.block_version }} + release_name: mc-core-dev-env-setup + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + consensus-deploy: + needs: + - setup-environment + runs-on: [self-hosted, Linux, small] + strategy: + matrix: + release_name: + - consensus-node-1 + - consensus-node-2 + - consensus-node-3 + - consensus-node-4 + - consensus-node-5 + steps: + - name: Deploy Consensus nodes + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: ${{ inputs.chart_repo }} + chart_name: consensus-node + chart_version: ${{ inputs.version }} + chart_set: | + --set=image.org=${{ inputs.docker_image_org }} + chart_wait_timeout: 10m + release_name: ${{ matrix.release_name }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + postgresql-deploy: + needs: + - setup-environment + runs-on: [self-hosted, Linux, small] + steps: + - name: Deploy PostgreSQL instance + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: https://charts.bitnami.com/bitnami + chart_name: postgresql + chart_version: 11.2.3 + chart_set: | + --set=global.postgresql.auth.existingSecret=fog-recovery-postgresql + --set=global.postgresql.auth.database=fog_recovery + --set=architecture=replication + chart_wait_timeout: 5m + release_name: fog-recovery-postgresql + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + mobilecoind-deploy: + needs: + - consensus-deploy + runs-on: [self-hosted, Linux, small] + steps: + - name: Deploy Consensus nodes + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: ${{ inputs.chart_repo }} + chart_name: mobilecoind + chart_version: ${{ inputs.version }} + chart_set: | + --set=image.org=${{ inputs.docker_image_org }} + chart_wait_timeout: 5m + release_name: mobilecoind + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + fog-ingest-deploy: + needs: + - postgresql-deploy + - consensus-deploy + runs-on: [self-hosted, Linux, small] + steps: + - name: Deploy fog-ingest + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: ${{ inputs.chart_repo }} + chart_name: fog-ingest + chart_version: ${{ inputs.version }} + chart_wait_timeout: 10m + chart_set: | + --set=image.org=${{ inputs.docker_image_org }} + release_name: fog-ingest-${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + - name: Run fog-recovery database migrations + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + fog-sql-recovery-db-migrations + + - name: Activate primary ingest + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: fog-ingest-activate + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + fog-services-deploy: + needs: + - postgresql-deploy + - consensus-deploy + runs-on: [self-hosted, Linux, small] + steps: + - name: Deploy fog-services + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: ${{ inputs.chart_repo }} + chart_name: fog-services + chart_version: ${{ inputs.version }} + chart_wait_timeout: 10m + chart_set: | + --set=image.org=${{ inputs.docker_image_org }} + release_name: fog-services + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} diff --git a/.github/workflows/mobilecoin-workflow-dev-reset.yaml b/.github/workflows/mobilecoin-workflow-dev-reset.yaml new file mode 100644 index 0000000000..ba7ed1e1f5 --- /dev/null +++ b/.github/workflows/mobilecoin-workflow-dev-reset.yaml @@ -0,0 +1,100 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Reusable Workflow - Reset/remove all components from a development namespace. +# +# We don't want to just delete the namespace on every run. We need to preserve letsEncrypt certificates due to rate limits. We can delete app charts, postgres and dangling PVCs. + +name: mobilecoin-workflow-dev-reset + +on: + workflow_call: + inputs: + namespace: + description: "Target Namespace" + type: string + required: true + secrets: + RANCHER_CLUSTER: + description: "Rancher cluster name" + required: true + RANCHER_URL: + description: "Rancher server URL" + required: true + RANCHER_TOKEN: + description: "Rancher access token" + required: true + LEDGER_AWS_ACCESS_KEY_ID: + description: "Ledger AWS S3 access" + required: true + LEDGER_AWS_SECRET_ACCESS_KEY: + description: "Ledger AWS S3 access" + required: true + +jobs: + list-values: + runs-on: [self-hosted, Linux, small] + steps: + - name: values + run: | + echo namespace ${{ inputs.namespace }} + + reset-releases: + runs-on: [self-hosted, Linux, small] + strategy: + matrix: + chart: + - consensus-node-1 + - consensus-node-2 + - consensus-node-3 + - consensus-node-4 + - consensus-node-5 + - fog-ingest-blue + - fog-ingest-green + - fog-recovery-postgresql + - fog-services + - mobilecoind + steps: + - name: Delete release + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-release-delete + namespace: ${{ inputs.namespace }} + release_name: ${{ matrix.chart }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + reset-storage: + needs: + - reset-releases + runs-on: [self-hosted, Linux, small] + steps: + - name: Delete PersistentVolumeClaims + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: pvcs-delete + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + reset-s3: + needs: + - reset-releases + runs-on: [self-hosted, Linux, small] + container: + image: amazon/aws-cli:latest + steps: + - name: Clear out s3 bucket objects + env: + AWS_ACCESS_KEY_ID: ${{ secrets.LEDGER_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LEDGER_AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: eu-central-1 + BUCKET: mobilecoin.eu.development.chain + NAMESPACE: ${{ inputs.namespace }} + run: | + aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node1.${NAMESPACE}.development.mobilecoin.com + aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node2.${NAMESPACE}.development.mobilecoin.com + aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node3.${NAMESPACE}.development.mobilecoin.com + aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node4.${NAMESPACE}.development.mobilecoin.com + aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node5.${NAMESPACE}.development.mobilecoin.com diff --git a/.github/workflows/mobilecoin-workflow-dev-test.yaml b/.github/workflows/mobilecoin-workflow-dev-test.yaml new file mode 100644 index 0000000000..49abe15d29 --- /dev/null +++ b/.github/workflows/mobilecoin-workflow-dev-test.yaml @@ -0,0 +1,348 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Reusable Workflow - Run integration tests in a development namespace. +# +# All current tests run with tools, scripts and binaries built and embedded within the toolbox +# (bootstrap-tools) image. The toolbox image is built and versioned with the app code, so it will only +# have the tools available at its build time. This allows tests to be internally consistent with the +# release you added the test in. +# +# To add tests: +# - Make sure binaries/scripts are included as part of the toolbox. +# Dockerfile: .internal-ci/docker/Dockerfile.bootstrap-tools +# All files saved under .internal-ci/util and .internal-ci/test are already included in the +# toolbox image +# +# - Simple commands or standalone binaries can use the mobilecoinofficial/gha-k8s-toolbox +# toolbox-exec GitHub Action. +# +# - Python tests and multipart scripts should include a wrapper script that installs/refreshes +# any requirements and build protos as required. See .internal-ci/test +# +# - Secrets should be generated at Deploy time (mobilecoin-workflow-dev-deploy) and placed in a +# k8s secret or configmap object that is then configured as a env or volume on the toolbox deployment. +# .internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml +# CBB: move testing tool box into its own chart. +# +# - Make tests optional by adding a variable in the inputs and add variable to +# mobilecoin-dispatch-dev-test so dispatch workflows can use it. +# +# When adding tests remember: +# - Tests are baked into the version they were added in. This is so they will be internally consistent +# with the binaries and configurations they were intended to test. +# +# - Any tests/tools/configs/secrets you add now will not be available to the "Previous Release" +# toolbox container. +# +# - All tests run with in the kubernetes namespace context so we can reach internally hosted endpoints, +# like mobilecoind. (CBB: add full-service?) +# +# CBB: make tests work if client_auth_token is enabled. Will require generating the auth tokens. + +name: mobilecoin-workflow-dev-test + +on: + workflow_call: + inputs: + namespace: + description: "Target Namespace" + type: string + required: true + ingest_color: + description: "Fog Ingest blue/green" + type: string + required: true + fog_distribution: + description: "Run fog-distribution test" + type: string + required: false + default: 'true' + testing_1_1: + description: "Run v1.1.x tests (block_version 0)" + type: string + required: false + default: 'true' + testing_1_2: + description: "Run v1.2.x tests (block_version 0/2" + type: string + required: false + default: 'true' + secrets: + RANCHER_CLUSTER: + description: "Rancher cluster name" + required: true + RANCHER_URL: + description: "Rancher server URL" + required: true + RANCHER_TOKEN: + description: "Rancher access token" + required: true + FOG_REPORT_SIGNING_CA_CERT: + description: "Fog Report Signing CA" + required: true + CACHE_BUSTER: + description: "string to make cache unique" + required: true + CLIENT_AUTH_USER_VALUE: + description: "client auth rendered value" + required: false + +jobs: + list-values: + runs-on: [self-hosted, Linux, small] + steps: + - name: values + run: | + echo namespace ${{ inputs.namespace }} + echo ingest_color ${{ inputs.ingest_color }} + echo fog_distribution ${{ inputs.fog_distribution }} + echo testing_1_1 ${{ inputs.testing_1_1 }} + echo testing_1_2 ${{ inputs.testing_1_2 }} + + setup-environment: + runs-on: [self-hosted, Linux, small] + env: + FOG_REPORT_SIGNING_CA_CERT_PATH: .tmp/fog_report_signing_ca_cert.pem + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Delete existing keys + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + rm -rf /tmp/sample_data + + # Populates ledger and keys in toolbox at /tmp/sample_data + - name: Recreate Keys for Testing + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + INITIALIZE_LEDGER="true" \ + FOG_REPORT_URL="fog://fog.${{ inputs.namespace }}.development.mobilecoin.com:443" \ + /util/generate_origin_data.sh + + fog-distribution: + name: fog-distribution ${{ inputs.fog_distribution == 'true' && '(run)' || '(skipped)' }} + runs-on: [self-hosted, Linux, small] + needs: + - setup-environment + steps: + - name: Test - fog-distribution + if: inputs.fog_distribution == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /test/fog-distribution-test.sh + + testing-1-1: + name: testing-1-1 ${{ inputs.testing_1_1 == 'true' && '(run)' || '(skipped)' }} + runs-on: [self-hosted, Linux, small] + needs: + - fog-distribution + steps: + - name: Test - fog-test-client + if: inputs.testing_1_1 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + test_client \ + --key-dir /tmp/sample_data/fog_keys \ + --consensus mc://node1.${{ inputs.namespace }}.development.mobilecoin.com/ \ + --consensus mc://node2.${{ inputs.namespace }}.development.mobilecoin.com/ \ + --consensus mc://node3.${{ inputs.namespace }}.development.mobilecoin.com/ \ + --num-clients 6 \ + --num-transactions 32 \ + --consensus-wait 300 \ + --transfer-amount 20 \ + --fog-view fog-view://${{ secrets.CLIENT_AUTH_USER_VALUE }}fog.${{ inputs.namespace }}.development.mobilecoin.com:443 \ + --fog-ledger fog-ledger://${{ secrets.CLIENT_AUTH_USER_VALUE }}fog.${{ inputs.namespace }}.development.mobilecoin.com:443 + + + - name: Test - mobilecoind-grpc (previously Wallet Integration) + if: inputs.testing_1_1 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /test/mobilecoind-integration-test.sh + + testing-1-2: + name: Testing for v1.2.x ${{ inputs.testing_1_2 == 'true' && '(run)' || '(skipped)' }} + runs-on: [self-hosted, Linux, small] + needs: + - testing-1-1 + env: + SRC_KEYS_DIR: /tmp/sample_data/keys + SRC_FOG_KEYS_DIR: /tmp/sample_data/fog_keys + DST_KEYS_DIR: /tmp/1.2-testing/keys + DST_FOG_KEYS_DIR: /tmp/1.2-testing/fog_keys + START_KEYS: '494' + END_KEYS: '499' + steps: + - name: Copy subset of non-fog keys + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /util/copy_account_keys.sh \ + --src ${{ env.SRC_KEYS_DIR }} \ + --dst ${{ env.DST_KEYS_DIR }} \ + --start ${{ env.START_KEYS }} \ + --end ${{ env.END_KEYS }} + + - name: Copy subset of fog keys + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /util/copy_account_keys.sh \ + --src ${{ env.SRC_FOG_KEYS_DIR }} \ + --dst ${{ env.DST_FOG_KEYS_DIR }} \ + --start ${{ env.START_KEYS }} \ + --end ${{ env.END_KEYS }} + + - name: Test - Minting config tx + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /test/minting-config-tx-test.sh \ + --token-id 1 + + - name: Test - Minting tx + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /test/minting-tx-test.sh \ + --key-dir ${{ env.DST_KEYS_DIR }} \ + --token-id 1 + + - name: Test - mobilecoind-json integration + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /test/mobilecoind-json-integration-test.sh \ + --key-dir ${{ env.DST_KEYS_DIR }} + + - name: Test - mint-auditor + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /test/mint-auditor-test.sh \ + --token-id 1 + + - name: Test - use drain_accounts to transfer id 1 balances to fog keys + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /util/drain_accounts.sh \ + --src ${{ env.DST_KEYS_DIR }} \ + --dst ${{ env.DST_FOG_KEYS_DIR }} \ + --fee 1024 \ + --token-id 1 + + - name: Test - fog-test-client token id 0 + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /test/fog-test-client.sh \ + --key-dir ${{ env.DST_FOG_KEYS_DIR }} \ + --token-id 0 + + - name: Test - fog-test-client token id 1 + if: inputs.testing_1_2 == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: toolbox-exec + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + command: | + /test/fog-test-client.sh \ + --key-dir ${{ env.DST_FOG_KEYS_DIR }} \ + --token-id 1 diff --git a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml new file mode 100644 index 0000000000..54d7df45df --- /dev/null +++ b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml @@ -0,0 +1,177 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Reusable Workflow - update consensus nodes in a development namespace. + +name: mobilecoin-workflow-dev-update-consensus + +on: + workflow_call: + inputs: + namespace: + description: "Target Namespace" + type: string + required: true + version: + description: "release version" + type: string + required: true + docker_image_org: + description: "Docker Image Org" + type: string + required: true + default: docker.io/mobilecoin + chart_repo: + description: "Chart Repo URL" + type: string + required: true + default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + minting_config_enabled: + description: "Enable minting config" + type: string + required: true + block_version: + description: "block_version" + type: string + required: true + + secrets: + RANCHER_CLUSTER: + description: "Rancher cluster name" + required: true + RANCHER_URL: + description: "Rancher server URL" + required: true + RANCHER_TOKEN: + description: "Rancher access token" + required: true + LEDGER_AWS_ACCESS_KEY_ID: + description: "Ledger AWS S3 access" + required: true + LEDGER_AWS_SECRET_ACCESS_KEY: + description: "Ledger AWS S3 access" + required: true + IAS_KEY: + description: "IAS" + required: true + IAS_SPID: + description: "IAS" + required: true + FOG_REPORT_SIGNING_CERT: + description: "Fog Report signing cert pem" + required: true + FOG_REPORT_SIGNING_CERT_KEY: + description: "Fog Report signing cert key" + required: true + MINTING_TRUST_ROOT_PRIVATE: + description: "Root private key for singing the tokens config" + required: false + DOCKERHUB_TOKEN: + description: "Docker hub creds" + required: false + DOCKERHUB_USERNAME: + description: "Docker hub creds" + required: false + IP_INFO_TOKEN: + description: "ipinfo.io token for authenticated access" + required: true + CLIENT_AUTH_TOKEN: + description: "shared token for client auth" + required: false + +jobs: + setup-environment: + runs-on: [self-hosted, Linux, small] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Create minting keys + if: inputs.minting_config_enabled == 'true' + env: + MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.MINTING_TRUST_ROOT_PRIVATE }} + run: | + .internal-ci/util/generate_minting_keys.sh + + - name: Login to DockerHub + if: inputs.minting_config_enabled == 'true' + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + # CBB: create a minimal image with just mc-consensus-mint-client binary. + - name: Generate and sign tokens config + if: inputs.minting_config_enabled == 'true' + id: tokens_config + run: | + docker run \ + -v ${{ github.workspace }}:/workspace \ + --network none \ + --workdir /workspace \ + ${{ inputs.docker_image_org }}/bootstrap-tools:${{ inputs.version }} \ + .internal-ci/util/generate_tokens_config.sh + + - name: Create minting key secrets + if: inputs.minting_config_enabled == 'true' + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: secrets-create-from-file + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + object_name: consensus-minting-secrets + src: .tmp/seeds/minting + + - name: Generate environment values file + env: + IAS_KEY: ${{ secrets.IAS_KEY }} + IAS_SPID: ${{ secrets.IAS_SPID }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.LEDGER_AWS_SECRET_ACCESS_KEY }} + FOG_REPORT_SIGNING_CERT: ${{ secrets.FOG_REPORT_SIGNING_CERT }} + FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.FOG_REPORT_SIGNING_CERT_KEY }} + IP_INFO_TOKEN: ${{ secrets.IP_INFO_TOKEN }} + CLIENT_AUTH_TOKEN: ${{ secrets.CLIENT_AUTH_TOKEN }} + run: | + mkdir -p .tmp/values/ + .internal-ci/util/generate_dev_values.sh > .tmp/values/mc-core-dev-env-values.yaml + + - name: Deploy environment setup with block_version + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: ${{ inputs.chart_repo }} + chart_name: mc-core-dev-env-setup + chart_version: ${{ inputs.version }} + chart_values: .tmp/values/mc-core-dev-env-values.yaml + chart_set: | + --set=global.node.nodeConfig.blockVersion=${{ inputs.block_version }} + release_name: mc-core-dev-env-setup + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + consensus-restart: + needs: + - setup-environment + runs-on: [self-hosted, Linux, small] + strategy: + matrix: + object_name: + - deployment.app/consensus-node-1 + - deployment.app/consensus-node-2 + - deployment.app/consensus-node-3 + - deployment.app/consensus-node-4 + - deployment.app/consensus-node-5 + steps: + - name: Restart Consensus Nodes + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: pod-restart + object_name: ${{ matrix.object_name }} + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} diff --git a/.gitignore b/.gitignore index 07b3520cfd..ccd0aa568a 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,13 @@ tools/fog-local-network/*_pb2*.py # libmobilecoin/rust-bitcode build libmobilecoin/rust-bitcode/* + +# build automation tmp +.tmp +**/charts/*.tgz +**/Chart.lock +sample_data/ +rust_build_artifacts/ +go_build_artifacts/ + +minting-trust-root* diff --git a/.internal-ci/README.md b/.internal-ci/README.md new file mode 100644 index 0000000000..54bf71f4ae --- /dev/null +++ b/.internal-ci/README.md @@ -0,0 +1,116 @@ +# Mobilecoin Internal CI/CD tools + +These build, dockerfiles, helm charts and scripts are used internally for MobileCoin builds and deployments and is subject to change without notice, YMMV, no warranties provided, all that good stuff. + +## Artifacts + +This process will create a set of versioned docker containers and helm charts for deploying the release. + +- Containers - https://hub.docker.com/u/mobilecoin +- Helm Chart Repo URL - https://s3.us-east-2.amazonaws.com/charts.mobilecoin.com/ + +### Versioning + +We use [Semver 2](https://semver.org/) for general versioning. + +⚠️ Note: Because we have multiple final releases (TestNet, MainNet...), and semver metadata isn't taken in account for ordering, all of the releases are technically "development" releases. Be aware that some tools like `helm` will need extra flags to display development versions. + +**Feature Branches** + +- `feature/my-awesome-feature` valid characters `[a-z][0-9]-` +- Feature branch names will be normalized for versioning, namespaces, dns... + - `feature/` prefix will be removed + - semver portion will be set to `v0.0.0`. + +format: +``` +v0.0.0-${branch}.${GITHUB_RUN_NUMBER}.sha-${sha} +``` + +examples: +``` +feature/my.awesome_feature + +v0.0.0-my-awesome-feature.21.sha-abcd1234 +``` + +**Release branches** + +- `release/v1.2.0` valid characters `v[0-9]+/.[0-9]+/.[0-9]+` +- Release branches will be normalized for versioning, namespaces, dns... + - namespaces will be prefixed with `release-` + - semver will be set to match the branch name. + - `-dev` and full tags will be create for the artifacts. + +format: +``` +v1.2.3-${GITHUB_RUN_NUMBER}.sha-${sha} +v1.2.3-dev +``` + +examples: +``` +release/v1.2.3 + +v1.2.3-21.sha-abcd1234 +v1.2.3-dev +``` + +## CI triggers + +This workflow is set up to trigger of certain branch patterns. + +### Feature Branches - `feature/*` + +Feature branches will trigger a build that will create a dynamic development environment and run integration tests against the environment. + +| Tags | SGX_MODE | IAS_MODE | Signer | Description | +| --- | --- | --- | --- | --- | +| `v0.0.0-my-awesome-feature.21.sha-abcd1234` | `HW` | `DEV` | CI Signed Development | For use in development environments. | + +### Release Branches - `release/*` + +Release branches will trigger a build that will create a set of release artifacts. + +TBD: Automatically deploy/destroy this release to the development cluster. + +| Tags | SGX_MODE | IAS_MODE | Signer | Description | +| --- | --- | --- | --- | --- | +| `v1.0.0-dev` | `HW` | `DEV` | CI Signed Development | For use in development environments. | + +### Production Releases - Manual Trigger + +⚠️ **Not Yet Implemented** + +Once the release branch is tested you can use the manual `workflow-dispatch` actions to build the TestNet and MainNet deployment artifacts. This process will expect a set of externally built signed enclaves uploaded to S3 storage. + +| Tags | SGX_MODE | IAS_MODE | Signer | Description | +| --- | --- | --- | --- | --- | +| `v1.0.0-test` | `HW` | `PROD` | External Signed TestNet | TestNet Build. | +| `v1.0.0-prod` | `HW` | `PROD` | External Signed MainNet | MainNet Build. | + +## CI Commit Message Flags + +This workflow watches the head(latest) commit for the current push and parses the commit message for defined bracket `[]` statements. + +### `[tag=]` Flag + +The `[tag=]` flag will override the automatically generated docker/helm tag and deploy the specified version in the `current-release-*` steps. + +### `[skip *]` Flags + +⚠️ Using skip flags may lead to incomplete and/or broken builds. + +Available skips: + +- `[skip ci]` - GHA built-in to skip all workflow steps. +- `[skip build]` - Skip rust/go builds. +- `[skip docker]` - Skip docker image build/publish. +- `[skip charts]` - Skip helm chart build/publish. +- `[skip dev-reset]` - Skip dev namespace reset. +- `[skip previous-deploy]` - Skip deploy of the previous consensus/fog release. +- `[skip previous-test]` - Skip test of previous release. +- `[skip current-release-v0-deploy]` - Skip current release at block-version=0 deploy. +- `[skip current-release-v0-test]`- Skip current release at block-version=0 deploy. +- `[skip current-release-v1-update]` - Skip current release at block-version=1 consensus update. +- `[skip current-release-v1-test]` - Skip current release at block-version=1 tests. diff --git a/.internal-ci/docker/Dockerfile.bootstrap-tools b/.internal-ci/docker/Dockerfile.bootstrap-tools new file mode 100644 index 0000000000..e69ee2a713 --- /dev/null +++ b/.internal-ci/docker/Dockerfile.bootstrap-tools @@ -0,0 +1,67 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.bootstrap-tools +# +# Multipurpose "toolbox" container for operations, testing and migrations. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +SHELL ["/bin/bash", "-c"] + +ENV TZ=Etc/UTC +ENV PYTHONUNBUFFERED=1 +ARG DEBIAN_FRONTEND=noninteractive + +# Install updates +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y \ + ca-certificates \ + gettext \ + libssl1.1 \ + jq \ + vim \ + python3-pip \ + zstd \ + openssl \ + && rm -rf /var/cache/apt \ + && rm -rf /var/lib/apt/lists/* + +# update pip +RUN pip3 install --upgrade pip + +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/fog-sql-recovery-db-migrations /usr/local/bin/ +COPY ${RUST_BIN_PATH}/generate-sample-ledger /usr/local/bin/ +COPY ${RUST_BIN_PATH}/sample-keys /usr/local/bin/ +COPY ${RUST_BIN_PATH}/fog-distribution /usr/local/bin/ +COPY ${RUST_BIN_PATH}/test_client /usr/local/bin/ +COPY ${RUST_BIN_PATH}/fog_ingest_client /usr/local/bin/ +COPY ${RUST_BIN_PATH}/mc-consensus-mint-client /usr/local/bin/ +COPY ${RUST_BIN_PATH}/mc-util-seeded-ed25519-key-gen /usr/local/bin/ +COPY ${RUST_BIN_PATH}/fog-report-cli /usr/local/bin/ +COPY ${RUST_BIN_PATH}/read-pubfile /usr/local/bin/ +COPY ${RUST_BIN_PATH}/mc-util-grpc-token-generator /usr/local/bin/ + +# Test wrappers and util scripts +COPY .internal-ci/test/ /test/ +COPY .internal-ci/util/ /util/ + +# Proto files +COPY api/proto/* /proto/api/ +COPY mobilecoind/api/proto/* /proto/mobilecoind/ +COPY consensus/api/proto/* /proto/consensus/ +COPY mint-auditor/api/proto/* /proto/mint-auditor/ + +# Python tests +COPY mobilecoind/strategies/ /test/mobilecoind/strategies/ +COPY mobilecoind-json/tests/ /test/mobilecoind-json/ +COPY mint-auditor/tests/ /test/mint-auditor/ + +# Install mobilecoind integration test requirements +RUN pip3 install -r /test/mobilecoind/strategies/requirements.txt + +# Entrypoint +COPY .internal-ci/docker/entrypoints/bootstrap-tools.sh /usr/local/bin/entrypoint.sh +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/.internal-ci/docker/Dockerfile.fog-ledger b/.internal-ci/docker/Dockerfile.fog-ledger new file mode 100644 index 0000000000..77eb27228e --- /dev/null +++ b/.internal-ci/docker/Dockerfile.fog-ledger @@ -0,0 +1,35 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.fog-ledger +# +# Runtime image for MobileCoin fog-ledger nodes. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +# Copy binaries +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/libledger-enclave.signed.so /usr/bin/ +COPY ${RUST_BIN_PATH}/ledger_server /usr/bin/ +COPY ${RUST_BIN_PATH}/mobilecoind /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-admin-http-gateway /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-ledger-migration /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-util-grpc-admin-tool /usr/bin/ + +# Entrypoint +# COPY docker/entrypoints/fog-ledger.sh /usr/bin/entrypoint.sh +# ENTRYPOINT ["/usr/bin/entrypoint.sh"] + +# Rust defaults +ENV RUST_BACKTRACE="1" +ENV RUST_LOG="info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn" +ENV RUST_LOG_STYLE="never" + +# Default Ports +# HTTP Management +EXPOSE 8000 +# GRPC Ledger API +EXPOSE 3228 + +# App Defaults +ENV OMAP_CAPACITY=2097152 diff --git a/.internal-ci/docker/Dockerfile.fog-test-client b/.internal-ci/docker/Dockerfile.fog-test-client new file mode 100644 index 0000000000..6d3ec21d43 --- /dev/null +++ b/.internal-ci/docker/Dockerfile.fog-test-client @@ -0,0 +1,58 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.fog-test-client +# +# Binaries and associated tools for running fog-test-client in canary mode for continuous +# e2e testing. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +RUN addgroup --system --gid 1000 app \ + && addgroup --system --gid 2000 app-data \ + && adduser --system --ingroup app --uid 1000 app \ + && usermod -a -G 2000 app + +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y ca-certificates \ + && apt-get clean \ + && rm -r /var/lib/apt/lists + +# Copy binaries +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/test_client /usr/local/bin/ +COPY ${RUST_BIN_PATH}/mc-admin-http-gateway /usr/local/bin/ +COPY ${RUST_BIN_PATH}/mc-util-grpc-token-generator /usr/local/bin/ + +# Entrypoint +COPY .internal-ci/docker/entrypoints/fog-test-client.sh /usr/local/bin/entrypoint.sh + +ENV KEY_DIR /keys +ENV CONSENSUS_ENCLAVE_CSS /measurements/consensus-enclave.css +ENV INGEST_ENCLAVE_CSS /measurements/ingest-enclave.css +ENV LEDGER_ENCLAVE_CSS /measurements/ledger-enclave.css +ENV VIEW_ENCLAVE_CSS /measurements/view-enclave.css +ENV ADMIN_LISTEN_URI insecure-mca://0.0.0.0:8001/ +ENV TRANSFER_AMOUNT 100000000000 +ENV CONTINUOUS true +ENV TRANSFER_PERIOD 60 +ENV CONSENSUS_WAIT 15 +ENV NUM_CLIENTS 4 +ENV NO_MEMOS true + +# Required Environment Variables +# CONSENSUS_VALIDATORS - comma separated list of consensus urls. +# FOG_VIEW - fog view url. +# FOG_LEDGER - fog ledger url. +# CLIENT_AUTH_TOKEN_SECRET - if running against a Signal fog instance. + +# Share key files in /keys +VOLUME /keys +# Share enclave css files in /measurements +VOLUME /measurements + +USER app +EXPOSE 8001 +ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ] +CMD [ "/usr/local/bin/test_client" ] diff --git a/.internal-ci/docker/Dockerfile.fogingest b/.internal-ci/docker/Dockerfile.fogingest new file mode 100644 index 0000000000..611fb2cfda --- /dev/null +++ b/.internal-ci/docker/Dockerfile.fogingest @@ -0,0 +1,34 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.fogingest +# +# Runtime image for MobileCoin fogingest nodes. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +# Copy binaries +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/libingest-enclave.signed.so /usr/bin/ +COPY ${RUST_BIN_PATH}/mobilecoind /usr/bin/ +COPY ${RUST_BIN_PATH}/fog_ingest_server /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-admin-http-gateway /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-ledger-migration /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-util-grpc-admin-tool /usr/bin/ + +# Entrypoint +# COPY docker/entrypoints/fogingest.sh /usr/bin/entrypoint.sh +# ENTRYPOINT ["/usr/bin/entrypoint.sh"] + +# Rust defaults +ENV RUST_BACKTRACE="1" +ENV RUST_LOG="info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn" +ENV RUST_LOG_STYLE="never" + +# Default Ports +# HTTP Management +EXPOSE 8000 +# GRPC Ingest API +EXPOSE 3226 +# GRPC Peer +EXPOSE 8090 diff --git a/.internal-ci/docker/Dockerfile.fogreport b/.internal-ci/docker/Dockerfile.fogreport new file mode 100644 index 0000000000..6f79479042 --- /dev/null +++ b/.internal-ci/docker/Dockerfile.fogreport @@ -0,0 +1,29 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.fogreport +# +# Runtime image for MobileCoin fogreport nodes. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +# Copy binaries +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/mc-admin-http-gateway /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-util-grpc-admin-tool /usr/bin/ +COPY ${RUST_BIN_PATH}/report_server /usr/bin/ + +# Entrypoint +# COPY docker/entrypoints/fogreport.sh /usr/bin/entrypoint.sh +# ENTRYPOINT ["/usr/bin/entrypoint.sh"] + +# Rust defaults +ENV RUST_BACKTRACE="1" +ENV RUST_LOG="info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn" +ENV RUST_LOG_STYLE="never" + +# Default Ports +# HTTP Management +EXPOSE 8000 +# GRPC Report API +EXPOSE 3222 diff --git a/.internal-ci/docker/Dockerfile.fogview b/.internal-ci/docker/Dockerfile.fogview new file mode 100644 index 0000000000..35e369b559 --- /dev/null +++ b/.internal-ci/docker/Dockerfile.fogview @@ -0,0 +1,33 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.fogview +# +# Runtime image for MobileCoin fogview nodes. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +# Copy binaries +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/libview-enclave.signed.so /usr/bin/ +COPY ${RUST_BIN_PATH}/fog_view_server /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-admin-http-gateway /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-util-grpc-admin-tool /usr/bin/ + +# Entrypoint +# COPY docker/entrypoints/fogview.sh /usr/bin/entrypoint.sh +# ENTRYPOINT ["/usr/bin/entrypoint.sh"] + +# Rust defaults +ENV RUST_BACKTRACE="1" +ENV RUST_LOG="info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn" +ENV RUST_LOG_STYLE="never" + +# Default Ports +# HTTP Management +EXPOSE 8000 +# GRPC View +EXPOSE 3225 + +# App Defaults +ENV OMAP_CAPACITY=2097152 diff --git a/.internal-ci/docker/Dockerfile.go-grpc-gateway b/.internal-ci/docker/Dockerfile.go-grpc-gateway new file mode 100644 index 0000000000..9ca5aa90f0 --- /dev/null +++ b/.internal-ci/docker/Dockerfile.go-grpc-gateway @@ -0,0 +1,16 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.go-grpc-gateway +# +# Runtime Image for the json -> grpc gateway service. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +ARG GO_BIN_PATH=go-grpc-gateway +COPY ${GO_BIN_PATH}/grpc-proxy /usr/bin/go-grpc-gateway + +COPY .internal-ci/docker/entrypoints/go-grpc-gateway.sh /usr/bin/entrypoint.sh +ENTRYPOINT ["/usr/bin/entrypoint.sh"] + +EXPOSE 8000 diff --git a/.internal-ci/docker/Dockerfile.mobilecoind b/.internal-ci/docker/Dockerfile.mobilecoind new file mode 100644 index 0000000000..742637536b --- /dev/null +++ b/.internal-ci/docker/Dockerfile.mobilecoind @@ -0,0 +1,48 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.mobilecoind +# +# Runtime image for mobilecoind service. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +# Copy binaries +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/mobilecoind /usr/bin/ +COPY ${RUST_BIN_PATH}/mobilecoind-json /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-ledger-migration /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-util-grpc-admin-tool /usr/bin/ +COPY ${RUST_BIN_PATH}/libingest-enclave.css /enclaves/libingest-enclave.css + +# mint-auditor +# CBB: maybe a standalone service with a embedded mobilecoind? +COPY ${RUST_BIN_PATH}/mc-mint-auditor /usr/bin + +# Add attest test_certs +COPY attest/test_certs/ /var/lib/mobilecoin/attest/test_certs + +# Entrypoint +# COPY docker/entrypoints/mobilecoind.sh /usr/bin/entrypoint.sh +# ENTRYPOINT ["/usr/bin/entrypoint.sh"] + +# Rust defaults +ENV RUST_BACKTRACE="1" +ENV RUST_LOG="info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn" +ENV RUST_LOG_STYLE="never" + +# App paths (TODO make volumes and clean up) +ARG NODE_LEDGER_DIR="/var/lib/mobilecoin/ledger" +ARG MOBILECOIND_DB_DIR="/var/lib/mobilecoin/mobilecoind_db" +ENV NODE_LEDGER_DIR=${NODE_LEDGER_DIR} +ENV MOBILECOIND_DB_DIR=${MOBILECOIND_DB_DIR} +ENV MC_FOG_INGEST_ENCLAVE_CSS="/enclaves/libingest-enclave.css" + +# Default Ports +# GRPC Client +EXPOSE 3229 +# JSON Client +EXPOSE 9090 + +# mint-auditor grpc client +EXPOSE 7774 diff --git a/.internal-ci/docker/Dockerfile.node_hw b/.internal-ci/docker/Dockerfile.node_hw new file mode 100644 index 0000000000..6b1e0f1892 --- /dev/null +++ b/.internal-ci/docker/Dockerfile.node_hw @@ -0,0 +1,44 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.node_hw +# +# Runtime image for MobileCoin consensus nodes built in SGX hw mode. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +# Copy binaries +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/consensus-service /usr/bin/ +COPY ${RUST_BIN_PATH}/ledger-distribution /usr/bin/ +COPY ${RUST_BIN_PATH}/ledger-from-archive /usr/bin/ +COPY ${RUST_BIN_PATH}/libconsensus-enclave.signed.so /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-admin-http-gateway /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-ledger-migration /usr/bin/ +COPY ${RUST_BIN_PATH}/mc-util-grpc-admin-tool /usr/bin/ + +COPY ${RUST_BIN_PATH}/sample-keys /usr/local/bin/ +COPY ${RUST_BIN_PATH}/generate-sample-ledger /usr/local/bin/ +COPY .internal-ci/util/generate_origin_data.sh /usr/local/bin/ + +# Populate origin data +# We should pull origin data at runtime from an external source, like a public s3 url, but keep this for legacy. +ARG ORIGIN_DATA_DIR=.internal-ci/sample_data +COPY ${ORIGIN_DATA_DIR}/ledger /var/lib/mobilecoin/origin_data + +# Entrypoint +# COPY docker/entrypoints/consensus_validator.sh /usr/bin/entrypoint.sh +# ENTRYPOINT ["/usr/bin/entrypoint.sh"] + +# Rust defaults +ENV RUST_BACKTRACE="1" +ENV RUST_LOG="info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn" +ENV RUST_LOG_STYLE="never" + +# Default Ports +# HTTP Management +EXPOSE 8000 +# GRPC Client +EXPOSE 3223 +# GRPC Peer +EXPOSE 8443 diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base new file mode 100644 index 0000000000..f33382613a --- /dev/null +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -0,0 +1,41 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.runtime-base +# A minimal base runtime image for mobilecoin applications. +# +FROM ubuntu:focal-20220404 + +SHELL ["/bin/bash", "-c"] + +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg \ + supervisor \ + libpq5 + +# Install Filebeat repo +RUN curl --retry 5 -fL https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add - \ + && echo "deb https://artifacts.elastic.co/packages/oss-8.x/apt stable main" > /etc/apt/sources.list.d/elastic-8.x.list + +# Install SGX ASEM repo +COPY .internal-ci/docker/support/intel-sgx-archive-keyring.gpg /etc/apt/trusted.gpg.d/ +RUN echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ focal main" > /etc/apt/sources.list.d/intel-sgx.list + +# Install packages +RUN apt-get update \ + && apt-get install -y \ + filebeat \ + sgx-aesm-service \ + libsgx-epid \ + && apt-get clean \ + && rm -r /var/lib/apt/lists + +# Install GRPC health probe +ARG GRPC_HEALTH_UTILITY_URL=https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/v0.4.7/grpc_health_probe-linux-amd64 + +RUN curl --retry 5 -fL ${GRPC_HEALTH_UTILITY_URL} -o /usr/local/bin/grpc_health_probe \ + && chmod +x /usr/local/bin/grpc_health_probe diff --git a/.internal-ci/docker/Dockerfile.watcher b/.internal-ci/docker/Dockerfile.watcher new file mode 100644 index 0000000000..cb4515a47f --- /dev/null +++ b/.internal-ci/docker/Dockerfile.watcher @@ -0,0 +1,17 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Dockerfile.watcher +# +# Runtime image for MobileCoin watcher service. + +ARG REPO_ORG=mobilecoin +FROM ${REPO_ORG}/runtime-base:latest + +# Copy binaries +ARG RUST_BIN_PATH=target/release +COPY ${RUST_BIN_PATH}/mc-watcher /usr/bin/ + +# Rust defaults +ENV RUST_BACKTRACE="1" +ENV RUST_LOG="info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn" +ENV RUST_LOG_STYLE="never" diff --git a/.internal-ci/docker/entrypoints/bootstrap-tools.sh b/.internal-ci/docker/entrypoints/bootstrap-tools.sh new file mode 100755 index 0000000000..4a8d4375e0 --- /dev/null +++ b/.internal-ci/docker/entrypoints/bootstrap-tools.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Entrypoint script to set up testing environment in bootstrap(toolbox) container. + +exec "$@" diff --git a/.internal-ci/docker/entrypoints/fog-test-client.sh b/.internal-ci/docker/entrypoints/fog-test-client.sh new file mode 100755 index 0000000000..f5b2d735cc --- /dev/null +++ b/.internal-ci/docker/entrypoints/fog-test-client.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Entrypoint script to set up fog-test-client environment. +# + +function parse_url() +{ + # extract the protocol + proto=$(echo "$1" | grep :// | sed -e's,^\(.*://\).*,\1,g') + # remove the protocol + url="${1/$proto/}" + # extract the user (if any) + user=$(echo "${url}" | grep @ | cut -d@ -f1) + # extract the host and port + hostport=$(echo "${url/$user@/}" | cut -d/ -f1) + # by request host without port + host="${hostport/:*/}" + # by request - try to extract the port + port=$(echo "${hostport}" | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g') + # extract the path (if any) + path=$(echo "${url}" | grep / | cut -d/ -f2-) +} + +# check to see if a var is set. Exit 1 if not set. +# 1: Variable name +function is_set() +{ + var_name="${1}" + + if [ -z "${!var_name}" ]; then + echo "${var_name} is not set." + exit 1 + fi +} + +is_set FOG_LEDGER +is_set FOG_VIEW +is_set CONSENSUS_VALIDATORS + +if [ -n "${CLIENT_AUTH_TOKEN_SECRET}" ] +then + echo "Generating Client Auth Creds" + us="user1" + pw=$(mc-util-grpc-token-generator --shared-secret "${CLIENT_AUTH_TOKEN_SECRET}" --username user1 | grep Password: | awk '{print $2}') + + echo "Re-exporting FOG_LEDGER with user/token" + parse_url "${FOG_LEDGER}" + export FOG_LEDGER="${proto}${us}:${pw}@${host}:${port}/${path}" + + echo "Re-exporting FOG_VIEW with user/token" + parse_url "${FOG_VIEW}" + export FOG_VIEW="${proto}${us}:${pw}@${host}:${port}/${path}" +fi + +exec "$@" diff --git a/.internal-ci/docker/entrypoints/go-grpc-gateway.sh b/.internal-ci/docker/entrypoints/go-grpc-gateway.sh new file mode 100755 index 0000000000..a52ea53699 --- /dev/null +++ b/.internal-ci/docker/entrypoints/go-grpc-gateway.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# entrypoint script for the go-grpc-gateway (json -> grpc) +# + +# exit if anything fails. +if [[ ${ENTRYPOINT_DEBUG} == "true" ]]; then + set -ex +else + set -e +fi + +/usr/bin/go-grpc-gateway \ + -grpc-server-endpoint "${GRPC_SERVER_ENDPOINT}" \ + "${GRPC_INSECURE}" \ + -http-server-listen "${HTTP_SERVER_LISTEN}" + +wait -n diff --git a/.internal-ci/docker/support/intel-sgx-archive-keyring.gpg b/.internal-ci/docker/support/intel-sgx-archive-keyring.gpg new file mode 100644 index 0000000000000000000000000000000000000000..7af2429d7bca8dd79ec8b667006e7c9ed1f65813 GIT binary patch literal 362 zcmV-w0hRul0F4A(=Tz(g1OVo9JKTJ~Oh%S;oSDROMS+d2T7-%) z`W+K829zc<)OxA5B-kCY(W))P32W32u`Vi&ybRb*yghHhmb_z2GRNWh9a0(?(;W8| zx=?!%_kGUXFyL0bpH<>{5ma-F) IQ;KS=$;xDqmjD0& literal 0 HcmV?d00001 diff --git a/.internal-ci/helm/consensus-node-config/.helmignore b/.internal-ci/helm/consensus-node-config/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/.internal-ci/helm/consensus-node-config/Chart.yaml b/.internal-ci/helm/consensus-node-config/Chart.yaml new file mode 100644 index 0000000000..d74496c03d --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/Chart.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: consensus-node-config +description: Consensus node specific configuration. +type: application +version: 0.0.0 +appVersion: 1.0.0 diff --git a/.internal-ci/helm/consensus-node-config/templates/NOTES.txt b/.internal-ci/helm/consensus-node-config/templates/NOTES.txt new file mode 100644 index 0000000000..2671db2149 --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/templates/NOTES.txt @@ -0,0 +1,5 @@ +Common consensus config + +Client hostname: {{ include "consensusNodeConfig.clientHostname" . }} +Peer hostname: {{ include "consensusNodeConfig.peerHostname" . }} +Blockchain Path: {{ include "consensusNodeConfig.ledgerDistributionAWSPath" . }} diff --git a/.internal-ci/helm/consensus-node-config/templates/_helpers.tpl b/.internal-ci/helm/consensus-node-config/templates/_helpers.tpl new file mode 100644 index 0000000000..fe4b8c7526 --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/templates/_helpers.tpl @@ -0,0 +1,70 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* +Expand the name of the consensusNodeConfig. +*/}} +{{- define "consensusNodeConfig.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "consensusNodeConfig.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- tpl .Values.fullnameOverride . | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "consensusNodeConfig.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "consensusNodeConfig.labels" -}} +helm.sh/chart: {{ include "consensusNodeConfig.chart" . }} +{{ include "consensusNodeConfig.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "consensusNodeConfig.selectorLabels" -}} +app.kubernetes.io/name: {{ include "consensusNodeConfig.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* Figure out our node id from the name or use values clientHostname/peerHostname */}} + +{{/* clientHostname */}} +{{- define "consensusNodeConfig.clientHostname" -}} +{{- tpl .Values.node.client.hostname . }} +{{- end }} + +{{/* peerHostname */}} +{{- define "consensusNodeConfig.peerHostname" -}} +{{- tpl .Values.node.peer.hostname . }} +{{- end }} + +{{/* ledgerDistributionAWSPath */}} +{{- define "consensusNodeConfig.ledgerDistributionAWSPath" -}} +{{ printf "s3://%s/%s?region=%s" .Values.global.node.ledgerDistribution.s3Bucket (include "consensusNodeConfig.clientHostname" .) .Values.global.node.ledgerDistribution.awsRegion }} +{{- end }} diff --git a/.internal-ci/helm/consensus-node-config/templates/node-config-configmap.yaml b/.internal-ci/helm/consensus-node-config/templates/node-config-configmap.yaml new file mode 100644 index 0000000000..00a3a24bd3 --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/templates/node-config-configmap.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "consensusNodeConfig.fullname" . }}-consensus-node + labels: + {{- include "consensusNodeConfig.labels" . | nindent 4 }} +data: + clientHostname: {{ include "consensusNodeConfig.clientHostname" . | squote }} + peerHostname: {{ include "consensusNodeConfig.peerHostname" . | squote }} + blockVersion: {{ .Values.global.node.nodeConfig.blockVersion | squote }} diff --git a/.internal-ci/helm/consensus-node-config/templates/node-ledger-distribution-secret.yaml b/.internal-ci/helm/consensus-node-config/templates/node-ledger-distribution-secret.yaml new file mode 100644 index 0000000000..4370780dfc --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/templates/node-ledger-distribution-secret.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "consensusNodeConfig.fullname" . }}-ledger-distribution + labels: + {{- include "consensusNodeConfig.labels" . | nindent 4 }} +type: Opaque +stringData: + {{- with .Values.global.node.ledgerDistribution }} + AWS_ACCESS_KEY_ID: {{ .awsAccessKeyId | quote }} + AWS_SECRET_ACCESS_KEY: {{ .awsSecretAccessKey | quote }} + AWS_REGION: {{ .awsRegion | quote }} + LEDGER_DISTRIBUTION_S3_BUCKET: {{ .s3Bucket | quote }} + LEDGER_DISTRIBUTION_START_FROM: {{ .startFrom | quote }} + LEDGER_DISTRIBUTION_S3_PATH: {{ tpl .awsPath $ | quote }} + {{- end }} diff --git a/.internal-ci/helm/consensus-node-config/templates/node-msg-signer-key-secret.yaml b/.internal-ci/helm/consensus-node-config/templates/node-msg-signer-key-secret.yaml new file mode 100644 index 0000000000..f6e5ce1d76 --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/templates/node-msg-signer-key-secret.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ include "consensusNodeConfig.fullname" . }}-msg-signer-key + labels: + {{- include "consensusNodeConfig.labels" . | nindent 4 }} +stringData: + NODE_SIGNER_KEY: {{ .Values.node.msgSignerKey.privateKey | quote }} diff --git a/.internal-ci/helm/consensus-node-config/templates/node-network-config-configmap.yaml b/.internal-ci/helm/consensus-node-config/templates/node-network-config-configmap.yaml new file mode 100644 index 0000000000..2ae9296bd6 --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/templates/node-network-config-configmap.yaml @@ -0,0 +1,39 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- $peers := .Values.global.node.networkConfig.peers }} +{{- $threshold := .Values.global.node.networkConfig.threshold }} +{{- $localPeerHostname := (include "consensusNodeConfig.peerHostname" .) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "consensusNodeConfig.fullname" . }}-network-config + labels: + {{- include "consensusNodeConfig.labels" . | nindent 4 }} +data: + network.toml: | + broadcast_peers = [ + {{- range $key, $value := $peers }} + {{- $peerHostname := tpl $value.peer.hostname $ }} + {{- if not (eq $peerHostname $localPeerHostname) }} + "mcp://{{ $peerHostname }}:{{ $value.peer.port }}/?consensus-msg-key={{ $value.signerPublicKey }}", + {{- end }} + {{- end }} + ] + + tx_source_urls = [ + {{- range $key, $value := $peers }} + {{- $peerHostname := tpl $value.peer.hostname $ }} + {{- $ledgerArchiveLocation := tpl $value.ledgerArchiveLocation $ }} + {{- if not (eq $peerHostname $localPeerHostname) }} + "{{ $ledgerArchiveLocation }}", + {{- end }} + {{- end }} + ] + + quorum_set = { threshold = {{ $threshold }}, members = [ + {{- range $key, $value := $peers }} + {{- $peerHostname := tpl $value.peer.hostname $ }} + {{- if not (eq $peerHostname $localPeerHostname) }} + { type = "Node", args = "{{ $peerHostname }}:{{ $value.peer.port }}" }, + {{- end }} + {{- end }} + ] } diff --git a/.internal-ci/helm/consensus-node-config/templates/node-tokens-config-configmap.yaml b/.internal-ci/helm/consensus-node-config/templates/node-tokens-config-configmap.yaml new file mode 100644 index 0000000000..5c4ffe74f0 --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/templates/node-tokens-config-configmap.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if .Values.global.node.tokensConfig }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "consensusNodeConfig.fullname" . }}-tokens-config + labels: + {{- include "consensusNodeConfig.labels" . | nindent 4 }} +data: + tokens.signed.json: | + {{- .Values.global.node.tokensConfig.tokensSignedJson | nindent 4 }} +{{- end }} diff --git a/.internal-ci/helm/consensus-node-config/values.yaml b/.internal-ci/helm/consensus-node-config/values.yaml new file mode 100644 index 0000000000..debc3fe477 --- /dev/null +++ b/.internal-ci/helm/consensus-node-config/values.yaml @@ -0,0 +1,58 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +### Set fullnameOverride to match the consensus-node release name. +# example consensus-node-1 +fullnameOverride: '' + +### This node's specific values +node: + ### This node's client fully qualified domain name. + client: + hostname: '' + ### This node's peer fully qualified domain name. + # maps to + peer: + hostname: '' + + ### This nodes's Message Signing Key + msgSignerKey: + privateKey: '' + +### Values that will be shared by all nodes, but generate a unique k8s objects per node. +global: + node: + ### Node configuration settings + nodeConfig: + ### Block version - set to upgrade block version. + blockVersion: 0 + + ### Ledger distribution settings. The default for awsPath is auto-generated based on + # this values, but can be overridden. + # https://github.com/mobilecoinfoundation/mobilecoin/tree/master/ledger/distribution + ledgerDistribution: + awsAccessKeyId: '' + awsSecretAccessKey: '' + awsRegion: '' + s3Bucket: '' + awsPath: '{{ include "consensusNodeConfig.ledgerDistributionAWSPath" . }}' + startFrom: last + + ### Network config list of settings to generate the network.toml file. + # You can list all the peers here. When we generate the node's config we + # will skip the the local node. + # https://github.com/mobilecoinfoundation/mobilecoin/tree/master/consensus/service + networkConfig: + threshold: '' + peers: {} + ### Needs to be a map so we can override a specific entry. + # The keys names don't really matter. + # 1: + # peer: + # hostname: peer1.test.example.com + # port: '443' + # signerPublicKey: public-key + # ledgerArchiveLocation: https://s3-location-hostname/ledger/peer1.test.example.com + + # json formatted tokens configuration file. see consensus/service/config/src/tokens.rs + # Add signed tokens.json with --set-file=global.node.tokensConfig.tokensSignedJson=tokens.signed.json + # tokensConfig: + # tokensSignedJson: |- diff --git a/.internal-ci/helm/consensus-node/Chart.yaml b/.internal-ci/helm/consensus-node/Chart.yaml new file mode 100644 index 0000000000..8b959dfaa2 --- /dev/null +++ b/.internal-ci/helm/consensus-node/Chart.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: consensus-node +description: MobileCoin consensus node +type: application +version: 0.0.0 +appVersion: 0.0.0 +dependencies: +- name: consensus-node-config + repository: file://../consensus-node-config + version: 0.0.0 + condition: consensusNodeConfig.enabled + alias: consensusNodeConfig +- name: mc-core-common-config + repository: file://../mc-core-common-config + version: 0.0.0 + condition: mcCoreCommonConfig.enabled + alias: mcCoreCommonConfig diff --git a/.internal-ci/helm/consensus-node/README.md b/.internal-ci/helm/consensus-node/README.md new file mode 100644 index 0000000000..f237d4d171 --- /dev/null +++ b/.internal-ci/helm/consensus-node/README.md @@ -0,0 +1,26 @@ +# consensus-node Helm Chart + +Deploy a single node of the consensus service + +```sh +helm upgrade node1 ./ -i -n \ + --set image.tag=prod-1.0.1-pre2 +``` +Note: generated PersistentVolumeClaims will stick around if the Helm Chart is removed or the pods are deleted and allowed to regenerate. + +## Setup + +Configure a `values.yaml` file or pre-populate your namespace with the following ConfigMaps and Secrets. + +- `mobilecoin-network` + + Mobilecoin network value for monitoring: mainnet, testnet, alpha... + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: mobilecoin-network + data: + network: testnet + ``` \ No newline at end of file diff --git a/.internal-ci/helm/consensus-node/templates/NOTES.txt b/.internal-ci/helm/consensus-node/templates/NOTES.txt new file mode 100644 index 0000000000..b63e476da3 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/NOTES.txt @@ -0,0 +1,17 @@ + +:::: :::: :::::::: ::::::::: ::::::::::: ::: :::::::::: ++:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: ++:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ ++#+ +:+ +#+ +#+ +:+ +#++:++#+ +#+ +#+ +#++:++# ++#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+# #+# #+# #+# #+# #+# #+# #+# #+# +### ### ######## ######### ########### ########## ########## + :::::::: :::::::: ::::::::::: :::: ::: +:+: :+: :+: :+: :+: :+:+: :+: ++:+ +:+ +:+ +:+ :+:+:+ +:+ ++#+ +#+ +:+ +#+ +#+ +:+ +#+ ++#+ +#+ +#+ +#+ +#+ +#+#+# +#+# #+# #+# #+# #+# #+# #+#+# + ######## ######## ########### ### #### + +MobileCoin Node deployment completed successfully. \ No newline at end of file diff --git a/.internal-ci/helm/consensus-node/templates/_helpers.tpl b/.internal-ci/helm/consensus-node/templates/_helpers.tpl new file mode 100644 index 0000000000..4a29bfac84 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/_helpers.tpl @@ -0,0 +1,111 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* Expand the name of the consensusNode. */}} +{{- define "consensusNode.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "consensusNode.fullname" -}} +{{- if .Values.fullnameOverride }} + {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} + {{- $name := default .Chart.Name .Values.nameOverride }} + {{- if contains $name .Release.Name }} + {{- .Release.Name | trunc 63 | trimSuffix "-" }} + {{- else }} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} + {{- end }} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "consensusNode.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Common labels */}} +{{- define "consensusNode.labels" -}} +helm.sh/chart: {{ include "consensusNode.chart" . }} +{{ include "consensusNode.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* Selector labels */}} +{{- define "consensusNode.selectorLabels" -}} +app.kubernetes.io/name: {{ include "consensusNode.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* Define Secret and ConfigMap object names */}} +{{- define "consensusNode.nodeConfig.configMap.name" -}} +{{ include "consensusNode.fullname" . }}-consensus-node +{{- end }} + +{{- define "consensusNode.ledgerDistribution.secret.name" -}} +{{ include "consensusNode.fullname" . }}-ledger-distribution +{{- end }} + +{{- define "consensusNode.msgSignerKey.secret.name" -}} +{{ include "consensusNode.fullname" . }}-msg-signer-key +{{- end }} + +{{- define "consensusNode.networkConfig.configMap.name" -}} +{{ include "consensusNode.fullname" . }}-network-config +{{- end }} + +{{- define "consensusNode.tokensConfig.configMap.name" -}} +{{ include "consensusNode.fullname" . }}-tokens-config +{{- end }} + +{{/* +peer and client hostnames - we need this for ingress. +lookup name from configmap if we have created the objects in consensus-node-config separately. +*/}} +{{- define "consensusNode.peerHostname" -}} + {{- if eq .Values.consensusNodeConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.peerHostname | default "" }} + {{- else }} + {{- tpl .Values.consensusNodeConfig.node.peer.hostname . }} + {{- end }} +{{- end }} + +{{- define "consensusNode.clientHostname" -}} + {{- if eq .Values.consensusNodeConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.clientHostname | default "" }} + {{- else }} + {{- tpl .Values.consensusNodeConfig.node.client.hostname . }} + {{- end }} +{{- end }} + +{{- define "consensusNode.blockVersion" -}} + {{- if eq .Values.consensusNodeConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.blockVersion | default "false" }} + {{- else }} + {{- tpl .Values.global.node.nodeConfig.blockVersion . }} + {{- end }} +{{- end }} + +{{/* Mobilecoin Network monitoring labels */}} +{{- define "consensusNode.mobileCoinNetwork.network" -}} + {{- if eq .Values.mcCoreCommonConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace "mobilecoin-network").data.network | default "" }} + {{- else }} + {{- tpl .Values.mcCoreCommonConfig.mobileCoinNetwork.network . }} + {{- end }} +{{- end }} + +{{- define "consensusNode.mobileCoinNetwork.partner" -}} + {{- if eq .Values.mcCoreCommonConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace "mobilecoin-network").data.partner | default "" }} + {{- else }} + {{- tpl .Values.mcCoreCommonConfig.mobileCoinNetwork.partner . }} + {{- end }} +{{- end }} diff --git a/.internal-ci/helm/consensus-node/templates/client-grpc-ingress.yaml b/.internal-ci/helm/consensus-node/templates/client-grpc-ingress.yaml new file mode 100644 index 0000000000..320bc11da4 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/client-grpc-ingress.yaml @@ -0,0 +1,46 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "consensusNode.fullname" . }}-client-grpc + annotations: + {{- toYaml .Values.node.client.ingress.annotations | nindent 4 }} + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + tls: + - hosts: + - {{ include "consensusNode.clientHostname" . }} + secretName: {{ include "consensusNode.fullname" . }}-client-tls + rules: + - host: {{ include "consensusNode.clientHostname" . }} + http: + paths: + - path: /attest.AttestedApi + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 3223 + - path: /build_info.BuildInfoApi + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 3223 + - path: /consensus_common.BlockchainAPI + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 3223 + - path: /consensus_client.ConsensusClientAPI + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 3223 diff --git a/.internal-ci/helm/consensus-node/templates/gateway-deployment.yaml b/.internal-ci/helm/consensus-node/templates/gateway-deployment.yaml new file mode 100644 index 0000000000..351e887739 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/gateway-deployment.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: Deployment +metadata: + name: grpc-gateway-{{ include "consensusNode.fullname" . }} + labels: + app: grpc-gateway + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + app: grpc-gateway + {{- include "consensusNode.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: grpc-gateway + {{- include "consensusNode.labels" . | nindent 8 }} + spec: + nodeSelector: + {{- toYaml .Values.grpcGateway.nodeSelector | nindent 8 }} + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 6 }} + containers: + - name: grpc-gateway + image: "{{ .Values.grpcGateway.image.org | default .Values.image.org }}/{{ .Values.grpcGateway.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: IfNotPresent + command: + - /usr/bin/go-grpc-gateway + - -grpc-server-endpoint={{ include "consensusNode.clientHostname" . }}:443 + - -http-server-listen=:8000 + - -logtostderr + ports: + - name: gateway + containerPort: 8000 diff --git a/.internal-ci/helm/consensus-node/templates/gateway-ingress.yaml b/.internal-ci/helm/consensus-node/templates/gateway-ingress.yaml new file mode 100644 index 0000000000..c7f8b37e6e --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/gateway-ingress.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "consensusNode.fullname" . }}-grpc-gateway + annotations: + {{- toYaml .Values.grpcGateway.ingress | nindent 4}} + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + tls: + - hosts: + - {{ include "consensusNode.clientHostname" . }} + secretName: {{ include "consensusNode.fullname" . }}-client-tls + rules: + - host: {{ include "consensusNode.clientHostname" . }} + http: + paths: + - path: /gw + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }}-grpc-gateway + port: + number: 8000 diff --git a/.internal-ci/helm/consensus-node/templates/gateway-service.yaml b/.internal-ci/helm/consensus-node/templates/gateway-service.yaml new file mode 100644 index 0000000000..a6182092ac --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/gateway-service.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "consensusNode.fullname" . }}-grpc-gateway + labels: + app: grpc-gateway + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: grpc-gateway + {{- include "consensusNode.selectorLabels" . | nindent 4 }} + ports: + - name: gateway + port: 8000 + targetPort: gateway diff --git a/.internal-ci/helm/consensus-node/templates/node-certificate.yaml b/.internal-ci/helm/consensus-node/templates/node-certificate.yaml new file mode 100644 index 0000000000..87d35b9f44 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/node-certificate.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: cert-manager.io/v1alpha2 +kind: Certificate +metadata: + name: {{ include "consensusNode.fullname" . }}-internal-tls + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + # Secret names are always required. + secretName: {{ include "consensusNode.fullname" . }}-internal-tls + duration: 8760h # 365d + renewBefore: 360h # 15d + keySize: 2048 + keyAlgorithm: rsa + keyEncoding: pkcs1 + usages: + - server auth + - client auth + dnsNames: + - {{ include "consensusNode.peerHostname" . }} + issuerRef: + name: internal-ca-issuer + kind: ClusterIssuer diff --git a/.internal-ci/helm/consensus-node/templates/node-data-volume.yaml b/.internal-ci/helm/consensus-node/templates/node-data-volume.yaml new file mode 100644 index 0000000000..e98be24574 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/node-data-volume.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if .Values.node.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "consensusNode.fullname" . }}-data + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + {{- toYaml .Values.node.persistence.spec | nindent 2 }} +{{- end }} diff --git a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml new file mode 100644 index 0000000000..05eec2a49a --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml @@ -0,0 +1,218 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "consensusNode.fullname" . }} + labels: + app: consensus-node + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: consensus-node + {{- include "consensusNode.selectorLabels" . | nindent 6 }} + {{- if .Values.loadBalancedNode }} + client-load-balanced: 'true' + {{- end }} + template: + metadata: + annotations: + {{- toYaml .Values.node.podAnnotations | nindent 8 }} + labels: + app: consensus-node + {{- include "consensusNode.labels" . | nindent 8 }} + {{- if .Values.loadBalancedNode }} + client-load-balanced: 'true' + {{- end }} + spec: + nodeSelector: + {{- toYaml .Values.node.nodeSelector | nindent 8 }} + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - consensus-node + topologyKey: 'kubernetes.io/hostname' + tolerations: + {{- toYaml .Values.node.tolerations | nindent 6 }} + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 6 }} + initContainers: + {{- tpl (toYaml .Values.node.initContainers) . | nindent 6 }} + containers: + - name: node + image: '{{ .Values.node.image.org | default .Values.image.org }}/{{ .Values.node.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' + imagePullPolicy: Always + command: [ '/usr/bin/supervisord' ] + ports: + - name: cns-client + containerPort: 3223 + - name: cns-port + containerPort: 8443 + - name: cns-mgmt + containerPort: 8000 + livenessProbe: + exec: + command: + - '/usr/local/bin/grpc_health_probe' + - '-addr=:8443' + failureThreshold: 3 + periodSeconds: 30 + readinessProbe: + exec: + command: + - '/usr/local/bin/grpc_health_probe' + - '-addr=:8443' + failureThreshold: 30 + periodSeconds: 30 + envFrom: + - secretRef: + name: {{ include "consensusNode.ledgerDistribution.secret.name" . }} + - secretRef: + name: {{ include "consensusNode.msgSignerKey.secret.name" . }} + - secretRef: + name: ias + env: + - name: PATH + value: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64' + - name: RUST_BACKTRACE + value: '1' + - name: RUST_LOG + value: 'info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn' + - name: LOCAL_NODE_ID + valueFrom: + configMapKeyRef: + name: {{ include "consensusNode.nodeConfig.configMap.name" . }} + key: peerHostname + # Responder ID will need to be made variable when we fix load balanced consensus nodes. + - name: CLIENT_RESPONDER_ID + valueFrom: + configMapKeyRef: + name: {{ include "consensusNode.nodeConfig.configMap.name" . }} + key: clientHostname + - name: MC_LOG_EXTRA_CONTEXT + value: 'mc.local_node_id=$(LOCAL_NODE_ID)' + - name: CONSENSUS_SERVICE_SENTRY_DSN + valueFrom: + configMapKeyRef: + name: sentry + key: consensus-sentry-dsn + - name: LEDGER_DISTRIBUTION_SENTRY_DSN + valueFrom: + configMapKeyRef: + name: sentry + key: ledger-distribution-sentry-dsn + - name: MC_BRANCH + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network + - name: MC_BLOCK_VERSION + valueFrom: + configMapKeyRef: + name: {{ include "consensusNode.nodeConfig.configMap.name" . }} + key: blockVersion + # This file is generated at consensus node startup and should be persistent as long as its on the same node. + - name: SEALED_BLOCK_SIGNING_KEY + value: /sealed-signing-key/block-signing-key + volumeMounts: + - name: sealed-signing-key + mountPath: /sealed-signing-key + - name: aesm-socket-dir + mountPath: /var/run/aesmd + - name: config-dir + mountPath: /config + - name: ledger-db-dir + mountPath: /ledger + - name: keys-dir + mountPath: /keys + - name: node-cert + mountPath: /certs + readOnly: true + - name: supervisor-conf + mountPath: /etc/supervisor/conf.d + readOnly: true + resources: + {{- toYaml .Values.node.resources | nindent 10}} + {{- if eq .Values.jaegerTracing.enabled true }} + - name: jaeger-agent + image: jaegertracing/jaeger-agent:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5775 + name: zk-compact-trft + protocol: UDP + - containerPort: 5778 + name: config-rest + protocol: TCP + - containerPort: 6831 + name: jg-compact-trft + protocol: UDP + - containerPort: 6832 + name: jg-binary-trft + protocol: UDP + - containerPort: 14271 + name: admin-http + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + args: + - --reporter.grpc.host-port={{ .Values.jaegerTracing.collector }} + - --reporter.type=grpc + - --agent.tags=cluster=undefined,container.name=node,deployment.name={{ include "consensusNode.fullname" . }},host.ip=${HOST_IP:},pod.name=${POD_NAME:},pod.namespace={{ .Release.Namespace }} + {{- end }} + volumes: + - name: sealed-signing-key + emptyDir: {} + - name: keys-dir + emptyDir: {} + - name: aesm-socket-dir + emptyDir: {} + - name: config-dir + projected: + sources: + - configMap: + name: {{ include "consensusNode.networkConfig.configMap.name" . }} + - configMap: + name: {{ include "consensusNode.tokensConfig.configMap.name" . }} + - name: node-cert + secret: + secretName: {{ include "consensusNode.fullname" . }}-internal-tls + - name: supervisor-conf + projected: + sources: + - configMap: + name: {{ include "consensusNode.fullname" . }}-supervisor-daemon + - configMap: + name: {{ include "consensusNode.fullname" . }}-supervisor-sgx + - configMap: + name: {{ include "consensusNode.fullname" . }}-supervisor-consensus + - configMap: + name: {{ include "consensusNode.fullname" . }}-supervisor-ledger-distribution + - configMap: + name: {{ include "consensusNode.fullname" . }}-supervisor-admin-http-gw + - name: ledger-db-dir + {{- if eq .Values.node.persistence.enabled true }} + persistentVolumeClaim: + claimName: {{ include "consensusNode.fullname" . }}-data + {{- else }} + emptyDir: {} + {{- end }} diff --git a/.internal-ci/helm/consensus-node/templates/node-service.yaml b/.internal-ci/helm/consensus-node/templates/node-service.yaml new file mode 100644 index 0000000000..a6295aa557 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/node-service.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "consensusNode.fullname" . }} + labels: + app: consensus-node + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: consensus-node + {{- include "consensusNode.selectorLabels" . | nindent 4 }} + ports: + - name: cns-port + port: 8443 + targetPort: cns-port + - name: cns-mgmt + port: 8000 + targetPort: cns-mgmt + {{- if .Values.acceptClientConnections }} + - name: cns-client + port: 3223 + targetPort: cns-client + {{- end }} diff --git a/.internal-ci/helm/consensus-node/templates/node-servicemonitor.yaml b/.internal-ci/helm/consensus-node/templates/node-servicemonitor.yaml new file mode 100644 index 0000000000..8e607843ec --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/node-servicemonitor.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "consensusNode.fullname" . }} + labels: + publish: grafana-cloud + app: consensus-node + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: consensus-node + {{- include "consensusNode.selectorLabels" . | nindent 6 }} + endpoints: + - port: cns-mgmt + relabelings: + - targetLabel: instance + replacement: {{ include "consensusNode.clientHostname" . }} + - targetLabel: network + replacement: {{ include "consensusNode.mobileCoinNetwork.network" . }} + - targetLabel: partner + replacement: {{ include "consensusNode.mobileCoinNetwork.partner" . }} diff --git a/.internal-ci/helm/consensus-node/templates/peer-grpc-ingress.yaml b/.internal-ci/helm/consensus-node/templates/peer-grpc-ingress.yaml new file mode 100644 index 0000000000..193457a4ed --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/peer-grpc-ingress.yaml @@ -0,0 +1,53 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "consensusNode.fullname" . }}-peer-grpc + annotations: + {{- toYaml .Values.node.peer.ingress.annotations | nindent 4 }} + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +spec: + tls: + - hosts: + - {{ include "consensusNode.peerHostname" . }} + secretName: {{ include "consensusNode.fullname" . }}-peer-tls + rules: + - host: {{ include "consensusNode.peerHostname" . }} + http: + paths: + - path: /attest.AttestedApi + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 8443 + - path: /build_info + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 8443 + - path: /consensus_common.BlockchainAPI + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 8443 + - path: /consensus_peer.ConsensusPeerAPI + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 8443 + - path: /grpc.health.v1.Health + pathType: Prefix + backend: + service: + name: {{ include "consensusNode.fullname" . }} + port: + number: 8443 diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-admin-gateway-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-admin-gateway-configmap.yaml new file mode 100644 index 0000000000..a42cd3261d --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/supervisor-admin-gateway-configmap.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "consensusNode.fullname" . }}-supervisor-admin-http-gw + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +data: + admin_http_gw.conf: | + [program:mc-admin-http-gateway] + priority=200 + command=/usr/bin/mc-admin-http-gateway + --listen-host 0.0.0.0 + --listen-port 8000 + --admin-uri insecure-mca://127.0.0.1:8001/ + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-consensus-service-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-consensus-service-configmap.yaml new file mode 100644 index 0000000000..c7cbf2f144 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/supervisor-consensus-service-configmap.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "consensusNode.fullname" . }}-supervisor-consensus + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +data: + consensus-service-node.conf: | + [program:consensus-service] + priority=100 + environment=MC_SENTRY_DSN="%(ENV_CONSENSUS_SERVICE_SENTRY_DSN)s" + command=/usr/bin/consensus-service + --client-responder-id "%(ENV_CLIENT_RESPONDER_ID)s:443" + --peer-responder-id "%(ENV_LOCAL_NODE_ID)s:443" + --peer-listen-uri=insecure-mcp://0.0.0.0:8443/ + --admin-listen-uri=insecure-mca://127.0.0.1:8001/ + --network /config/network.toml + --tokens /config/tokens.signed.json + --ledger-path /ledger + --ias-spid "%(ENV_IAS_SPID)s" + --ias-api-key "%(ENV_IAS_API_KEY)s" + --msg-signer-key "%(ENV_NODE_SIGNER_KEY)s" + --sealed-block-signing-key "%(ENV_SEALED_BLOCK_SIGNING_KEY)s" + --scp-debug-dump /scp-debug-dump + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-daemon-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-daemon-configmap.yaml new file mode 100644 index 0000000000..0cef1a4458 --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/supervisor-daemon-configmap.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "consensusNode.fullname" . }}-supervisor-daemon + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +data: + supervisor.conf: | + [supervisord] + nodaemon=true diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-ledger-distribution-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-ledger-distribution-configmap.yaml new file mode 100644 index 0000000000..7559883cae --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/supervisor-ledger-distribution-configmap.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "consensusNode.fullname" . }}-supervisor-ledger-distribution + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +data: + ledger_dist.conf: | + [program:ledger-distribution] + priority=20 + environment=MC_SENTRY_DSN="%(ENV_LEDGER_DISTRIBUTION_SENTRY_DSN)s" + command=/usr/bin/ledger-distribution + --dest "%(ENV_LEDGER_DISTRIBUTION_S3_PATH)s" + --ledger-path /ledger + --state-file /ledger/.distribution-state + --start-from "%(ENV_LEDGER_DISTRIBUTION_START_FROM)s" + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-sgx-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-sgx-configmap.yaml new file mode 100644 index 0000000000..8734bf3e5d --- /dev/null +++ b/.internal-ci/helm/consensus-node/templates/supervisor-sgx-configmap.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "consensusNode.fullname" . }}-supervisor-sgx + labels: + {{- include "consensusNode.labels" . | nindent 4 }} +data: + sgx.conf: | + [program:aesm-service] + priority=10 + command=/opt/intel/sgx-aesm-service/aesm/aesm_service --no-daemon + environment=AESM_PATH="/opt/intel/sgx-aesm-service/aesm",LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" + + stdout_logfile=/dev/null + stderr_logfile=/dev/null + autorestart=true diff --git a/.internal-ci/helm/consensus-node/values.yaml b/.internal-ci/helm/consensus-node/values.yaml new file mode 100644 index 0000000000..df046a5ec8 --- /dev/null +++ b/.internal-ci/helm/consensus-node/values.yaml @@ -0,0 +1,208 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +fullnameOverride: '' + +imagePullSecrets: +- name: docker-credentials + +image: + org: mobilecoin + tag: '' + +### Shared values with child charts. +global: + # Shared across all instances of consensusNodeConfig config. + node: + ledgerDistribution: + awsAccessKeyId: '' + awsSecretAccessKey: '' + awsRegion: '' + s3Bucket: '' + startFrom: last + + networkConfig: + threshold: '' + peers: {} + + # tokensConfig: + # tokensSignedJson: |- + # { json } + +### Enable to launch child chart to create node required configMaps and secrets. +# See helm/consensus-node-config/values.yaml for config details. +consensusNodeConfig: + enabled: false + fullnameOverride: '{{ .Release.Name }}' + node: + client: + hostname: '' + peer: + hostname: '' + +### Enable to launch child chart to create core common configMaps and secrets. +# See helm/mc-core-common-config/values.yaml for config details. +mcCoreCommonConfig: + enabled: false + # clientAuth: + # token: '' + # ias: + # key: '' + # spid: '' + # mobileCoinNetwork: + # network: '' + # partner: '' + # sentry: + # consensus-sentry-dsn: '' + # ledger-distribution-sentry-dsn: '' + # fog-report-sentry-dsn: '' + # fog-view-sentry-dsn: '' + # fog-ledger-sentry-dsn: '' + # fog-ingest-sentry-dsn: '' + +# Consensus node settings +node: + image: + org: '' + name: node_hw + + podAnnotations: + fluentbit.io/include: 'true' + fluentbit.io/exclude-jaeger-agent: 'true' + + nodeSelector: + sgx-enabled-node: 'true' + + resources: + limits: + intel.com/sgx: 5000 + requests: + intel.com/sgx: 5000 + + tolerations: + - key: sgx + operator: Equal + value: 'true' + effect: NoSchedule + + initContainers: + - name: copy-ledger-from-container + image: '{{ .Values.node.image.org | default .Values.image.org }}/{{ .Values.node.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' + imagePullPolicy: Always + env: + - name: INITIAL_KEYS_SEED + valueFrom: + secretKeyRef: + name: sample-keys-seeds + key: INITIAL_KEYS_SEED + optional: true + command: [ '/bin/bash' ] + # CBB 1.2+ - convert to using MNEMONIC keys + args: + - -c + - | + set -e + if [ ! -f /ledger/data.mdb ]; then + if [[ -n "${INITIAL_KEYS_SEED}" ]]; then + echo "INITIAL_KEYS_SEED found - populating origin data" + export INITIALIZE_LEDGER="true" + /usr/local/bin/generate_origin_data.sh + cp /tmp/sample_data/ledger/data.mdb /ledger + elif [ -f /var/lib/mobilecoin/origin_data/data.mdb ]; then + echo "Copying ledger /var/lib/mobilecoin/origin_data/data.mdb to /ledger" + cp /var/lib/mobilecoin/origin_data/data.mdb /ledger + else + echo "INITIAL_KEYS_SEED not set and cannot find origin ledger file" + exit 1 + fi + else + echo "Ledger /ledger/data.mdb already exists" + fi + volumeMounts: + - name: ledger-db-dir + mountPath: /ledger + - name: migrate-ledger + image: '{{ .Values.node.image.org | default .Values.image.org }}/{{ .Values.node.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' + imagePullPolicy: Always + command: [ '/bin/bash' ] + args: + - -c + - | + set -e + if [[ -f "/ledger/data.mdb" ]] + then + cp /ledger/data.mdb /ledger/data.mdb.bak + /usr/bin/mc-ledger-migration --ledger-db /ledger + fi + volumeMounts: + - name: ledger-db-dir + mountPath: /ledger + + persistence: + enabled: true + spec: + storageClassName: fast + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 512Gi + + client: + ingress: + annotations: + cert-manager.io/cluster-issuer: letsencrypt-production-http + # HAProxy Ingress + haproxy.org/server-proto: 'h2' # Force GRPC/H2 mode + haproxy.org/server-ssl: 'false' # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: 'true' + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + # Nginx Ingress + nginx.ingress.kubernetes.io/ssl-redirect: 'true' + nginx.ingress.kubernetes.io/backend-protocol: 'GRPC' + + peer: + ingress: + annotations: + cert-manager.io/cluster-issuer: letsencrypt-production-http + # HAProxy Ingress + haproxy.org/server-proto: 'h2' # Force GRPC/H2 mode + haproxy.org/server-ssl: 'false' # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: 'true' + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + # Nginx Ingress + nginx.ingress.kubernetes.io/ssl-redirect: 'true' + nginx.ingress.kubernetes.io/backend-protocol: 'GRPC' + +# GRPC Gateway settings +grpcGateway: + image: + org: '' + name: go-grpc-gateway + nodeSelector: {} + ingress: + cert-manager.io/cluster-issuer: letsencrypt-production-http + #HAProxy Ingress + haproxy.org/path-rewrite: /gw/(.*) /\1 # Strip the /gw prefix + haproxy.org/server-ssl: 'false' # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: 'true' + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + # Nginx ingress + nginx.ingress.kubernetes.io/ssl-redirect: 'true' + +# Disable Client Connects +acceptClientConnections: true + +jaegerTracing: + enabled: true + collector: 'dns:///jaeger-collector:14250' diff --git a/.internal-ci/helm/fog-ingest-config/.helmignore b/.internal-ci/helm/fog-ingest-config/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/.internal-ci/helm/fog-ingest-config/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/.internal-ci/helm/fog-ingest-config/Chart.yaml b/.internal-ci/helm/fog-ingest-config/Chart.yaml new file mode 100644 index 0000000000..bdf5218c3a --- /dev/null +++ b/.internal-ci/helm/fog-ingest-config/Chart.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: fog-ingest-config +description: fog ingest config +type: application +version: 0.0.0 +appVersion: 0.0.0 diff --git a/.internal-ci/helm/fog-ingest-config/templates/NOTES.txt b/.internal-ci/helm/fog-ingest-config/templates/NOTES.txt new file mode 100644 index 0000000000..b17f939e82 --- /dev/null +++ b/.internal-ci/helm/fog-ingest-config/templates/NOTES.txt @@ -0,0 +1 @@ +fog-ingest config diff --git a/.internal-ci/helm/fog-ingest-config/templates/_helpers.tpl b/.internal-ci/helm/fog-ingest-config/templates/_helpers.tpl new file mode 100644 index 0000000000..305994dca6 --- /dev/null +++ b/.internal-ci/helm/fog-ingest-config/templates/_helpers.tpl @@ -0,0 +1,70 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* Expand the name of the fogIngestConfig. */}} +{{- define "fogIngestConfig.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "fogIngestConfig.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- tpl .Values.fullnameOverride . | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "fogIngestConfig.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "fogIngestConfig.labels" -}} +helm.sh/chart: {{ include "fogIngestConfig.chart" . }} +{{ include "fogIngestConfig.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* Selector labels */}} +{{- define "fogIngestConfig.selectorLabels" -}} +app.kubernetes.io/name: {{ include "fogIngestConfig.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* pgPassword - reuse existing password */}} +{{- define "fogIngestConfig.pgPassword" -}} +{{- $pgPassword := randAlphaNum 48 }} +{{- if .Values.fogRecoveryDatabase.password }} +{{- $pgPassword = .Values.fogRecoveryDatabase.password }} +{{- end }} +{{- $pgSecret := (lookup "v1" "Secret" .Release.Namespace "fog-recovery-postgresql") }} +{{- if $pgSecret }} +{{- $pgPassword = index $pgSecret.data "postgres-password" | b64dec }} +{{- end }} +{{- $pgPassword }} +{{- end }} + +{{/* pgPassword - reuse existing password */}} +{{- define "fogIngestConfig.pgReplicationPassword" -}} +{{- $pgReplicationPassword := randAlphaNum 48 }} +{{- $pgSecret := (lookup "v1" "Secret" .Release.Namespace "fog-recovery-postgresql") }} +{{- if $pgSecret }} +{{- $pgReplicationPassword = index $pgSecret.data "replication-password" | b64dec }} +{{- end }} +{{- $pgReplicationPassword }} +{{- end }} diff --git a/.internal-ci/helm/fog-ingest-config/templates/fog-ingest-configmap.yaml b/.internal-ci/helm/fog-ingest-config/templates/fog-ingest-configmap.yaml new file mode 100644 index 0000000000..bf4d3ff7d8 --- /dev/null +++ b/.internal-ci/helm/fog-ingest-config/templates/fog-ingest-configmap.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +kind: ConfigMap +apiVersion: v1 +metadata: + name: fog-ingest + labels: + {{- include "fogIngestConfig.labels" . | nindent 4 }} +data: + {{- toYaml .Values.fogIngest | nindent 2 }} diff --git a/.internal-ci/helm/fog-ingest-config/templates/fog-recovery-postgresql-configmap.yaml b/.internal-ci/helm/fog-ingest-config/templates/fog-recovery-postgresql-configmap.yaml new file mode 100644 index 0000000000..641ad8b0b2 --- /dev/null +++ b/.internal-ci/helm/fog-ingest-config/templates/fog-recovery-postgresql-configmap.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if .Values.fogRecoveryDatabase.configMap.enabled }} +kind: ConfigMap +apiVersion: v1 +metadata: + name: fog-recovery-postgresql + labels: + {{- include "fogIngestConfig.labels" . | nindent 4 }} +data: +# Note in live environments these values are populated by terraform. +# When we clean this up we will need to take in account other tools. +# duplication to support postgres chart and fog configs. + postgres-database: {{ .Values.fogRecoveryDatabase.database | quote }} + postgres-hostname: {{ .Values.fogRecoveryDatabase.hostname | quote }} + postgres-port: {{ .Values.fogRecoveryDatabase.port | quote }} + postgres-ssl-options: {{ .Values.fogRecoveryDatabase.options | quote }} + postgres-username: {{ .Values.fogRecoveryDatabase.username | quote }} + postgresql-database: {{ .Values.fogRecoveryDatabase.database | quote }} + postgresql-hostname: {{ .Values.fogRecoveryDatabase.hostname | quote }} + postgresql-port: {{ .Values.fogRecoveryDatabase.port | quote }} + postgresql-ssl-options: {{ .Values.fogRecoveryDatabase.options | quote }} + postgresql-username: {{ .Values.fogRecoveryDatabase.username | quote }} +{{- end }} diff --git a/.internal-ci/helm/fog-ingest-config/templates/fog-recovery-postgresql-secret.yaml b/.internal-ci/helm/fog-ingest-config/templates/fog-recovery-postgresql-secret.yaml new file mode 100644 index 0000000000..c21aef87e0 --- /dev/null +++ b/.internal-ci/helm/fog-ingest-config/templates/fog-recovery-postgresql-secret.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if .Values.fogRecoveryDatabase.secret.enabled }} +{{- $pw := (include "fogIngestConfig.pgPassword" .)}} +apiVersion: v1 +kind: Secret +metadata: + name: fog-recovery-postgresql + labels: + {{- include "fogIngestConfig.labels" . | nindent 4 }} +type: Opaque +stringData: +# Note in live environments these values are populated by terraform. +# When we clean this up we will need to take in account other tools. +# duplication to support postgres chart and fog configs. + postgres-password: {{ $pw | quote }} + postgresql-password: {{ $pw | quote }} + replication-password: {{ include "fogIngestConfig.pgReplicationPassword" . | quote }} +{{- end }} diff --git a/.internal-ci/helm/fog-ingest-config/values.yaml b/.internal-ci/helm/fog-ingest-config/values.yaml new file mode 100644 index 0000000000..52e6dfab87 --- /dev/null +++ b/.internal-ci/helm/fog-ingest-config/values.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +fullnameOverride: '' + +fogRecoveryDatabase: + configMap: + # Default to a TF or external created ConfigMap + enabled: false + secret: + # Default to a TF or external created Secret + enabled: false + ### helm install fog-recovery bitnami/postgresql -n \ + # --set global.postgresql.auth.existingSecret=fog-recover-postgresql \ + # --set global.postgresql.auth.database=fog_recovery \ + # -- + # For helm deployed postgres, set configMap.enabled and secret.enabled true + hostname: fog-recovery-postgresql-primary + password: '' + username: postgres + database: fog_recovery + port: '5432' + options: '?sslmode=disable' + +fogIngest: + # https://docs.diesel.rs/diesel/r2d2/struct.Builder.html + POSTGRES_IDLE_TIMEOUT: '60' + POSTGRES_MAX_LIFETIME: '120' + POSTGRES_CONNECTION_TIMEOUT: '5' + POSTGRES_MAX_CONNECTIONS: '3' + FOG_PUBKEY_EXPIRY_WINDOW: '10' diff --git a/.internal-ci/helm/fog-ingest/.helmignore b/.internal-ci/helm/fog-ingest/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/.internal-ci/helm/fog-ingest/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/.internal-ci/helm/fog-ingest/Chart.yaml b/.internal-ci/helm/fog-ingest/Chart.yaml new file mode 100644 index 0000000000..29f83de61c --- /dev/null +++ b/.internal-ci/helm/fog-ingest/Chart.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: fog-ingest +description: MobileCoin Fog Ingest service. +type: application +version: 0.0.0 +appVersion: 0.0.0 +dependencies: +- name: mc-core-common-config + repository: file://../mc-core-common-config + version: 0.0.0 + condition: mcCoreCommonConfig.enabled + alias: mcCoreCommonConfig +- name: fog-ingest-config + repository: file://../fog-ingest-config + version: 0.0.0 + condition: fogIngestConfig.enabled + alias: fogIngestConfig diff --git a/.internal-ci/helm/fog-ingest/README.md b/.internal-ci/helm/fog-ingest/README.md new file mode 100644 index 0000000000..ad28658506 --- /dev/null +++ b/.internal-ci/helm/fog-ingest/README.md @@ -0,0 +1,153 @@ +# fog-ingest Helm Chart + +Use in a blue/green type of deployment + +```sh +helm upgrade fog-ingest-blue ./ -i -n \ + --set image.tag=prod-1.0.1-pre2 +``` + +```sh +helm upgrade fog-ingest-green ./ -i -n \ + --set image.tag=prod-1.0.1-pre2 +``` + +Note: generated PersistentVolumeClaims will stick around if the Helm Chart is removed or the pods are deleted and allowed to regenerate. + +## Scaling + +`fog-ingest` is only designed to have one active instance. We should run at-least 2 in order to have a hot standby incase the active instance fails. Scaling the replicas doesn't improve performance. + +The peer list generation happens when the chart is generated. In order to scale the fog-ingest service you should adjust the `fogIngest.replicaCount` value and upgrade the fogIngest. The peer list is added to the ConfigMap additional pods will be added, but existing pods will not automatically update. Either destroy and re-create the pods or execute a restart of the fog services with supervisord. + +## Setup + +Configure a `values.yaml` file or pre-populate your namespace with the following ConfigMaps and Secrets. + +- `ias` + + Intel spid and primary or secondary key. + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: ias + type: Opaque + stringData: + key: + spid: + ``` + +- `sentry` + + Sentry service alert and error monitoring + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: sentry + data: + fog-ingest-sentry-dsn: + fog-view-sentry-dsn: + fog-ledger-sentry-dsn: + fog-report-sentry-dsn: + ledger-distribution-sentry-dsn: + ``` + +- `supervisord-mobilecoind` + + `mobilecoind` configuration for in container supervisord. Example values are for MobileCoin MainNet. + + `mobilecoind` needs direct connections to each node. The `--peer` url must have `?responder-id=` query string if the peer is part of a load balanced set. + + Set `--peer` and `--tx-source-url` (associated public s3 bucket https:// url) per node that you want to watch. + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: supervisord-mobilecoind + data: + mobilecoind.conf: | + [program:mobilecoind-sync] + command=/usr/bin/mobilecoind + --peer mc://node1.prod.mobilecoinww.com:443/ + --tx-source-url https://ledger.mobilecoinww.com/node1.prod.mobilecoinww.com + --peer mc://node2.prod.mobilecoinww.com:443/ + --tx-source-url https://ledger.mobilecoinww.com/node2.prod.mobilecoinww.com + --peer mc://node3.prod.mobilecoinww.com:443/ + --tx-source-url https://ledger.mobilecoinww.com/node3.prod.mobilecoinww.com + --ledger-db /fog-data/ledger + --watcher-db /fog-data/watcher + --poll-interval 1 + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true + ``` + +- `fog-recovery-postgresql` ConfigMap + + If you're using an cluster external database, populate the ConfigMap and Secret with the connection values. + + These example setting work with the helm postgresql chart when launched in the local namespace. + + ```sh + helm install fog-recovery bitnami/postgresql -n \ + --set postgresqlDatabase=recovery + ``` + + ```yaml + kind: ConfigMap + apiVersion: v1 + metadata: + name: fog-recovery-postgresql + data: + postgresql-database: recovery + postgresql-hostname: fog-recovery-postgresql + postgresql-port: "5432" + postgresql-ssl-options: "?sslmode=disable" # Set as appropriate + postgresql-username: postgres + ``` + + +- `fog-recovery-postgresql` Secret + + If you're using an cluster external database, populate the ConfigMap and Secret with the connection values. + + If you're using the postgresql helm chart launched as follows, this secret will be populated for you. + + ```sh + helm install fog-recovery bitnami/postgresql -n \ + --set postgresqlDatabase=recovery + ``` + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: fog-recovery-postgresql + type: Opaque + stringData: + postgresql-password: really-good-password + ``` + +- `fog-ingest` ConfigMap + + Database connection configuration for fog-ingest + + ```yaml + kind: ConfigMap + apiVersion: v1 + metadata: + name: fog-ingest + data: + POSTGRES_IDLE_TIMEOUT: "60" + POSTGRES_MAX_LIFETIME: "120" + POSTGRES_CONNECTION_TIMEOUT: "5" + POSTGRES_MAX_CONNECTIONS: "3" + ``` diff --git a/.internal-ci/helm/fog-ingest/templates/NOTES.txt b/.internal-ci/helm/fog-ingest/templates/NOTES.txt new file mode 100644 index 0000000000..15ef359d12 --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/NOTES.txt @@ -0,0 +1,17 @@ + +:::: :::: :::::::: ::::::::: ::::::::::: ::: :::::::::: ++:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: ++:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ ++#+ +:+ +#+ +#+ +:+ +#++:++#+ +#+ +#+ +#++:++# ++#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+# #+# #+# #+# #+# #+# #+# #+# #+# +### ### ######## ######### ########### ########## ########## + :::::::: :::::::: ::::::::::: :::: ::: +:+: :+: :+: :+: :+: :+:+: :+: ++:+ +:+ +:+ +:+ :+:+:+ +:+ ++#+ +#+ +:+ +#+ +#+ +:+ +#+ ++#+ +#+ +#+ +#+ +#+ +#+#+# +#+# #+# #+# #+# #+# #+# #+#+# + ######## ######## ########### ### #### + +Fog Ingest deployment successfully. Don't forget to retire/activate. diff --git a/.internal-ci/helm/fog-ingest/templates/_helpers.tpl b/.internal-ci/helm/fog-ingest/templates/_helpers.tpl new file mode 100644 index 0000000000..1a5d25e4c4 --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/_helpers.tpl @@ -0,0 +1,73 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* Expand the name of the fogIngest. */}} +{{- define "fogIngest.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "fogIngest.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "fogIngest.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Common labels */}} +{{- define "fogIngest.labels" -}} +helm.sh/chart: {{ include "fogIngest.chart" . }} +{{ include "fogIngest.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* Selector labels */}} +{{- define "fogIngest.selectorLabels" -}} +app.kubernetes.io/name: {{ include "fogIngest.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* Generate fog-ingest Peers List */}} +{{- define "fogIngest.peerURLs" }} + {{- $peerURLs := list }} + {{- $name := include "fogIngest.fullname" . }} + {{- $namespace := .Release.Namespace }} + {{- range $i, $e := until (int .Values.fogIngest.replicaCount ) }} + {{- $peerURLs = append $peerURLs (printf "insecure-igp://%s-%d.%s.%s.svc.cluster.local:8090" $name $i $name $namespace) }} + {{- end }} + {{- join "," $peerURLs }} +{{- end }} + +{{/* Mobilecoin Network monitoring labels */}} +{{- define "fogIngest.mobileCoinNetwork.network" -}} + {{- if eq .Values.mcCoreCommonConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace "mobilecoin-network").data.network | default "" }} + {{- else }} + {{- tpl .Values.mcCoreCommonConfig.mobileCoinNetwork.network . }} + {{- end }} +{{- end }} + +{{- define "fogIngest.mobileCoinNetwork.partner" -}} + {{- if eq .Values.mcCoreCommonConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace "mobilecoin-network").data.partner | default "" }} + {{- else }} + {{- tpl .Values.mcCoreCommonConfig.mobileCoinNetwork.partner . }} + {{- end }} +{{- end }} diff --git a/.internal-ci/helm/fog-ingest/templates/fog-ingest-service.yaml b/.internal-ci/helm/fog-ingest/templates/fog-ingest-service.yaml new file mode 100644 index 0000000000..0482f35911 --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/fog-ingest-service.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "fogIngest.fullname" . }} + labels: + app: fog-ingest + {{- include "fogIngest.labels" . | nindent 4 }} +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + selector: + {{- include "fogIngest.selectorLabels" . | nindent 4 }} + app: fog-ingest + ports: + - name: ingest + port: 3226 + targetPort: ingest + - name: peer + port: 8090 + targetPort: peer + - name: mgmt + port: 8000 + targetPort: mgmt \ No newline at end of file diff --git a/.internal-ci/helm/fog-ingest/templates/fog-ingest-servicmonitor.yaml b/.internal-ci/helm/fog-ingest/templates/fog-ingest-servicmonitor.yaml new file mode 100644 index 0000000000..71b6f0fc29 --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/fog-ingest-servicmonitor.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "fogIngest.fullname" . }} + labels: + publish: grafana-cloud + app: fog-ingest + {{- include "fogIngest.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: fog-ingest + {{- include "fogIngest.selectorLabels" . | nindent 6 }} + endpoints: + - port: mgmt + relabelings: + - targetLabel: network + replacement: {{ include "fogIngest.mobileCoinNetwork.network" . }} + - targetLabel: partner + replacement: {{ include "fogIngest.mobileCoinNetwork.partner" . }} diff --git a/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml b/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml new file mode 100644 index 0000000000..0f3b95f7e8 --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml @@ -0,0 +1,206 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "fogIngest.fullname" . }} + labels: + {{- include "fogIngest.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.fogIngest.replicaCount }} + selector: + matchLabels: + app: fog-ingest + {{- include "fogIngest.selectorLabels" . | nindent 6 }} + serviceName: {{ include "fogIngest.fullname" . }} + template: + metadata: + annotations: + {{- toYaml .Values.fogIngest.podAnnotations | nindent 8 }} + labels: + app: fog-ingest + {{- include "fogIngest.labels" . | nindent 8 }} + spec: + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 6 }} + terminationGracePeriodSeconds: 30 + dnsConfig: + options: + - name: ndots + value: "1" + initContainers: + {{- tpl (toYaml .Values.fogIngest.initContainers) . | nindent 6 }} + containers: + - name: fog-ingest + image: "{{ .Values.fogIngest.image.org | default .Values.image.org }}/{{ .Values.fogIngest.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.fogIngest.image.pullPolicy }} + command: [ "/usr/bin/supervisord" ] + ports: + - name: ingest + containerPort: 3226 + - name: peer + containerPort: 8090 + - name: mgmt + containerPort: 8000 + envFrom: + - configMapRef: + name: fog-ingest + - secretRef: + name: ias + - secretRef: + name: ipinfo + optional: true + env: + - name: RUST_BACKTRACE + value: {{ .Values.fogIngest.rust.backtrace | quote }} + - name: RUST_LOG + value: {{ .Values.fogIngest.rust.log | quote }} + - name: MY_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + # LOCAL_NODE_ID on ingest needs to be the name of the Service object that points to THIS ingest server + - name: LOCAL_NODE_ID + value: "$(MY_POD_NAME).{{ include "fogIngest.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:8090" + - name: FOG_INGEST_SENTRY_DSN + valueFrom: + configMapKeyRef: + name: sentry + key: fog-ingest-sentry-dsn + # Maps to Sentry Environment + - name: MC_BRANCH + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: FOGDB_HOST + valueFrom: + configMapKeyRef: + name: fog-recovery-postgresql + key: postgresql-hostname + - name: FOGDB_USER + valueFrom: + configMapKeyRef: + name: fog-recovery-postgresql + key: postgresql-username + - name: FOGDB_PASSWORD + valueFrom: + secretKeyRef: + name: fog-recovery-postgresql + key: postgresql-password + - name: FOGDB_DATABASE + valueFrom: + configMapKeyRef: + name: fog-recovery-postgresql + key: postgresql-database + - name: FOGDB_SSL_OPTIONS + valueFrom: + configMapKeyRef: + name: fog-recovery-postgresql + key: postgresql-ssl-options + - name: DATABASE_URL + value: 'postgres://$(FOGDB_USER):$(FOGDB_PASSWORD)@$(FOGDB_HOST)/$(FOGDB_DATABASE)$(FOGDB_SSL_OPTIONS)' + - name: STATE_FILE + value: /var/run/ingest-state-file + startupProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3226" + failureThreshold: 30 + periodSeconds: 10 + livenessProbe: + exec: + command: + - '/usr/local/bin/grpc_health_probe' + - '-addr=:3226' + failureThreshold: 5 + periodSeconds: 30 + readinessProbe: + exec: + command: + - '/usr/local/bin/grpc_health_probe' + - '-addr=:3226' + failureThreshold: 2 + periodSeconds: 30 + volumeMounts: + - name: aesm-socket-dir + mountPath: /var/run/aesmd + - name: fog-data + mountPath: /fog-data + - name: ingest-run-data + mountPath: /ingest-run-data + - name: supervisor-conf + mountPath: /etc/supervisor/conf.d + readOnly: true + resources: + {{- toYaml .Values.fogIngest.resources | nindent 10 }} + {{- if eq .Values.jaegerTracing.enabled true }} + - name: jaeger-agent + image: jaegertracing/jaeger-agent:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5775 + name: zk-compact-trft + protocol: UDP + - containerPort: 5778 + name: config-rest + protocol: TCP + - containerPort: 6831 + name: jg-compact-trft + protocol: UDP + - containerPort: 6832 + name: jg-binary-trft + protocol: UDP + - containerPort: 14271 + name: admin-http + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + args: + - --reporter.grpc.host-port={{ .Values.jaegerTracing.collector }} + - --reporter.type=grpc + - --agent.tags=cluster=undefined,container.name=fog-ingest,deployment.name={{ include "fogIngest.fullname" . }},host.ip=${HOST_IP:},pod.name=${POD_NAME:},pod.namespace={{ .Release.Namespace }} + {{- end }} + nodeSelector: + {{- toYaml .Values.fogIngest.nodeSelector | nindent 8 }} + tolerations: + {{- toYaml .Values.fogIngest.tolerations | nindent 6 }} + affinity: + {{- toYaml .Values.fogIngest.affinity | nindent 8 }} + volumes: + {{- if eq .Values.fogIngest.persistence.enabled false }} + - name: fog-data + emptyDir: {} + {{- end }} + - name: aesm-socket-dir + emptyDir: {} + - name: ingest-run-data + emptyDir: {} + - name: supervisor-conf + projected: + sources: + - configMap: + name: {{ include "fogIngest.fullname" . }}-supervisord-sgx + - configMap: + name: {{ include "fogIngest.fullname" . }}-supervisord-daemon + - configMap: + name: fog-supervisord-mobilecoind + - configMap: + name: {{ include "fogIngest.fullname" . }}-supervisord-fog-ingest + - configMap: + name: {{ include "fogIngest.fullname" . }}-supervisord-admin + {{- if .Values.fogIngest.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: fog-data + spec: + {{- toYaml .Values.fogIngest.persistence.spec | nindent 6 }} + {{- end }} diff --git a/.internal-ci/helm/fog-ingest/templates/supervisord-admin-configmap.yaml b/.internal-ci/helm/fog-ingest/templates/supervisord-admin-configmap.yaml new file mode 100644 index 0000000000..0e69d58b8a --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/supervisord-admin-configmap.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogIngest.fullname" . }}-supervisord-admin + labels: + {{- include "fogIngest.labels" . | nindent 4 }} +data: + admin_http_gw.conf: | + [program:mc-admin-http-gateway] + priority=200 + command=/usr/bin/mc-admin-http-gateway + --listen-host 0.0.0.0 + --listen-port 8000 + --admin-uri insecure-mca://127.0.0.1:8001/ + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/fog-ingest/templates/supervisord-daemon-configmap.yaml b/.internal-ci/helm/fog-ingest/templates/supervisord-daemon-configmap.yaml new file mode 100644 index 0000000000..c62709557c --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/supervisord-daemon-configmap.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogIngest.fullname" . }}-supervisord-daemon + labels: + {{- include "fogIngest.labels" . | nindent 4 }} +data: + supervisor.conf: | + [supervisord] + nodaemon=true diff --git a/.internal-ci/helm/fog-ingest/templates/supervisord-fog-ingest-configmap.yaml b/.internal-ci/helm/fog-ingest/templates/supervisord-fog-ingest-configmap.yaml new file mode 100644 index 0000000000..92d9cbd92c --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/supervisord-fog-ingest-configmap.yaml @@ -0,0 +1,30 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogIngest.fullname" . }}-supervisord-fog-ingest + labels: + {{- include "fogIngest.labels" . | nindent 4 }} +data: + ingest.conf: | + [program:fog-ingest] + priority=100 + environment=MC_SENTRY_DSN="%(ENV_FOG_INGEST_SENTRY_DSN)s" + command=/usr/bin/fog_ingest_server + --pubkey-expiry-window %(ENV_FOG_PUBKEY_EXPIRY_WINDOW)s + --peers {{ include "fogIngest.peerURLs" . }} + --local-node-id %(ENV_LOCAL_NODE_ID)s + --ias-spid %(ENV_IAS_SPID)s + --ias-api-key %(ENV_IAS_API_KEY)s + --ledger-db /fog-data/ledger + --watcher-db /fog-data/watcher + --client-listen-uri insecure-fog-ingest://0.0.0.0:3226/ + --peer-listen-uri insecure-igp://0.0.0.0:8090/ + --state-file /ingest-run-data/ingest-state-file + --admin-listen-uri insecure-mca://127.0.0.1:8001/ + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/fog-ingest/templates/supervisord-sgx-configmap.yaml b/.internal-ci/helm/fog-ingest/templates/supervisord-sgx-configmap.yaml new file mode 100644 index 0000000000..9fc45aaae0 --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/supervisord-sgx-configmap.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogIngest.fullname" . }}-supervisord-sgx + labels: + {{- include "fogIngest.labels" . | nindent 4 }} +data: + sgx.conf: | + [program:aesm-service] + priority=10 + command=/opt/intel/sgx-aesm-service/aesm/aesm_service --no-daemon + environment=AESM_PATH="/opt/intel/sgx-aesm-service/aesm",LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" + + stdout_logfile=/dev/null + stderr_logfile=/dev/null + autorestart=true \ No newline at end of file diff --git a/.internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml b/.internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml new file mode 100644 index 0000000000..ceca6aa0d3 --- /dev/null +++ b/.internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml @@ -0,0 +1,132 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "fogIngest.fullname" . }}-toolbox + labels: + {{- include "fogIngest.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + app: toolbox + {{- include "fogIngest.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: toolbox + {{- include "fogIngest.selectorLabels" . | nindent 8 }} + spec: + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 6 }} + containers: + - image: '{{ .Values.toolbox.image.org | default .Values.image.org }}/{{ .Values.toolbox.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' + imagePullPolicy: Always + name: toolbox + args: + - /bin/cat + tty: true + envFrom: + - secretRef: + name: sample-keys-seeds + optional: true + env: + - name: FOGDB_HOST + valueFrom: + configMapKeyRef: + name: fog-recovery-postgresql + key: postgresql-hostname + - name: FOGDB_USER + valueFrom: + configMapKeyRef: + name: fog-recovery-postgresql + key: postgresql-username + - name: FOGDB_PASSWORD + valueFrom: + secretKeyRef: + name: fog-recovery-postgresql + key: postgresql-password + - name: FOGDB_DATABASE + valueFrom: + configMapKeyRef: + name: fog-recovery-postgresql + key: postgresql-database + - name: FOGDB_SSL_OPTIONS + valueFrom: + configMapKeyRef: + name: fog-recovery-postgresql + key: postgresql-ssl-options + - name: DATABASE_URL + value: 'postgres://$(FOGDB_USER):$(FOGDB_PASSWORD)@$(FOGDB_HOST)/$(FOGDB_DATABASE)$(FOGDB_SSL_OPTIONS)' + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: RUST_LOG + value: error + - name: CLIENT_AUTH_TOKEN_SECRET + valueFrom: + secretKeyRef: + name: client-auth-token + key: token + optional: true + volumeMounts: + - name: minting-keys + mountPath: /minting-keys + readOnly: true + - name: wallet-seeds + mountPath: /wallet-seeds + readOnly: true + {{- if eq .Values.jaegerTracing.enabled true }} + - name: jaeger-agent + image: jaegertracing/jaeger-agent:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5775 + name: zk-compact-trft + protocol: UDP + - containerPort: 5778 + name: config-rest + protocol: TCP + - containerPort: 6831 + name: jg-compact-trft + protocol: UDP + - containerPort: 6832 + name: jg-binary-trft + protocol: UDP + - containerPort: 14271 + name: admin-http + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + args: + - --reporter.grpc.host-port={{ .Values.jaegerTracing.collector }} + - --reporter.type=grpc + - --agent.tags=cluster=undefined,container.name=fog-ingest,deployment.name={{ include "fogIngest.fullname" . }},host.ip=${HOST_IP:},pod.name=${POD_NAME:},pod.namespace=${NAMESPACE:} + {{- end }} + nodeSelector: + {{- toYaml .Values.toolbox.nodeSelector | nindent 8 }} + tolerations: + {{- toYaml .Values.toolbox.tolerations | nindent 8 }} + volumes: + - name: minting-keys + secret: + secretName: consensus-minting-secrets + optional: true + - name: wallet-seeds + secret: + secretName: sample-keys-seeds + optional: true diff --git a/.internal-ci/helm/fog-ingest/values.yaml b/.internal-ci/helm/fog-ingest/values.yaml new file mode 100644 index 0000000000..5537cb5b4b --- /dev/null +++ b/.internal-ci/helm/fog-ingest/values.yaml @@ -0,0 +1,128 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +### Chart wide values. +nameOverride: '' +fullnameOverride: '' + +imagePullSecrets: +- name: docker-credentials + +# mc-core-common-config child chart configuration. +# See ../mc-core-common-config for details. +mcCoreCommonConfig: + enabled: false + +# fog-ingest-config child chart configuration. +# See ../fog-ingest-config for details. +fogIngestConfig: + enabled: false + +# Pods share the image tag. +image: + org: mobilecoin + tag: '' # Overrides the image tag whose default is the chart appVersion. + + +### Fog Ingest Service Configuration +fogIngest: + replicaCount: 2 + image: + org: '' + name: fogingest + pullPolicy: Always + + ### Persistent storage for LMDB + persistence: + enabled: true + spec: + storageClassName: fast + accessModes: + - 'ReadWriteOnce' + resources: + requests: + storage: 512Gi + + rust: + backtrace: full + log: info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn + + podAnnotations: + fluentbit.io/include: 'true' # collect logs with fluentbit + fluentbit.io/exclude-jaeger-agent: 'true' + + ### Intel SGX extended resources are defined with: https://github.com/sebva/sgx-device-plugin + resources: + limits: + intel.com/sgx: 5000 + requests: + intel.com/sgx: 5000 + + nodeSelector: + sgx-enabled-node: 'true' + + tolerations: + - key: sgx + operator: Equal + value: 'true' + effect: NoSchedule + + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - fog-ingest + topologyKey: 'kubernetes.io/hostname' + + initContainers: + - name: sysctl + image: ubuntu:20.04 + imagePullPolicy: Always + command: + - sysctl + - -w + - net.ipv4.tcp_retries2=5 + securityContext: + privileged: true + runAsUser: 0 + runAsNonRoot: False + - name: migrate-ledger + image: "{{ .Values.fogIngest.image.org | default .Values.image.org }}/{{ .Values.fogIngest.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + command: [ '/bin/bash' ] + args: + - -c + - | + set -e + if [[ -f "/fog-data/ledger/data.mdb" ]] + then + cp /fog-data/ledger/data.mdb /fog-data/ledger/data.mdb.bak + /usr/bin/mc-ledger-migration --ledger-db /fog-data/ledger + fi + volumeMounts: + - name: fog-data + mountPath: /fog-data + +### Toolbox deployment. Used for activating and retiring. +toolbox: + image: + org: '' + name: bootstrap-tools + pullPolicy: Always + tag: '' # Overrides the image tag whose default is the chart appVersion. + + nodeSelector: + builder-node: 'false' + sgx-enabled-node: 'false' + + tolerations: [] + + affinity: {} + +jaegerTracing: + enabled: true + collector: 'dns:///jaeger-collector:14250' diff --git a/.internal-ci/helm/fog-services-config/.helmignore b/.internal-ci/helm/fog-services-config/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/.internal-ci/helm/fog-services-config/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/.internal-ci/helm/fog-services-config/Chart.yaml b/.internal-ci/helm/fog-services-config/Chart.yaml new file mode 100644 index 0000000000..cb9d5a5e41 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/Chart.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: fog-services-config +description: fog services config +type: application +version: 0.0.0 +appVersion: 0.0.0 diff --git a/.internal-ci/helm/fog-services-config/templates/NOTES.txt b/.internal-ci/helm/fog-services-config/templates/NOTES.txt new file mode 100644 index 0000000000..b17f939e82 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/NOTES.txt @@ -0,0 +1 @@ +fog-ingest config diff --git a/.internal-ci/helm/fog-services-config/templates/_helpers.tpl b/.internal-ci/helm/fog-services-config/templates/_helpers.tpl new file mode 100644 index 0000000000..dd634fb855 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/_helpers.tpl @@ -0,0 +1,121 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* Expand the name of the fogServicesConfig. */}} +{{- define "fogServicesConfig.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "fogServicesConfig.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- tpl .Values.fullnameOverride . | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "fogServicesConfig.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Common labels */}} +{{- define "fogServicesConfig.labels" -}} +helm.sh/chart: {{ include "fogServicesConfig.chart" . }} +{{ include "fogServicesConfig.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* Selector labels */}} +{{- define "fogServicesConfig.selectorLabels" -}} +app.kubernetes.io/name: {{ include "fogServicesConfig.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* pgPassword - reuse existing password */}} +{{- define "fogServicesConfig.pgPassword" -}} +{{- $pgPassword := randAlphaNum 48 }} +{{- if .Values.fogRecoveryDatabaseReader.password }} +{{- $pgPassword = .Values.fogRecoveryDatabaseReader.password }} +{{- end }} +{{- $pgSecret := (lookup "v1" "Secret" .Release.Namespace "fog-recovery-postgresql") }} +{{- if $pgSecret }} +{{- $pgPassword = index $pgSecret.data "postgres-password" | b64dec }} +{{- end }} +{{- $pgPassword }} +{{- end }} + +{{/* pgReplicationPassword - reuse existing password */}} +{{- define "fogServicesConfig.pgReplicationPassword" -}} +{{- $pgReplicationPassword := randAlphaNum 48 }} +{{- $pgSecret := (lookup "v1" "Secret" .Release.Namespace "fog-recovery-postgresql") }} +{{- if $pgSecret }} +{{- $pgReplicationPassword = index $pgSecret.data "replication-password" | b64dec }} +{{- end }} +{{- $pgReplicationPassword }} +{{- end }} + +{{/* fogViewGRPCCookieSalt - reuse existing password */}} +{{- define "fogServicesConfig.fogViewGRPCCookieSalt" -}} +{{- $salt := randAlphaNum 8 }} +{{- if .Values.fogView.grpc.cookie.salt }} +{{- $salt = .Values.fogView.grpc.cookie.salt }} +{{- end }} +{{- $saltSecret := (lookup "v1" "Secret" .Release.Namespace "fog-view-grpc-cookie") }} +{{- if $saltSecret }} +{{- $salt = index $saltSecret.data "salt" | b64dec }} +{{- end }} +{{- $salt }} +{{- end }} + +{{/* fogViewHTTPCookieSalt - reuse existing password */}} +{{- define "fogServicesConfig.fogViewHTTPCookieSalt" -}} +{{- $salt := randAlphaNum 8 }} +{{- if .Values.fogView.http.cookie.salt }} +{{- $salt = .Values.fogView.http.cookie.salt }} +{{- end }} +{{- $saltSecret := (lookup "v1" "Secret" .Release.Namespace "fog-view-http-cookie") }} +{{- if $saltSecret }} +{{- $salt = index $saltSecret.data "salt" | b64dec }} +{{- end }} +{{- $salt }} +{{- end }} + + +{{/* fogLedgerGRPCCookieSalt - reuse existing password */}} +{{- define "fogServicesConfig.fogLedgerGRPCCookieSalt" -}} +{{- $salt := randAlphaNum 8 }} +{{- if .Values.fogLedger.grpc.cookie.salt }} +{{- $salt = .Values.fogLedger.grpc.cookie.salt }} +{{- end }} +{{- $saltSecret := (lookup "v1" "Secret" .Release.Namespace "fog-ledger-grpc-cookie") }} +{{- if $saltSecret }} +{{- $salt = index $saltSecret.data "salt" | b64dec }} +{{- end }} +{{- $salt }} +{{- end }} + +{{/* fogLedgerHTTPCookieSalt - reuse existing password */}} +{{- define "fogServicesConfig.fogLedgerHTTPCookieSalt" -}} +{{- $salt := randAlphaNum 8 }} +{{- if .Values.fogLedger.http.cookie.salt }} +{{- $salt = .Values.fogLedger.http.cookie.salt }} +{{- end }} +{{- $saltSecret := (lookup "v1" "Secret" .Release.Namespace "fog-ledger-http-cookie") }} +{{- if $saltSecret }} +{{- $salt = index $saltSecret.data "salt" | b64dec }} +{{- end }} +{{- $salt }} +{{- end }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-ledger-configmap.yaml b/.internal-ci/helm/fog-services-config/templates/fog-ledger-configmap.yaml new file mode 100644 index 0000000000..9754d3bdb7 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-ledger-configmap.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +kind: ConfigMap +apiVersion: v1 +metadata: + name: fog-ledger + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +data: + {{- toYaml .Values.fogLedger.configMap | nindent 2 }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-ledger-grpc-cookie-secret.yaml b/.internal-ci/helm/fog-services-config/templates/fog-ledger-grpc-cookie-secret.yaml new file mode 100644 index 0000000000..d3557f3b87 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-ledger-grpc-cookie-secret.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: fog-ledger-grpc-cookie + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +type: Opaque +stringData: + salt: {{ include "fogServicesConfig.fogLedgerGRPCCookieSalt" . | quote }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-ledger-http-cookie-secret.yaml b/.internal-ci/helm/fog-services-config/templates/fog-ledger-http-cookie-secret.yaml new file mode 100644 index 0000000000..78adf4675a --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-ledger-http-cookie-secret.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: fog-ledger-http-cookie + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +type: Opaque +stringData: + salt: {{ include "fogServicesConfig.fogLedgerHTTPCookieSalt" . | quote }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-public-fqdn-configmap.yaml b/.internal-ci/helm/fog-services-config/templates/fog-public-fqdn-configmap.yaml new file mode 100644 index 0000000000..aeb4307446 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-public-fqdn-configmap.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +kind: ConfigMap +apiVersion: v1 +metadata: + name: fog-public-fqdn + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +data: + domainname: {{ tpl .Values.fogPublicFQDN.domainname . | quote }} + fogReportSANs: {{ tpl .Values.fogPublicFQDN.fogReportSANs . | quote }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-recovery-postgresql-secret.yaml b/.internal-ci/helm/fog-services-config/templates/fog-recovery-postgresql-secret.yaml new file mode 100644 index 0000000000..8d0146d203 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-recovery-postgresql-secret.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if .Values.fogRecoveryDatabaseReader.secret.enabled }} +{{- $pw := (include "fogServicesConfig.pgPassword" .)}} +apiVersion: v1 +kind: Secret +metadata: + name: fog-recovery-postgresql + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +type: Opaque +stringData: +# Note in live environments these values are populated by terraform. +# When we clean this up we will need to take in account other tools. +# Duplication to support postgres chart and fog configs. + postgres-password: {{ $pw | quote }} + postgresql-password: {{ $pw | quote }} + replication-password: {{ include "fogServicesConfig.pgReplicationPassword" . | quote }} +{{- end }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-recovery-reader-0-postgresql-configmap.yaml b/.internal-ci/helm/fog-services-config/templates/fog-recovery-reader-0-postgresql-configmap.yaml new file mode 100644 index 0000000000..27bf4551d8 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-recovery-reader-0-postgresql-configmap.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if .Values.fogRecoveryDatabaseReader.configMap.enabled }} +kind: ConfigMap +apiVersion: v1 +metadata: + name: fog-recovery-reader-0-postgresql + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +data: +# Note in live environments these values are populated by terraform. +# When we clean this up we will need to take in account other tools. +# Duplication to support postgres chart and fog configs. + postgres-database: {{ .Values.fogRecoveryDatabaseReader.database | quote }} + postgres-hostname: {{ .Values.fogRecoveryDatabaseReader.hostname | quote }} + postgres-port: {{ .Values.fogRecoveryDatabaseReader.port | quote }} + postgres-ssl-options: {{ .Values.fogRecoveryDatabaseReader.options | quote }} + postgres-username: {{ .Values.fogRecoveryDatabaseReader.username | quote }} + postgresql-database: {{ .Values.fogRecoveryDatabaseReader.database | quote }} + postgresql-hostname: {{ .Values.fogRecoveryDatabaseReader.hostname | quote }} + postgresql-port: {{ .Values.fogRecoveryDatabaseReader.port | quote }} + postgresql-ssl-options: {{ .Values.fogRecoveryDatabaseReader.options | quote }} + postgresql-username: {{ .Values.fogRecoveryDatabaseReader.username | quote }} +{{- end }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-report-configmap.yaml b/.internal-ci/helm/fog-services-config/templates/fog-report-configmap.yaml new file mode 100644 index 0000000000..e65295878e --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-report-configmap.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +kind: ConfigMap +apiVersion: v1 +metadata: + name: fog-report + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +data: + {{- toYaml .Values.fogReport.configMap | nindent 2 }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-report-signing-cert-secret.yaml b/.internal-ci/helm/fog-services-config/templates/fog-report-signing-cert-secret.yaml new file mode 100644 index 0000000000..46c0f7f0b8 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-report-signing-cert-secret.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: fog-report-signing-cert + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +type: kubernetes.io/tls +data: + tls.crt: {{ .Values.fogReport.signingCert.crt | b64enc }} + tls.key: {{ .Values.fogReport.signingCert.key | b64enc }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-view-configmap.yaml b/.internal-ci/helm/fog-services-config/templates/fog-view-configmap.yaml new file mode 100644 index 0000000000..133ca47a63 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-view-configmap.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +kind: ConfigMap +apiVersion: v1 +metadata: + name: fog-view + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +data: + {{- toYaml .Values.fogView.configMap | nindent 2 }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-view-grpc-cookie-secret.yaml b/.internal-ci/helm/fog-services-config/templates/fog-view-grpc-cookie-secret.yaml new file mode 100644 index 0000000000..6c2a9a6fd8 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-view-grpc-cookie-secret.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: fog-view-grpc-cookie + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +type: Opaque +stringData: + salt: {{ include "fogServicesConfig.fogViewGRPCCookieSalt" . | quote }} diff --git a/.internal-ci/helm/fog-services-config/templates/fog-view-http-cookie-secret.yaml b/.internal-ci/helm/fog-services-config/templates/fog-view-http-cookie-secret.yaml new file mode 100644 index 0000000000..cf31931250 --- /dev/null +++ b/.internal-ci/helm/fog-services-config/templates/fog-view-http-cookie-secret.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: fog-view-http-cookie + labels: + {{- include "fogServicesConfig.labels" . | nindent 4 }} +type: Opaque +stringData: + salt: {{ include "fogServicesConfig.fogViewHTTPCookieSalt" . | quote }} diff --git a/.internal-ci/helm/fog-services-config/values.yaml b/.internal-ci/helm/fog-services-config/values.yaml new file mode 100644 index 0000000000..66d89f13ca --- /dev/null +++ b/.internal-ci/helm/fog-services-config/values.yaml @@ -0,0 +1,75 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +fullnameOverride: '' + +fogRecoveryDatabaseReader: + configMap: + # Default to a TF or external created ConfigMap + enabled: false + secret: + # Default to a TF or external created Secret + enabled: false + ### helm install fog-recovery bitnami/postgresql -n \ + # --set global.postgresql.auth.existingSecret=fog-recover-postgresql \ + # --set global.postgresql.auth.database=fog_recovery \ + # --set architecture=replication + # For helm deployed postgres, set configMap.enabled and secret.enabled true + # Password will be generated if you leave this empty. + # Secret values will be reused if they already exist. + hostname: fog-recovery-postgresql-read + password: '' + username: postgres + database: fog_recovery + port: '5432' + options: '?sslmode=disable' + +fogReport: + signingCert: + key: '' + crt: '' + configMap: + # https://docs.diesel.rs/diesel/r2d2/struct.Builder.html + POSTGRES_IDLE_TIMEOUT: '60' + POSTGRES_MAX_LIFETIME: '120' + POSTGRES_CONNECTION_TIMEOUT: '5' + POSTGRES_MAX_CONNECTIONS: '3' + +fogView: + ### Cookie salts will be generated if no values are provided + # Secret values will be reused if they already exist. + grpc: + cookie: + salt: '' + http: + cookie: + salt: '' + configMap: + # https://docs.diesel.rs/diesel/r2d2/struct.Builder.html + POSTGRES_IDLE_TIMEOUT: '60' + POSTGRES_MAX_LIFETIME: '120' + POSTGRES_CONNECTION_TIMEOUT: '5' + POSTGRES_MAX_CONNECTIONS: '3' + OMAP_CAPACITY: '4194304' + +fogLedger: + ### Cookie salts will be generated if no values are provided + # Secret values will be reused if they already exist. + grpc: + cookie: + salt: '' + http: + cookie: + salt: '' + configMap: + OMAP_CAPACITY: '4194304' + +### fogPublicFQDN +# Public domain names for ingres into fog services. +fogPublicFQDN: + domainname: '' + # Since you can't put structured data in a config-map entry + # String value, list of SANs one per line + fogReportSANs: '' + # fogReportSANs: |- + # one.mc.com + # two.mc.com + diff --git a/.internal-ci/helm/fog-services/.helmignore b/.internal-ci/helm/fog-services/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/.internal-ci/helm/fog-services/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/.internal-ci/helm/fog-services/Chart.yaml b/.internal-ci/helm/fog-services/Chart.yaml new file mode 100644 index 0000000000..b69d40e674 --- /dev/null +++ b/.internal-ci/helm/fog-services/Chart.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: fog-services +description: fog services (report, view, ledger) +type: application +version: 0.0.0 +appVersion: 0.0.0 +dependencies: +- name: mc-core-common-config + repository: file://../mc-core-common-config + version: 0.0.0 + condition: mcCoreCommonConfig.enabled + alias: mcCoreCommonConfig +- name: fog-services-config + repository: file://../fog-services-config + version: 0.0.0 + condition: fogServicesConfig.enabled + alias: fogServicesConfig \ No newline at end of file diff --git a/.internal-ci/helm/fog-services/README.md b/.internal-ci/helm/fog-services/README.md new file mode 100644 index 0000000000..2d3f41f9ae --- /dev/null +++ b/.internal-ci/helm/fog-services/README.md @@ -0,0 +1,221 @@ +# fog-services Helm Chart + +Rolling upgrades for view, report and ledger fog services. + +```sh +helm upgrade fog-services ./ -i -n \ + --set image.tag=prod-1.0.1-pre2 +``` +Note: generated PersistentVolumeClaims will stick around if the Helm Chart is removed or the pods are deleted and allowed to regenerate. + +## Setup + +Configure a `values.yaml` file or pre-populate your namespace with the following ConfigMaps and Secrets. + + +- `mobilecoin-network` + + Mobilecoin network value for monitoring: mainnet, testnet, alpha... + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: mobilecoin-network + data: + network: testnet + ``` + +- `ias` + + Intel spid and primary or secondary key. + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: ias + type: Opaque + stringData: + key: + spid: + ``` + +- `sentry` + + Sentry service alert and error monitoring + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: sentry + data: + fog-ingest-sentry-dsn: + fog-view-sentry-dsn: + fog-ledger-sentry-dsn: + fog-report-sentry-dsn: + ledger-distribution-sentry-dsn: + ``` + +- `supervisord-mobilecoind` + + `mobilecoind` configuration for in container supervisord. Example values are for MobileCoin MainNet. + + `mobilecoind` needs direct connections to each node. The `--peer` url must have `?responder-id=` query string if the peer is part of a load balanced set. + + Set `--peer` and `--tx-source-url` (associated public s3 bucket https:// url) per node that you want to watch. + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: supervisord-mobilecoind + data: + mobilecoind.conf: | + [program:mobilecoind-sync] + command=/usr/bin/mobilecoind + --peer mc://node1.prod.mobilecoinww.com:443/ + --tx-source-url https://ledger.mobilecoinww.com/node1.prod.mobilecoinww.com + --peer mc://node2.prod.mobilecoinww.com:443/ + --tx-source-url https://ledger.mobilecoinww.com/node2.prod.mobilecoinww.com + --peer mc://node3.prod.mobilecoinww.com:443/ + --tx-source-url https://ledger.mobilecoinww.com/node3.prod.mobilecoinww.com + --quorum-set '{ "threshold": 3, "members": [{"args":"node1.prod.mobilecoinww.com:443","type":"Node"},{"args":"node2.prod.mobilecoinww.com:443","type":"Node"},{"args":"node3.prod.mobilecoinww.com:443","type":"Node"}] }' + --ledger-db /fog-data/ledger + --watcher-db /fog-data/watcher + --poll-interval 1 + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true + ``` + +- `fog-recovery-postgresql` ConfigMap + + If you're using an cluster external database, populate the ConfigMap and Secret with the connection values. + + These example setting work with the helm postgresql chart when launched in the local namespace. + + ```sh + helm install fog-recovery bitnami/postgresql -n \ + --set postgresqlDatabase=recovery + ``` + + ```yaml + kind: ConfigMap + apiVersion: v1 + metadata: + name: fog-recovery-postgresql + data: + postgresql-database: recovery + postgresql-hostname: fog-recovery-postgresql + postgresql-port: "5432" + postgresql-ssl-options: "?sslmode=disable" # Set as appropriate + postgresql-username: postgres + ``` + + +- `fog-recovery-postgresql` Secret + + If you're using an cluster external database, populate the ConfigMap and Secret with the connection values. + + If you're using the postgresql helm chart launched as follows, this secret will be populated for you. + + ```sh + helm install fog-recovery bitnami/postgresql -n \ + --set postgresqlDatabase=recovery + ``` + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: fog-recovery-postgresql + type: Opaque + stringData: + postgresql-password: really-good-password + ``` + +- `fog-client-auth-token` Secret + + Client auth token for Signal auth. + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: fog-client-auth-token + type: Opaque + stringData: + token: long-token-value + ``` + +- `fog-report-signing-cert` Secret + + Certificate chain and key for Fog reports + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: fog-report-signing-cert + type: kubernetes.io/tls + stringData: + tls.crt: |- + + tls.key: |- + + ``` + +- `fog-public-fqdn` ConfigMap + + FQDN for the fog ingress + + ```yaml + kind: ConfigMap + apiVersion: v1 + metadata: + name: fog-public-fqdn + data: + value: + # Since you can't put structured data in a config-map entry + # String value, list of SANs one per line + fogReportSANs: |- + some.name.com + some.other.com + ``` + +- `fog-report` ConfigMap + + Database connection configuration for fog-report + + ```yaml + kind: ConfigMap + apiVersion: v1 + metadata: + name: fog-report + data: + POSTGRES_IDLE_TIMEOUT: "60" + POSTGRES_MAX_LIFETIME: "120" + POSTGRES_CONNECTION_TIMEOUT: "5" + POSTGRES_MAX_CONNECTIONS: "3" + ``` + +- `fog-view` ConfigMap + + Database connection configuration for fog-view + + ```yaml + kind: ConfigMap + apiVersion: v1 + metadata: + name: fog-view + data: + POSTGRES_IDLE_TIMEOUT: "60" + POSTGRES_MAX_LIFETIME: "120" + POSTGRES_CONNECTION_TIMEOUT: "5" + POSTGRES_MAX_CONNECTIONS: "3" + ``` diff --git a/.internal-ci/helm/fog-services/templates/NOTES.txt b/.internal-ci/helm/fog-services/templates/NOTES.txt new file mode 100644 index 0000000000..e988a35778 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/NOTES.txt @@ -0,0 +1,20 @@ + +:::: :::: :::::::: ::::::::: ::::::::::: ::: :::::::::: ++:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: ++:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ ++#+ +:+ +#+ +#+ +:+ +#++:++#+ +#+ +#+ +#++:++# ++#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+# #+# #+# #+# #+# #+# #+# #+# #+# +### ### ######## ######### ########### ########## ########## + :::::::: :::::::: ::::::::::: :::: ::: +:+: :+: :+: :+: :+: :+:+: :+: ++:+ +:+ +:+ +:+ :+:+:+ +:+ ++#+ +#+ +:+ +#+ +#+ +:+ +#+ ++#+ +#+ +#+ +#+ +#+ +#+#+# +#+# #+# #+# #+# #+# #+# #+#+# + ######## ######## ########### ### #### + +Fog Service deployed: +- view +- report +- ledger diff --git a/.internal-ci/helm/fog-services/templates/_helpers.tpl b/.internal-ci/helm/fog-services/templates/_helpers.tpl new file mode 100644 index 0000000000..e5ecc1b4c6 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/_helpers.tpl @@ -0,0 +1,152 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* Expand the name of the fogServices. */}} +{{- define "fogServices.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "fogServices.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "fogServices.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Common labels */}} +{{- define "fogServices.labels" -}} +helm.sh/chart: {{ include "fogServices.chart" . }} +{{ include "fogServices.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* Selector labels */}} +{{- define "fogServices.selectorLabels" -}} +app.kubernetes.io/name: {{ include "fogServices.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* Fog Public FQDN */}} +{{- define "fogServices.fogPublicFQDN" -}} +{{- $domainname := "" }} +{{- if .Values.fogServicesConfig.fogPublicFQDN.domainname }} +{{- $domainname = .Values.fogServicesConfig.fogPublicFQDN.domainname }} +{{- end }} +{{- $publicFQDNConfig := lookup "v1" "ConfigMap" .Release.Namespace "fog-public-fqdn" }} +{{- if $publicFQDNConfig }} +{{- $domainname = index $publicFQDNConfig.data "domainname" }} +{{- end }} +{{- $domainname }} +{{- end }} + +{{/* FogReport Hosts (fogPublicFQDN + fogReportSANs) */}} +{{- define "fogServices.fogReportHosts" -}} +{{- $reportHosts := list }} +{{- if .Values.fogServicesConfig.fogPublicFQDN.fogReportSANs }} +{{- $reportHosts = split "\n" (.Values.fogServicesConfig.fogPublicFQDN.fogReportSANs) }} +{{- end }} +{{- $fogReportSansConfig := lookup "v1" "ConfigMap" .Release.Namespace "fog-public-fqdn" }} +{{- if $fogReportSansConfig }} +{{- $reportHosts = split "\n" (index $fogReportSansConfig.data "fogReportSANs") }} +{{- end }} +{{ include "fogServices.fogPublicFQDN" . }} +{{- range $reportHosts }} +{{ . }} +{{- end }} +{{- end }} + +{{- define "fogServices.clientAuth" -}} + {{- if eq .Values.mcCoreCommonConfig.enabled false }} + {{- (lookup "v1" "Secret" .Release.Namespace "client-auth-token").data.token | default "" | b64dec }} + {{- else }} + {{- .Values.mcCoreCommonConfig.clientAuth.token | default ""}} + {{- end }} +{{- end }} + +{{/* Mobilecoin Network monitoring labels */}} +{{- define "fogServices.mobileCoinNetwork.network" -}} + {{- if eq .Values.mcCoreCommonConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace "mobilecoin-network").data.network | default "" }} + {{- else }} + {{- tpl .Values.mcCoreCommonConfig.mobileCoinNetwork.network . }} + {{- end }} +{{- end }} + +{{- define "fogServices.mobileCoinNetwork.partner" -}} + {{- if eq .Values.mcCoreCommonConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace "mobilecoin-network").data.partner | default "" }} + {{- else }} + {{- tpl .Values.mcCoreCommonConfig.mobileCoinNetwork.partner . }} + {{- end }} +{{- end }} + +{{/* fogViewGRPCCookieSalt - reuse existing password */}} +{{- define "fogServices.fogViewGRPCCookieSalt" -}} +{{- $salt := randAlphaNum 8 }} +{{- if .Values.fogServicesConfig.fogView.grpc.cookie.salt }} +{{- $salt = .Values.fogServicesConfig.fogView.grpc.cookie.salt }} +{{- end }} +{{- $saltSecret := (lookup "v1" "Secret" .Release.Namespace "fog-view-grpc-cookie") }} +{{- if $saltSecret }} +{{- $salt = index $saltSecret.data "salt" | b64dec }} +{{- end }} +{{- $salt }} +{{- end }} + +{{/* fogViewHTTPCookieSalt - reuse existing password */}} +{{- define "fogServices.fogViewHTTPCookieSalt" -}} +{{- $salt := randAlphaNum 8 }} +{{- if .Values.fogServicesConfig.fogView.http.cookie.salt }} +{{- $salt = .Values.fogServicesConfig.fogView.http.cookie.salt }} +{{- end }} +{{- $saltSecret := (lookup "v1" "Secret" .Release.Namespace "fog-view-http-cookie") }} +{{- if $saltSecret }} +{{- $salt = index $saltSecret.data "salt" | b64dec }} +{{- end }} +{{- $salt }} +{{- end }} + + +{{/* fogLedgerGRPCCookieSalt - reuse existing password */}} +{{- define "fogServices.fogLedgerGRPCCookieSalt" -}} +{{- $salt := randAlphaNum 8 }} +{{- if .Values.fogServicesConfig.fogLedger.grpc.cookie.salt }} +{{- $salt = .Values.fogServicesConfig.fogLedger.grpc.cookie.salt }} +{{- end }} +{{- $saltSecret := (lookup "v1" "Secret" .Release.Namespace "fog-ledger-grpc-cookie") }} +{{- if $saltSecret }} +{{- $salt = index $saltSecret.data "salt" | b64dec }} +{{- end }} +{{- $salt }} +{{- end }} + +{{/* fogLedgerHTTPCookieSalt - reuse existing password */}} +{{- define "fogServices.fogLedgerHTTPCookieSalt" -}} +{{- $salt := randAlphaNum 8 }} +{{- if .Values.fogServicesConfig.fogLedger.http.cookie.salt }} +{{- $salt = .Values.fogServicesConfig.fogLedger.http.cookie.salt }} +{{- end }} +{{- $saltSecret := (lookup "v1" "Secret" .Release.Namespace "fog-ledger-http-cookie") }} +{{- if $saltSecret }} +{{- $salt = index $saltSecret.data "salt" | b64dec }} +{{- end }} +{{- $salt }} +{{- end }} diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-grpc-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-grpc-ingress.yaml new file mode 100644 index 0000000000..487881b8a5 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-grpc-ingress.yaml @@ -0,0 +1,47 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "fogServices.fullname" . }}-fog-ledger-grpc + labels: + app: fog-ledger + {{- include "fogServices.labels" . | nindent 4 }} + annotations: + {{ toYaml (tpl .Values.fogLedger.ingress.grpc.annotations . | fromYaml)| nindent 4 }} +spec: + tls: + - hosts: + - {{ include "fogServices.fogPublicFQDN" . }} + secretName: {{ include "fogServices.fogPublicFQDN" . }}-fog-tls + rules: + - host: {{ include "fogServices.fogPublicFQDN" . }} + http: + paths: + - path: /fog_ledger.FogBlockAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-ledger + port: + number: 3228 + - path: /fog_ledger.FogKeyImageAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-ledger + port: + number: 3228 + - path: /fog_ledger.FogMerkleProofAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-ledger + port: + number: 3228 + - path: /fog_ledger.FogUntrustedTxOutApi + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-ledger + port: + number: 3228 diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-http-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-http-ingress.yaml new file mode 100644 index 0000000000..6f740b62f9 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-http-ingress.yaml @@ -0,0 +1,47 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "fogServices.fullname" . }}-fog-ledger-http + labels: + app: fog-ledger + {{- include "fogServices.labels" . | nindent 4 }} + annotations: + {{ toYaml (tpl .Values.fogLedger.ingress.http.annotations . | fromYaml)| nindent 4 }} +spec: + tls: + - hosts: + - {{ include "fogServices.fogPublicFQDN" . }} + secretName: {{ include "fogServices.fogPublicFQDN" . }}-fog-tls + rules: + - host: {{ include "fogServices.fogPublicFQDN" . }} + http: + paths: + - path: /gw/fog_ledger.FogBlockAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-ledger + port: + number: 8228 + - path: /gw/fog_ledger.FogKeyImageAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-ledger + port: + number: 8228 + - path: /gw/fog_ledger.FogMerkleProofAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-ledger + port: + number: 8228 + - path: /gw/fog_ledger.FogUntrustedTxOutApi + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-ledger + port: + number: 8228 diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-service.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-service.yaml new file mode 100644 index 0000000000..8bf92b4ab3 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-service.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "fogServices.fullname" . }}-fog-ledger + labels: + app: fog-ledger + {{- include "fogServices.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: fog-ledger + {{- include "fogServices.selectorLabels" . | nindent 4 }} + ports: + - name: ledger + port: 3228 + targetPort: ledger + - name: mgmt + port: 8000 + targetPort: mgmt + - name: ledger-http + port: 8228 + targetPort: ledger-http diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-servicmonitor.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-servicmonitor.yaml new file mode 100644 index 0000000000..433188c2db --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-servicmonitor.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "fogServices.fullname" . }}-fog-ledger + labels: + publish: grafana-cloud + app: fog-ledger + {{- include "fogServices.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: fog-ledger + {{- include "fogServices.selectorLabels" . | nindent 6 }} + endpoints: + - port: mgmt + relabelings: + - targetLabel: network + replacement: {{ include "fogServices.mobileCoinNetwork.network" . }} + - targetLabel: partner + replacement: {{ include "fogServices.mobileCoinNetwork.partner" . }} diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml new file mode 100644 index 0000000000..fec0a5f8de --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml @@ -0,0 +1,189 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "fogServices.fullname" . }}-fog-ledger + labels: + {{- include "fogServices.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.fogLedger.replicaCount }} + selector: + matchLabels: + app: fog-ledger + {{- include "fogServices.selectorLabels" . | nindent 6 }} + serviceName: {{ include "fogServices.fullname" . }}-fog-ledger + template: + metadata: + annotations: + {{- toYaml .Values.fogLedger.podAnnotations | nindent 8 }} + labels: + app: fog-ledger + {{- include "fogServices.labels" . | nindent 8 }} + spec: + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 6 }} + terminationGracePeriodSeconds: 30 + dnsConfig: + options: + - name: ndots + value: "1" + initContainers: + {{- tpl (toYaml .Values.fogLedger.initContainers) . | nindent 6 }} + containers: + - name: fog-ledger + image: "{{ .Values.fogLedger.image.org | default .Values.image.org }}/{{ .Values.fogLedger.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.fogLedger.image.pullPolicy }} + command: [ "/usr/bin/supervisord" ] + ports: + - name: ledger + containerPort: 3228 + - name: mgmt + containerPort: 8000 + envFrom: + - secretRef: + name: ias + - configMapRef: + name: fog-ledger + - secretRef: + name: ipinfo + optional: true + env: + - name: RUST_BACKTRACE + value: {{ .Values.fogLedger.rust.backtrace | quote }} + - name: RUST_LOG + value: {{ .Values.fogLedger.rust.log | quote }} + - name: FOG_LEDGER_SENTRY_DSN + valueFrom: + configMapKeyRef: + name: sentry + key: fog-ledger-sentry-dsn + # Maps to Sentry Environment + - name: MC_BRANCH + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: CLIENT_AUTH_TOKEN_SECRET + valueFrom: + secretKeyRef: + name: client-auth-token + key: token + optional: true + - name: CLIENT_RESPONDER_ID + value: "{{ include "fogServices.fogPublicFQDN" . }}:443" + # Hold liveness and readiness until this probe passes. + startupProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3228" + failureThreshold: 30 + periodSeconds: 10 + # Will wait for startup probe to succeed. When this passes k8s won't kill the service. + livenessProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3228" + failureThreshold: 5 + periodSeconds: 30 + # Will wait for startup probe to succeed. When this passes services/ingress will pass traffic + readinessProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3228" + failureThreshold: 2 + periodSeconds: 10 + volumeMounts: + - name: aesm-socket-dir + mountPath: /var/run/aesmd + - name: fog-data + mountPath: /fog-data + - name: supervisor-conf + mountPath: /etc/supervisor/conf.d + readOnly: true + resources: + {{- toYaml .Values.fogLedger.resources | nindent 10 }} + - name: grpc-gateway + image: "{{ .Values.grpcGateway.image.org | default .Values.image.org }}/{{ .Values.grpcGateway.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + command: + - /usr/bin/go-grpc-gateway + - -grpc-server-endpoint=127.0.0.1:3228 + - -grpc-insecure + - -http-server-listen=:8228 + - -logtostderr + ports: + - name: ledger-http + containerPort: 8228 + resources: + {{- toYaml .Values.grpcGateway.resources | nindent 10 }} +{{- if eq .Values.jaegerTracing.enabled true }} + - name: jaeger-agent + image: jaegertracing/jaeger-agent:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5775 + name: zk-compact-trft + protocol: UDP + - containerPort: 5778 + name: config-rest + protocol: TCP + - containerPort: 6831 + name: jg-compact-trft + protocol: UDP + - containerPort: 6832 + name: jg-binary-trft + protocol: UDP + - containerPort: 14271 + name: admin-http + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + args: + - --reporter.grpc.host-port={{ .Values.jaegerTracing.collector }} + - --reporter.type=grpc + - --agent.tags=cluster=undefined,container.name=fog-ledger,deployment.name={{ include "fogServices.fullname" . }},host.ip=${HOST_IP:},pod.name=${POD_NAME:},pod.namespace={{ .Release.Namespace }} +{{- end }} + nodeSelector: + {{- toYaml .Values.fogLedger.nodeSelector | nindent 8 }} + tolerations: + {{- toYaml .Values.fogLedger.tolerations | nindent 8 }} + affinity: + {{- toYaml .Values.fogLedger.affinity | nindent 8 }} + volumes: + {{- if eq .Values.fogLedger.persistence.enabled false }} + - name: fog-data + emptyDir: {} + {{- end }} + - name: aesm-socket-dir + emptyDir: {} + - name: supervisor-conf + projected: + sources: + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-sgx + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-daemon + - configMap: + name: fog-supervisord-mobilecoind + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-fog-ledger + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-admin + {{- if .Values.fogLedger.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: fog-data + spec: + {{- toYaml .Values.fogLedger.persistence.spec | nindent 6 }} + {{- end }} diff --git a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml new file mode 100644 index 0000000000..f5c6c908db --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml @@ -0,0 +1,192 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "fogServices.fullname" . }}-fog-report + labels: + app: fog-report + {{- include "fogServices.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.fogReport.replicaCount }} + selector: + matchLabels: + app: fog-report + {{- include "fogServices.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- toYaml .Values.fogReport.podAnnotations | nindent 8 }} + labels: + app: fog-report + {{- include "fogServices.labels" . | nindent 8 }} + spec: + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 8 }} + initContainers: + - name: sysctl + image: ubuntu:20.04 + command: + - sysctl + - -w + - net.ipv4.tcp_retries2=5 + - net.core.somaxconn=65535 + securityContext: + privileged: true + runAsUser: 0 + runAsNonRoot: False + containers: + - name: fog-report + image: "{{ .Values.fogReport.image.org | default .Values.image.org }}/{{ .Values.fogReport.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + command: [ "/usr/bin/supervisord" ] + ports: + - name: report + containerPort: 3222 + - name: mgmt + containerPort: 8000 + envFrom: + - configMapRef: + name: fog-report + env: + - name: "RUST_BACKTRACE" + value: {{ .Values.fogReport.rust.backtrace | quote }} + - name: "RUST_LOG" + value: {{ .Values.fogReport.rust.log | quote }} + - name: "FOG_REPORT_SENTRY_DSN" + valueFrom: + configMapKeyRef: + name: sentry + key: fog-report-sentry-dsn + # Maps to Sentry Environment + - name: MC_BRANCH + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: FOGDB_HOST + valueFrom: + configMapKeyRef: + name: fog-recovery-reader-0-postgresql + key: postgresql-hostname + - name: FOGDB_USER + valueFrom: + configMapKeyRef: + name: fog-recovery-reader-0-postgresql + key: postgresql-username + - name: FOGDB_PASSWORD + valueFrom: + secretKeyRef: + name: fog-recovery-postgresql + key: postgresql-password + - name: FOGDB_DATABASE + valueFrom: + configMapKeyRef: + name: fog-recovery-reader-0-postgresql + key: postgresql-database + - name: FOGDB_SSL_OPTIONS + valueFrom: + configMapKeyRef: + name: fog-recovery-reader-0-postgresql + key: postgresql-ssl-options + - name: DATABASE_URL + value: "postgres://$(FOGDB_USER):$(FOGDB_PASSWORD)@$(FOGDB_HOST)/$(FOGDB_DATABASE)$(FOGDB_SSL_OPTIONS)" + # Hold liveness and readiness until this probe passes. + startupProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3222" + failureThreshold: 30 + periodSeconds: 10 + # Will wait for startup probe to succeed. When this passes k8s won't kill the service. + livenessProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3222" + failureThreshold: 5 + periodSeconds: 30 + # Will wait for startup probe to succeed. When this passes services/ingress will pass traffic + readinessProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3222" + failureThreshold: 2 + periodSeconds: 10 + volumeMounts: + - name: supervisor-conf + mountPath: /etc/supervisor/conf.d + readOnly: true + - name: signing-cert + mountPath: /certs + readOnly: true + resources: + {{- toYaml .Values.fogReport.resources | nindent 10 }} + - name: grpc-gateway + image: "{{ .Values.grpcGateway.image.org | default .Values.image.org }}/{{ .Values.grpcGateway.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + command: + - /usr/bin/go-grpc-gateway + - -grpc-server-endpoint=127.0.0.1:3228 + - -grpc-insecure + - -http-server-listen=:8222 + - -logtostderr + ports: + - name: report-http + containerPort: 8222 + resources: + {{- toYaml .Values.grpcGateway.resources | nindent 10 }} +{{- if eq .Values.jaegerTracing.enabled true }} + - name: jaeger-agent + image: jaegertracing/jaeger-agent:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5775 + name: zk-compact-trft + protocol: UDP + - containerPort: 5778 + name: config-rest + protocol: TCP + - containerPort: 6831 + name: jg-compact-trft + protocol: UDP + - containerPort: 6832 + name: jg-binary-trft + protocol: UDP + - containerPort: 14271 + name: admin-http + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + args: + - --reporter.grpc.host-port={{ .Values.jaegerTracing.collector }} + - --reporter.type=grpc + - --agent.tags=cluster=undefined,container.name=fog-report,deployment.name={{ include "fogServices.fullname" . }},host.ip=${HOST_IP:},pod.name=${POD_NAME:},pod.namespace={{ .Release.Namespace }} +{{- end }} + nodeSelector: + {{- toYaml .Values.fogReport.nodeSelector | nindent 8 }} + tolerations: + {{- toYaml .Values.fogReport.tolerations | nindent 8 }} + affinity: + {{- toYaml .Values.fogReport.affinity | nindent 8 }} + volumes: + - name: signing-cert + secret: + secretName: fog-report-signing-cert + - name: supervisor-conf + projected: + sources: + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-daemon + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-fog-report + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-admin diff --git a/.internal-ci/helm/fog-services/templates/fog-report-grpc-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-report-grpc-ingress.yaml new file mode 100644 index 0000000000..8fdf3b58de --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-report-grpc-ingress.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# Adding a separate ingress for each host so we don't stomp on existing certs. +{{- $hosts := split "\n" (include "fogServices.fogReportHosts" . | trim) }} +{{- range $hosts }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "fogServices.fullname" $ }}-fog-report-grpc-{{ . }} + labels: + app: fog-report + {{- include "fogServices.labels" $ | nindent 4 }} + annotations: + {{- toYaml $.Values.fogReport.ingress.grpc.annotations | nindent 4 }} +spec: + tls: + - hosts: + - {{ . }} + secretName: {{ . }}-fog-tls + rules: + - host: {{ . }} + http: + paths: + - path: /report.ReportAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" $ }}-fog-report + port: + number: 3222 +--- +{{- end }} diff --git a/.internal-ci/helm/fog-services/templates/fog-report-http-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-report-http-ingress.yaml new file mode 100644 index 0000000000..07daa248db --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-report-http-ingress.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# Adding a separate ingress for each host so we don't stomp on existing certs. +{{- $hosts := split "\n" (include "fogServices.fogReportHosts" . | trim) }} +{{- range $hosts }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "fogServices.fullname" $ }}-fog-report-http-{{ . }} + labels: + app: fog-report + {{- include "fogServices.labels" $ | nindent 4 }} + annotations: + {{- toYaml $.Values.fogReport.ingress.http.annotations | nindent 4 }} +spec: + tls: + - hosts: + - {{ . }} + secretName: {{ . }}-fog-tls + rules: + - host: {{ . }} + http: + paths: + - path: /gw/report.ReportAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" $ }}-fog-report + port: + number: 8222 +--- +{{- end }} diff --git a/.internal-ci/helm/fog-services/templates/fog-report-service.yaml b/.internal-ci/helm/fog-services/templates/fog-report-service.yaml new file mode 100644 index 0000000000..7cf31faae1 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-report-service.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "fogServices.fullname" . }}-fog-report + labels: + app: fog-report + {{- include "fogServices.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: fog-report + {{- include "fogServices.selectorLabels" . | nindent 4 }} + ports: + - name: report + port: 3222 + targetPort: report + - name: mgmt + port: 8000 + targetPort: mgmt + - name: report-http + port: 8222 + targetPort: report-http diff --git a/.internal-ci/helm/fog-services/templates/fog-report-servicmonitor.yaml b/.internal-ci/helm/fog-services/templates/fog-report-servicmonitor.yaml new file mode 100644 index 0000000000..8c14917a34 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-report-servicmonitor.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "fogServices.fullname" . }}-fog-report + labels: + publish: grafana-cloud + app: fog-report + {{- include "fogServices.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: fog-report + {{- include "fogServices.selectorLabels" . | nindent 6 }} + endpoints: + - port: mgmt + relabelings: + - targetLabel: network + replacement: {{ include "fogServices.mobileCoinNetwork.network" . }} + - targetLabel: partner + replacement: {{ include "fogServices.mobileCoinNetwork.partner" . }} \ No newline at end of file diff --git a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml new file mode 100644 index 0000000000..52d8f590f7 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml @@ -0,0 +1,204 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "fogServices.fullname" . }}-fog-view + labels: + app: fog-view + {{- include "fogServices.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.fogView.replicaCount }} + selector: + matchLabels: + app: fog-view + {{- include "fogServices.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- toYaml .Values.fogView.podAnnotations | nindent 8 }} + labels: + app: fog-view + {{- include "fogServices.labels" . | nindent 8 }} + spec: + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 6 }} + initContainers: + - name: sysctl + image: ubuntu:20.04 + command: + - sysctl + - -w + - net.ipv4.tcp_retries2=5 + - net.core.somaxconn=65535 + securityContext: + privileged: true + runAsUser: 0 + runAsNonRoot: False + containers: + - name: fog-view + image: "{{ .Values.fogView.image.org | default .Values.image.org }}/{{ .Values.fogView.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.fogView.image.pullPolicy }} + command: [ "/usr/bin/supervisord" ] + ports: + - name: view + containerPort: 3225 + - name: mgmt + containerPort: 8000 + envFrom: + - configMapRef: + name: fog-view + - secretRef: + name: ias + env: + - name: RUST_BACKTRACE + value: {{ .Values.fogView.rust.backtrace | quote }} + - name: RUST_LOG + value: {{ .Values.fogView.rust.log | quote }} + - name: CLIENT_RESPONDER_ID + value: "{{ include "fogServices.fogPublicFQDN" . }}:443" + - name: FOG_VIEW_SENTRY_DSN + valueFrom: + configMapKeyRef: + name: sentry + key: fog-view-sentry-dsn + # Maps to Sentry Environment + - name: MC_BRANCH + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: FOGDB_HOST + valueFrom: + configMapKeyRef: + name: fog-recovery-reader-0-postgresql + key: postgresql-hostname + - name: FOGDB_USER + valueFrom: + configMapKeyRef: + name: fog-recovery-reader-0-postgresql + key: postgresql-username + - name: FOGDB_PASSWORD + valueFrom: + secretKeyRef: + name: fog-recovery-postgresql + key: postgresql-password + - name: FOGDB_DATABASE + valueFrom: + configMapKeyRef: + name: fog-recovery-reader-0-postgresql + key: postgresql-database + - name: FOGDB_SSL_OPTIONS + valueFrom: + configMapKeyRef: + name: fog-recovery-reader-0-postgresql + key: postgresql-ssl-options + - name: DATABASE_URL + value: "postgres://$(FOGDB_USER):$(FOGDB_PASSWORD)@$(FOGDB_HOST)/$(FOGDB_DATABASE)$(FOGDB_SSL_OPTIONS)" + - name: CLIENT_AUTH_TOKEN_SECRET + valueFrom: + secretKeyRef: + name: client-auth-token + key: token + optional: true + # Hold liveness and readiness until this probe passes. + startupProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3225" + failureThreshold: 120 + periodSeconds: 60 + initialDelaySeconds: 60 + # Will wait for startup probe to succeed. When this passes k8s won't kill the service. + livenessProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3225" + failureThreshold: 5 + periodSeconds: 30 + # Will wait for startup probe to succeed. When this passes services/ingress will pass traffic + readinessProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3225" + failureThreshold: 2 + periodSeconds: 10 + volumeMounts: + - name: aesm-socket-dir + mountPath: /var/run/aesmd + - name: supervisor-conf + mountPath: /etc/supervisor/conf.d + readOnly: true + resources: + {{- toYaml .Values.fogView.resources | nindent 10 }} + - name: grpc-gateway + image: "{{ .Values.grpcGateway.image.org | default .Values.image.org }}/{{ .Values.grpcGateway.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + command: + - /usr/bin/go-grpc-gateway + - -grpc-server-endpoint=127.0.0.1:3228 + - -grpc-insecure + - -http-server-listen=:8225 + - -logtostderr + ports: + - name: view-http + containerPort: 8225 + resources: + {{- toYaml .Values.grpcGateway.resources | nindent 10 }} +{{- if eq .Values.jaegerTracing.enabled true }} + - name: jaeger-agent + image: jaegertracing/jaeger-agent:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5775 + name: zk-compact-trft + protocol: UDP + - containerPort: 5778 + name: config-rest + protocol: TCP + - containerPort: 6831 + name: jg-compact-trft + protocol: UDP + - containerPort: 6832 + name: jg-binary-trft + protocol: UDP + - containerPort: 14271 + name: admin-http + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + args: + - --reporter.grpc.host-port={{ .Values.jaegerTracing.collector }} + - --reporter.type=grpc + - --agent.tags=cluster=undefined,container.name=fog-view,deployment.name={{ include "fogServices.fullname" . }},host.ip=${HOST_IP:},pod.name=${POD_NAME:},pod.namespace={{ .Release.Namespace }} +{{- end }} + nodeSelector: + {{- toYaml .Values.fogView.nodeSelector | nindent 8 }} + tolerations: + {{- toYaml .Values.fogView.tolerations | nindent 8 }} + affinity: + {{- toYaml .Values.fogView.affinity | nindent 8 }} + volumes: + - name: aesm-socket-dir + emptyDir: {} + - name: supervisor-conf + projected: + sources: + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-sgx + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-daemon + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-fog-view + - configMap: + name: {{ include "fogServices.fullname" . }}-supervisord-admin diff --git a/.internal-ci/helm/fog-services/templates/fog-view-grpc-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-view-grpc-ingress.yaml new file mode 100644 index 0000000000..445bfb4165 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-view-grpc-ingress.yaml @@ -0,0 +1,26 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "fogServices.fullname" . }}-fog-view-grpc + labels: + app: fog-view + {{- include "fogServices.labels" . | nindent 4 }} + annotations: + {{ toYaml (tpl .Values.fogView.ingress.grpc.annotations . | fromYaml)| nindent 4 }} +spec: + tls: + - hosts: + - {{ include "fogServices.fogPublicFQDN" . }} + secretName: {{ include "fogServices.fogPublicFQDN" . }}-fog-tls + rules: + - host: {{ include "fogServices.fogPublicFQDN" . }} + http: + paths: + - path: /fog_view.FogViewAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-view + port: + number: 3225 diff --git a/.internal-ci/helm/fog-services/templates/fog-view-http-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-view-http-ingress.yaml new file mode 100644 index 0000000000..eecce0ca5b --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-view-http-ingress.yaml @@ -0,0 +1,26 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "fogServices.fullname" . }}-fog-view-http + labels: + app: fog-view + {{- include "fogServices.labels" . | nindent 4 }} + annotations: + {{ toYaml (tpl .Values.fogView.ingress.http.annotations . | fromYaml)| nindent 4 }} +spec: + tls: + - hosts: + - {{ include "fogServices.fogPublicFQDN" . }} + secretName: {{ include "fogServices.fogPublicFQDN" . }}-fog-tls + rules: + - host: {{ include "fogServices.fogPublicFQDN" . }} + http: + paths: + - path: /gw/fog_view.FogViewAPI + pathType: Prefix + backend: + service: + name: {{ include "fogServices.fullname" . }}-fog-view + port: + number: 8225 diff --git a/.internal-ci/helm/fog-services/templates/fog-view-service.yaml b/.internal-ci/helm/fog-services/templates/fog-view-service.yaml new file mode 100644 index 0000000000..248aab865b --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-view-service.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "fogServices.fullname" . }}-fog-view + labels: + app: fog-view + {{- include "fogServices.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: fog-view + {{- include "fogServices.selectorLabels" . | nindent 4 }} + ports: + - name: view + port: 3225 + targetPort: view + - name: mgmt + port: 8000 + targetPort: mgmt + - name: view-http + port: 8225 + targetPort: view-http diff --git a/.internal-ci/helm/fog-services/templates/fog-view-servicmonitor.yaml b/.internal-ci/helm/fog-services/templates/fog-view-servicmonitor.yaml new file mode 100644 index 0000000000..e8c9cb47df --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/fog-view-servicmonitor.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "fogServices.fullname" . }}-fog-view + labels: + publish: grafana-cloud + app: fog-view + {{- include "fogServices.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: fog-view + {{- include "fogServices.selectorLabels" . | nindent 6 }} + endpoints: + - port: mgmt + relabelings: + - targetLabel: network + replacement: {{ include "fogServices.mobileCoinNetwork.network" . }} + - targetLabel: partner + replacement: {{ include "fogServices.mobileCoinNetwork.partner" . }} + diff --git a/.internal-ci/helm/fog-services/templates/supervisord-admin-configmap.yaml b/.internal-ci/helm/fog-services/templates/supervisord-admin-configmap.yaml new file mode 100644 index 0000000000..74588389a6 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/supervisord-admin-configmap.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogServices.fullname" . }}-supervisord-admin + labels: + {{- include "fogServices.labels" . | nindent 4 }} +data: + admin_http_gw.conf: | + [program:mc-admin-http-gateway] + priority=200 + command=/usr/bin/mc-admin-http-gateway + --listen-host 0.0.0.0 + --listen-port 8000 + --admin-uri insecure-mca://127.0.0.1:8001/ + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/fog-services/templates/supervisord-daemon-configmap.yaml b/.internal-ci/helm/fog-services/templates/supervisord-daemon-configmap.yaml new file mode 100644 index 0000000000..0aac15055e --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/supervisord-daemon-configmap.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogServices.fullname" . }}-supervisord-daemon + labels: + {{- include "fogServices.labels" . | nindent 4 }} +data: + supervisor.conf: | + [supervisord] + nodaemon=true diff --git a/.internal-ci/helm/fog-services/templates/supervisord-fog-ledger-configmap.yaml b/.internal-ci/helm/fog-services/templates/supervisord-fog-ledger-configmap.yaml new file mode 100644 index 0000000000..24e8623966 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/supervisord-fog-ledger-configmap.yaml @@ -0,0 +1,30 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogServices.fullname" . }}-supervisord-fog-ledger + labels: + {{- include "fogServices.labels" . | nindent 4 }} +data: + acct_view.conf: | + [program:fog-ledger] + priority=100 + environment=MC_SENTRY_DSN="%(ENV_FOG_LEDGER_SENTRY_DSN)s" + command=/usr/bin/ledger_server + --ledger-db /fog-data/ledger + --watcher-db /fog-data/watcher + --client-responder-id "%(ENV_CLIENT_RESPONDER_ID)s" + --client-listen-uri insecure-fog-ledger://0.0.0.0:3228/ +{{- if (include "fogServices.clientAuth" .) }} + --client-auth-token-secret "%(ENV_CLIENT_AUTH_TOKEN_SECRET)s" + --client-auth-token-max-lifetime 31536000 +{{- end }} + --ias-spid %(ENV_IAS_SPID)s + --ias-api-key %(ENV_IAS_API_KEY)s + --admin-listen-uri insecure-mca://127.0.0.1:8001/ + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/fog-services/templates/supervisord-fog-report-configmap.yaml b/.internal-ci/helm/fog-services/templates/supervisord-fog-report-configmap.yaml new file mode 100644 index 0000000000..6660bc8cb9 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/supervisord-fog-report-configmap.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogServices.fullname" . }}-supervisord-fog-report + labels: + {{- include "fogServices.labels" . | nindent 4 }} +data: + report.conf: | + [program:fog-report] + priority=100 + environment=MC_SENTRY_DSN="%(ENV_FOG_REPORT_SENTRY_DSN)s" + command=/usr/bin/report_server + --client-listen-uri insecure-fog://0.0.0.0:3222/ + --admin-listen-uri insecure-mca://127.0.0.1:8001/ + --signing-chain /certs/tls.crt + --signing-key /certs/tls.key + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/fog-services/templates/supervisord-fog-view-configmap.yaml b/.internal-ci/helm/fog-services/templates/supervisord-fog-view-configmap.yaml new file mode 100644 index 0000000000..b9b87a0fe5 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/supervisord-fog-view-configmap.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogServices.fullname" . }}-supervisord-fog-view + labels: + {{- include "fogServices.labels" . | nindent 4 }} +data: + acct_view.conf: | + [program:fogview] + priority=100 + environment=MC_SENTRY_DSN="%(ENV_FOG_VIEW_SENTRY_DSN)s" + command=/usr/bin/fog_view_server + --client-listen-uri insecure-fog-view://0.0.0.0:3225/ + --client-responder-id "%(ENV_CLIENT_RESPONDER_ID)s" +{{- if (include "fogServices.clientAuth" .) }} + --client-auth-token-secret "%(ENV_CLIENT_AUTH_TOKEN_SECRET)s" + --client-auth-token-max-lifetime 31536000 +{{- end }} + --ias-spid %(ENV_IAS_SPID)s + --ias-api-key %(ENV_IAS_API_KEY)s + --admin-listen-uri insecure-mca://127.0.0.1:8001/ + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/fog-services/templates/supervisord-sgx-configmap.yaml b/.internal-ci/helm/fog-services/templates/supervisord-sgx-configmap.yaml new file mode 100644 index 0000000000..c80c9efc44 --- /dev/null +++ b/.internal-ci/helm/fog-services/templates/supervisord-sgx-configmap.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fogServices.fullname" . }}-supervisord-sgx + labels: + {{- include "fogServices.labels" . | nindent 4 }} +data: + sgx.conf: | + [program:aesm-service] + priority=10 + command=/opt/intel/sgx-aesm-service/aesm/aesm_service --no-daemon + environment=AESM_PATH="/opt/intel/sgx-aesm-service/aesm",LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" + + stdout_logfile=/dev/null + stderr_logfile=/dev/null + autorestart=true \ No newline at end of file diff --git a/.internal-ci/helm/fog-services/values.yaml b/.internal-ci/helm/fog-services/values.yaml new file mode 100644 index 0000000000..d147b547fd --- /dev/null +++ b/.internal-ci/helm/fog-services/values.yaml @@ -0,0 +1,249 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +### Chart wide values. +nameOverride: '' +fullnameOverride: '' + +### mc-core-common-config child chart configuration. +# See ../mc-core-common-config for details. +mcCoreCommonConfig: + enabled: false + +### fog-services-config child chart configuration +# See ../fog-services-config for details. +fogServicesConfig: + enabled: false + +imagePullSecrets: +- name: docker-credentials + +# Pods share the image tag. +image: + org: mobilecoin + tag: '' # Overrides the image tag whose default is the chart appVersion. + +### Fog Report Service +fogReport: + replicaCount: 2 + image: + org: '' + name: fogreport + pullPolicy: Always + + rust: + backtrace: full + log: info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn + + signingCert: + secret: + external: true + name: fog-report-signing-cert + crt: '' + key: '' + ingress: + grpc: + annotations: + cert-manager.io/cluster-issuer: letsencrypt-production-http + haproxy.org/server-proto: "h2" # Force GRPC/H2 mode + haproxy.org/server-ssl: "false" # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: "true" + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + + http: + annotations: + cert-manager.io/cluster-issuer: letsencrypt-production-http + haproxy.org/server-ssl: "false" # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: "true" + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + haproxy.org/path-rewrite: '/gw/(.*) /\1' # Strip the /gw prefix + + podAnnotations: + fluentbit.io/include: 'true' # collect logs with fluentbit + fluentbit.io/exclude-jaeger-agent: 'true' + + nodeSelector: + builder-node: 'false' + sgx-enabled-node: 'false' + + affinity: {} + tolerations: [] + resources: {} + + configMap: + external: true + name: fog-report + data: + # https://docs.diesel.rs/diesel/r2d2/struct.Builder.html + POSTGRES_IDLE_TIMEOUT: '60' + POSTGRES_MAX_LIFETIME: '120' + POSTGRES_CONNECTION_TIMEOUT: '5' + POSTGRES_MAX_CONNECTIONS: '3' + +fogView: + replicaCount: 2 + image: + org: '' + name: fogview + pullPolicy: Always + + rust: + backtrace: full + log: info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn + + ingress: + grpc: + annotations: |- + cert-manager.io/cluster-issuer: letsencrypt-production-http + haproxy.org/server-proto: "h2" # Force GRPC/H2 mode + haproxy.org/server-ssl: "false" # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: "true" + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + dynamic-cookie-key {{ include "fogServices.fogViewGRPCCookieSalt" . }} + cookie VIEW insert indirect nocache dynamic + http: + annotations: |- + cert-manager.io/cluster-issuer: letsencrypt-production-http + haproxy.org/server-ssl: "false" # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: "true" + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + dynamic-cookie-key {{ include "fogServices.fogViewHTTPCookieSalt" . }} + cookie "VIEWHTTP" insert indirect nocache dynamic + haproxy.org/path-rewrite: '/gw/(.*) /\1' # Strip the /gw prefix + + podAnnotations: + fluentbit.io/include: 'true' # collect logs with fluentbit + fluentbit.io/exclude-jaeger-agent: 'true' + + ### Intel SGX extended resources are defined with: https://github.com/sebva/sgx-device-plugin + resources: + limits: + intel.com/sgx: 5000 + requests: + intel.com/sgx: 5000 + + nodeSelector: + sgx-enabled-node: 'true' + + tolerations: + - key: sgx + operator: Equal + value: 'true' + effect: NoSchedule + +fogLedger: + replicaCount: 2 + image: + org: '' + name: fog-ledger + pullPolicy: Always + + rust: + backtrace: full + log: info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn + + persistence: + enabled: true + spec: + storageClassName: fast + accessModes: + - 'ReadWriteOnce' + resources: + requests: + storage: 512Gi + + initContainers: + - name: migrate-ledger + image: "{{ .Values.fogLedger.image.org | default .Values.image.org }}/{{ .Values.fogLedger.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + command: [ '/bin/bash' ] + args: + - -c + - | + set -e + if [[ -f "/fog-data/ledger/data.mdb" ]] + then + cp /fog-data/ledger/data.mdb /fog-data/ledger/data.mdb.bak + /usr/bin/mc-ledger-migration --ledger-db /fog-data/ledger + fi + volumeMounts: + - name: fog-data + mountPath: /fog-data + + ingress: + grpc: + annotations: |- + cert-manager.io/cluster-issuer: letsencrypt-production-http + haproxy.org/server-proto: "h2" # Force GRPC/H2 mode + haproxy.org/server-ssl: "false" # The backend (server) is http + # haproxy.org/cookie-persistence: "fog-ledger" + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: "true" + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + dynamic-cookie-key {{ include "fogServices.fogLedgerGRPCCookieSalt" . }} + cookie "LEDGER" insert indirect nocache dynamic + + http: + annotations: |- + cert-manager.io/cluster-issuer: letsencrypt-production-http + haproxy.org/server-ssl: "false" # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: "true" + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + dynamic-cookie-key {{ include "fogServices.fogLedgerHTTPCookieSalt" . }} + cookie "LEDGERHTTP" insert indirect nocache dynamic + haproxy.org/path-rewrite: '/gw/(.*) /\1' # Strip the /gw prefix + + podAnnotations: + fluentbit.io/include: 'true' # collect logs with fluentbit + fluentbit.io/exclude-jaeger-agent: 'true' + + ### Intel SGX extended resources are defined with: https://github.com/sebva/sgx-device-plugin + resources: + limits: + intel.com/sgx: 5000 + requests: + intel.com/sgx: 5000 + + nodeSelector: + sgx-enabled-node: 'true' + + tolerations: + - key: sgx + operator: Equal + value: 'true' + effect: NoSchedule + +grpcGateway: + image: + org: '' + name: go-grpc-gateway + pullPolicy: Always + resources: {} + tolerations: [] + affinity: {} + nodeSelector: {} + +jaegerTracing: + enabled: true + collector: 'dns:///jaeger-collector:14250' diff --git a/.internal-ci/helm/fog-test-client/.helmignore b/.internal-ci/helm/fog-test-client/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/.internal-ci/helm/fog-test-client/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/.internal-ci/helm/fog-test-client/Chart.yaml b/.internal-ci/helm/fog-test-client/Chart.yaml new file mode 100644 index 0000000000..ca916238ad --- /dev/null +++ b/.internal-ci/helm/fog-test-client/Chart.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: fog-test-client +description: fog-test-client - end to end testing of fog. +type: application +version: 0.0.0 +appVersion: 0.0.0 diff --git a/.internal-ci/helm/fog-test-client/README.md b/.internal-ci/helm/fog-test-client/README.md new file mode 100644 index 0000000000..7a4048273c --- /dev/null +++ b/.internal-ci/helm/fog-test-client/README.md @@ -0,0 +1,37 @@ +# fog-test-client + +## Requirements + +- op (1Password cli) +- jq +- kubectl +- helm + +## Setup + +This assumes that all the fog-test-client instances will be installed on the same cluster in different namespaces. + +1. Run `scripts/setup.sh` + + This will pull down the account keys and secrets from 1password and generate the kubernetes objects needed for the deployment. The files will be in `/tmp/nets` + +1. Run `scripts/apply-k8s.sh` + + This will apply the generated kubernetes objects in `/tmp/nets` for their networks into an isolated namespace. + +## Deployment + +### For MC networks + +```bash +helm -n ${namespace} upgrade fog-test-client ./ -i \ +--set fogTestClient.image.tag=0.0.1 +``` + +### For Signal networks + +```bash +helm -n ${namespace} upgrade fog-test-client ./ -i \ +--set fogTestClient.image.tag=0.0.1 \ +--set fogTestClientConfig.fogClientAuthTokenSecret.enabled=true +``` diff --git a/.internal-ci/helm/fog-test-client/scripts/apply-k8s.sh b/.internal-ci/helm/fog-test-client/scripts/apply-k8s.sh new file mode 100755 index 0000000000..6076df15f8 --- /dev/null +++ b/.internal-ci/helm/fog-test-client/scripts/apply-k8s.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +tmp=/tmp + +net="${1}" + +case ${net} in + mc-testnet) + namespace="fog-test-client-mc-testnet" + ;; + signal-testnet) + namespace="fog-test-client-signal-testnet" + ;; + mc-mainnet) + namespace="fog-test-client-mc-mainnet" + ;; + signal-mainnet) + namespace="fog-test-client-signal-mainnet" + ;; + *) + echo "Unknown network" + exit 1 + ;; +esac + +kubectl -n "${namespace}" apply -f -d "${tmp}/nets/${net}/k8s" diff --git a/.internal-ci/helm/fog-test-client/scripts/download_sigstruct.sh b/.internal-ci/helm/fog-test-client/scripts/download_sigstruct.sh new file mode 100755 index 0000000000..14716bc001 --- /dev/null +++ b/.internal-ci/helm/fog-test-client/scripts/download_sigstruct.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# Usage: +# source ./tools/download_sigstruct.sh +# +# OR +# +# NETWORK="prod.mobilecoinww.com" source ./tools/download_sigstruct.sh + +# Download sigstructs from enclave-distribution.${NETWORK}/production.json, +# and set _CSS environment variables correctly for the build. +# +# source this script in order to get those variables in your shell. +# +# Use with e.g. NETWORK="test.mobilecoin.com" or NETWORK="prod.mobilecoin.com" + +if [ -z ${NETWORK+x} ]; then + NETWORK="test.mobilecoin.com" +fi + +CONSENSUS_SIGSTRUCT_URI=$(curl -s https://enclave-distribution.${NETWORK}/production.json | grep consensus-enclave.css | awk '{print $2}' | tr -d \" | tr -d ,) +curl -O https://enclave-distribution.${NETWORK}/${CONSENSUS_SIGSTRUCT_URI} +INGEST_SIGSTRUCT_URI=$(curl -s https://enclave-distribution.${NETWORK}/production.json | grep ingest-enclave.css | awk '{print $2}' | tr -d \" | tr -d ,) +curl -O https://enclave-distribution.${NETWORK}/${INGEST_SIGSTRUCT_URI} +LEDGER_SIGSTRUCT_URI=$(curl -s https://enclave-distribution.${NETWORK}/production.json | grep ledger-enclave.css | awk '{print $2}' | tr -d \" | tr -d ,) +curl -O https://enclave-distribution.${NETWORK}/${LEDGER_SIGSTRUCT_URI} +VIEW_SIGSTRUCT_URI=$(curl -s https://enclave-distribution.${NETWORK}/production.json | grep view-enclave.css | awk '{print $2}' | tr -d \" | tr -d ,) +curl -O https://enclave-distribution.${NETWORK}/${VIEW_SIGSTRUCT_URI} +export CONSENSUS_ENCLAVE_CSS=$(pwd)/consensus-enclave.css +export INGEST_ENCLAVE_CSS=$(pwd)/ingest-enclave.css +export LEDGER_ENCLAVE_CSS=$(pwd)/ledger-enclave.css +export VIEW_ENCLAVE_CSS=$(pwd)/view-enclave.css diff --git a/.internal-ci/helm/fog-test-client/scripts/generate-k8s.sh b/.internal-ci/helm/fog-test-client/scripts/generate-k8s.sh new file mode 100755 index 0000000000..afe8f767ad --- /dev/null +++ b/.internal-ci/helm/fog-test-client/scripts/generate-k8s.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +tmp=/tmp + +net="${1}" + +case ${net} in + mc-testnet) + export CONSENSUS_VALIDATORS="mc://node1.test.mobilecoin.com/,mc://node2.test.mobilecoin.com/,mc://node3.test.mobilecoin.com/" + export FOG_VIEW="fog-view://fog.test.mobilecoin.com:443" + export FOG_LEDGER="fog-ledger://fog.test.mobilecoin.com:443" + export MC_PARTNER="mc" + export MC_NETWORK="test" + ;; + signal-testnet) + export CONSENSUS_VALIDATORS="mc://node1.test.mobilecoin.com/,mc://node2.test.mobilecoin.com/,mc://node3.test.mobilecoin.com/" + export FOG_VIEW="fog-view://service.fog.mob.staging.namda.net:443" + export FOG_LEDGER="fog-ledger://service.fog.mob.staging.namda.net:443" + export MC_PARTNER="signal" + export MC_NETWORK="test" + export CLIENT_AUTH_TOKEN_SECRET="${CLIENT_AUTH_TOKEN_SECRET}" + ;; + mc-mainnet) + export CONSENSUS_VALIDATORS="mc://node1.prod.mobilecoinww.com/,mc://node2.prod.mobilecoinww.com/,mc://node3.prod.mobilecoinww.com/" + export FOG_VIEW="fog-view://fog.prod.mobilecoinww.com:443" + export FOG_LEDGER="fog-ledger://fog.prod.mobilecoinww.com:443" + export MC_PARTNER="mc" + export MC_NETWORK="prod" + ;; + signal-mainnet) + export CONSENSUS_VALIDATORS="mc://node1.prod.mobilecoinww.com/,mc://node2.prod.mobilecoinww.com/,mc://node3.prod.mobilecoinww.com/" + export FOG_VIEW="fog-view://service.fog.mob.production.namda.net:443" + export FOG_LEDGER="fog-ledger://service.fog.mob.production.namda.net:443" + export MC_PARTNER="signal" + export MC_NETWORK="prod" + export CLIENT_AUTH_TOKEN_SECRET="${CLIENT_AUTH_TOKEN_SECRET}" + ;; + *) + echo "Unknown network" + exit 1 + ;; +esac + +net_path="${tmp}/nets/${net}" +measurement_path="${net_path}/measurements" +keys_path="${net_path}/keys" + +mkdir -p "${net_path}/k8s" + +kubectl create configmap fog-test-client-measurements -o yaml --dry-run=client \ + --from-file "${measurement_path}" \ + | grep -v creationTimestamp > "${net_path}/k8s/fog-test-client-measurements-configMap.yaml" + +kubectl create configmap fog-test-client -o yaml --dry-run=client \ + --from-literal=FOG_VIEW="${FOG_VIEW}" \ + --from-literal=FOG_LEDGER="${FOG_LEDGER}" \ + --from-literal=CONSENSUS_VALIDATORS="${CONSENSUS_VALIDATORS}" \ + | grep -v creationTimestamp > "${net_path}/k8s/fog-test-client-configMap.yaml" + +kubectl create secret generic fog-test-client-keys -o yaml --dry-run=client \ + --from-file "${keys_path}" \ + | grep -v creationTimestamp > "${net_path}/k8s/fog-test-client-keys-secret.yaml" + +if [ -n "${CLIENT_AUTH_TOKEN_SECRET}" ] +then + kubectl create secret generic fog-client-auth-token -o yaml --dry-run=client \ + --from-literal=token="${CLIENT_AUTH_TOKEN_SECRET}" \ + | grep -v creationTimestamp > "${net_path}/k8s/fog-client-auth-token-secret.yaml" +fi + +kubectl create configmap mobilecoin-network -o yaml --dry-run=client \ + --from-literal=network="${MC_NETWORK}" \ + --from-literal=partner="${MC_PARTNER}" \ + | grep -v creationTimestamp > "${net_path}/k8s/mobilecoin-network-configMap.yaml" diff --git a/.internal-ci/helm/fog-test-client/scripts/setup.sh b/.internal-ci/helm/fog-test-client/scripts/setup.sh new file mode 100755 index 0000000000..cafe582eca --- /dev/null +++ b/.internal-ci/helm/fog-test-client/scripts/setup.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +set -e + +# Paths +location=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +tmp=/tmp + +# Nets +all_nets="mc-mainnet mc-testnet signal-testnet signal-mainnet" +test_nets="mc-testnet signal-testnet" +prod_nets="mc-mainnet signal-mainnet" +signal_nets="signal-mainnet signal-testnet" + +# Vaults +wallet_vault="Fog-Test-Client Wallets" + +echo "---- Check to see if you're logged into 1Password and get Wallet Vault" +vault_items=$(op list items --vault "${wallet_vault}") + +echo "---- Setup keys and measurements directories" +for n in ${all_nets} +do + mkdir -p "${tmp}/nets/${n}/keys" + mkdir -p "${tmp}/nets/${n}/measurements" +done + +echo "---- Download testnet sigstructs" +for n in ${test_nets} +do + export NETWORK=test.mobilecoin.com + + pushd "${tmp}/nets/${n}/measurements" || exit 1 + "${location}/download_sigstruct.sh" + popd || exit 1 +done + +echo "---- Download mainnet sigstructs" +for n in ${prod_nets} +do + export NETWORK=prod.mobilecoin.com + + pushd "${tmp}/nets/${n}/measurements" || exit 1 + "${location}/download_sigstruct.sh" + popd || exit 1 +done + + +echo "---- Populate keys from 1pass vault" +for n in ${all_nets} +do + # get uuid for vault item that matches the network + uuid=$(echo "${vault_items}" |jq -r ".[] | select(.overview.title | match(\"${n}/fog-test-client\")).uuid") + # get item details for that uuid + item=$(op get item "${uuid}") + # list the fields for item - this contains the filenames (n) and contents (v) + fields=$(echo "${item}" | jq -r '.details.sections[0].fields[].n') + + # write values for each file + for f in ${fields} + do + name=$(echo "${item}" | jq -r ".details.sections[0].fields[] | select(.n == \"${f}\").t") + value=$(echo "${item}" | jq -r ".details.sections[0].fields[] | select(.n == \"${f}\").v") + + [ -n "${DEBUG}" ] && echo "DEBUG: Writing ${tmp}/nets/${n}/keys/${name}" + # .pub files are binary need to base64 decode values. + if [[ $name =~ \.pub$ ]] + then + [ -n "${DEBUG}" ] && echo "DEBUG: base64 decode" + echo -n "${value}" | base64 -i -d -w0 > "${tmp}/nets/${n}/keys/${name}" + else + echo "${value}" > "${tmp}/nets/${n}/keys/${name}" + fi + done +done + +echo "---- Get fog-client-auth-token-secrets" +for n in ${signal_nets} +do + # get uuid for fog-client-auth-secret by network + uuid=$(echo "${vault_items}" |jq -r ".[] | select(.overview.title | match(\"${n}/fog-client-auth-token-secret\")).uuid") + # get item details for uuid + item=$(op get item "${uuid}") + # get password for in item + value=$(echo "${item}" | jq -r '.details.fields[] | select(.name=="password").value') + + # write value to file + echo -n "${value}" > "${tmp}/nets/${n}/fog-client-auth-token-secret" +done + +echo "---- Generate k8s objects" +for n in ${all_nets} +do + if [[ ${n} =~ ^signal ]] + then + CLIENT_AUTH_TOKEN_SECRET=$(cat "${tmp}/nets/${n}/fog-client-auth-token-secret") + export CLIENT_AUTH_TOKEN_SECRET + fi + + "${location}/generate-k8s.sh" "${n}" + unset CLIENT_AUTH_TOKEN_SECRET +done diff --git a/.internal-ci/helm/fog-test-client/templates/NOTES.txt b/.internal-ci/helm/fog-test-client/templates/NOTES.txt new file mode 100644 index 0000000000..22651769fd --- /dev/null +++ b/.internal-ci/helm/fog-test-client/templates/NOTES.txt @@ -0,0 +1,16 @@ +:::: :::: :::::::: ::::::::: ::::::::::: ::: :::::::::: ++:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: ++:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ ++#+ +:+ +#+ +#+ +:+ +#++:++#+ +#+ +#+ +#++:++# ++#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+# #+# #+# #+# #+# #+# #+# #+# #+# +### ### ######## ######### ########### ########## ########## + :::::::: :::::::: ::::::::::: :::: ::: +:+: :+: :+: :+: :+: :+:+: :+: ++:+ +:+ +:+ +:+ :+:+:+ +:+ ++#+ +#+ +:+ +#+ +#+ +:+ +#+ ++#+ +#+ +#+ +#+ +#+ +#+#+# +#+# #+# #+# #+# #+# #+# #+#+# + ######## ######## ########### ### #### + +fog-test-client deployment successfully. diff --git a/.internal-ci/helm/fog-test-client/templates/_helpers.tpl b/.internal-ci/helm/fog-test-client/templates/_helpers.tpl new file mode 100644 index 0000000000..9fa2712a8f --- /dev/null +++ b/.internal-ci/helm/fog-test-client/templates/_helpers.tpl @@ -0,0 +1,75 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "chart.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chart.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "chart.labels" -}} +helm.sh/chart: {{ include "chart.chart" . }} +{{ include "chart.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chart.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chart.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Mobilecoin Network (monitoring label) +*/}} +{{- define "chart.mobileCoinNetwork.network" -}} + {{- if .Values.mobileCoinNetwork.configMap.external }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace .Values.mobileCoinNetwork.configMap.name).data.network | default "" }} + {{- else }} + {{- .Values.mobileCoinNetwork.network }} + {{- end }} +{{- end }} + +{{/* +Mobilecoin Network Partner (monitoring label) +*/}} +{{- define "chart.mobileCoinNetwork.partner" -}} + {{- if .Values.mobileCoinNetwork.configMap.external }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace .Values.mobileCoinNetwork.configMap.name).data.partner | default "" }} + {{- else }} + {{- .Values.mobileCoinNetwork.partner }} + {{- end }} +{{- end }} diff --git a/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml b/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml new file mode 100644 index 0000000000..8adcc8081f --- /dev/null +++ b/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml @@ -0,0 +1,132 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: Deployment +metadata: + name: "{{ include "chart.fullname" . }}" + labels: + {{- include "chart.labels" . | nindent 4 }} + app: fog-test-client +spec: + replicas: {{ .Values.fogTestClient.replicaCount }} + selector: + matchLabels: + {{- include "chart.selectorLabels" . | nindent 6 }} + app: fog-test-client + template: + metadata: + annotations: + {{- toYaml .Values.fogTestClient.podAnnotations | nindent 8 }} + labels: + {{- include "chart.selectorLabels" . | nindent 8 }} + app: fog-test-client + spec: + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 8 }} + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + containers: + - name: fog-test-client + image: "{{ .Values.fogTestClient.image.repository }}:{{ .Values.fogTestClient.image.tag }}" + imagePullPolicy: Always + securityContext: + capabilities: + drop: + - all + readOnlyRootFilesystem: true + env: + - name: FOG_VIEW + valueFrom: + configMapKeyRef: + name: {{ .Values.fogTestClientConfig.configMap.name }} + key: FOG_VIEW + - name: FOG_LEDGER + valueFrom: + configMapKeyRef: + name: {{ .Values.fogTestClientConfig.configMap.name }} + key: FOG_LEDGER + - name: CONSENSUS_VALIDATORS + valueFrom: + configMapKeyRef: + name: {{ .Values.fogTestClientConfig.configMap.name }} + key: CONSENSUS_VALIDATORS + - name: CONSENSUS_WAIT + valueFrom: + configMapKeyRef: + name: {{ .Values.fogTestClientConfig.configMap.name }} + key: CONSENSUS_WAIT + - name: TRANSFER_AMOUNT + value: "100000000000" + {{- if.Values.fogTestClientConfig.fogClientAuthTokenSecret.enabled }} + - name: CLIENT_AUTH_TOKEN_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.fogTestClientConfig.fogClientAuthTokenSecret.name }} + key: token + {{- end }} + ports: + - name: grpc-mgmt + containerPort: 8001 + protocol: TCP + readinessProbe: + tcpSocket: + port: 8001 + initialDelaySeconds: 10 + periodSeconds: 10 + livenessProbe: + tcpSocket: + port: 8001 + initialDelaySeconds: 20 + periodSeconds: 20 + volumeMounts: + - mountPath: /keys + name: keys + - mountPath: /measurements + name: measurements + resources: + {{- toYaml .Values.fogTestClient.resources | nindent 12 }} + - name: admin-gateway + image: "{{ .Values.fogTestClient.image.repository }}:{{ .Values.fogTestClient.image.tag }}" + imagePullPolicy: Always + securityContext: + capabilities: + drop: + - all + readOnlyRootFilesystem: true + env: + - name: RUST_LOG + value: warn + ports: + - name: http-mgmt + containerPort: 9090 + protocol: TCP + command: + - /usr/local/bin/mc-admin-http-gateway + args: + - --admin-uri=insecure-mca://127.0.0.1:8001/ + - --listen-host=0.0.0.0 + readinessProbe: + httpGet: + path: / + port: 9090 + initialDelaySeconds: 10 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 9090 + initialDelaySeconds: 20 + periodSeconds: 20 + nodeSelector: + {{- toYaml .Values.fogTestClient.nodeSelector | nindent 8 }} + affinity: + {{- toYaml .Values.fogTestClient.affinity | nindent 8 }} + tolerations: + {{- toYaml .Values.fogTestClient.tolerations | nindent 8 }} + volumes: + - name: keys + secret: + secretName: {{ .Values.fogTestClientConfig.keysSecret.name }} + - name: measurements + configMap: + name: {{ .Values.fogTestClientConfig.measurementsConfigMap.name }} diff --git a/.internal-ci/helm/fog-test-client/templates/fog-test-client-service.yaml b/.internal-ci/helm/fog-test-client/templates/fog-test-client-service.yaml new file mode 100644 index 0000000000..be44a0ac07 --- /dev/null +++ b/.internal-ci/helm/fog-test-client/templates/fog-test-client-service.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "chart.fullname" . }} + labels: + app: fog-test-client + {{- include "chart.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: fog-test-client + {{- include "chart.selectorLabels" . | nindent 4 }} + ports: + - name: mgmt + port: 9090 + targetPort: http-mgmt diff --git a/.internal-ci/helm/fog-test-client/templates/fog-test-client-serviceMonitor.yaml b/.internal-ci/helm/fog-test-client/templates/fog-test-client-serviceMonitor.yaml new file mode 100644 index 0000000000..80ff80be5e --- /dev/null +++ b/.internal-ci/helm/fog-test-client/templates/fog-test-client-serviceMonitor.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{ if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "chart.fullname" . }} + labels: + publish: grafana-cloud + app: fog-test-client + {{- include "chart.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: fog-test-client + {{- include "chart.selectorLabels" . | nindent 6 }} + endpoints: + - port: mgmt + relabelings: + - targetLabel: network + replacement: {{ include "chart.mobileCoinNetwork.network" . }} + - targetLabel: partner + replacement: {{ include "chart.mobileCoinNetwork.partner" . }} +{{- end }} \ No newline at end of file diff --git a/.internal-ci/helm/fog-test-client/values.yaml b/.internal-ci/helm/fog-test-client/values.yaml new file mode 100644 index 0000000000..f3b2c131fb --- /dev/null +++ b/.internal-ci/helm/fog-test-client/values.yaml @@ -0,0 +1,72 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +### Chart Overrides. +nameOverride: "" +fullnameOverride: "" + +imagePullSecrets: +- name: docker-credentials + + +### Configuration and Secrets +fogTestClientConfig: + ### populates keys directory, expects .b58pub and .json files for each key. + # Generate with: + # kubectl create secret generic fog-test-client -o yaml --dry-run=client \ + # --from-file ./keys \ + # | grep -v creationTimestamp > fog-test-client-secret.yaml + keysSecret: + name: fog-test-client-keys + + ### populates urls and vars + # Generate with: + # kubectl create configmap fog-test-client -o yaml --dry-run=client \ + # --from-literal=FOG_VIEW="${FOG_VIEW}" \ + # --from-literal=FOG_LEDGER="${FOG_LEDGER}" \ + # --from-literal=CONSENSUS_VALIDATORS="${CONSENSUS_VALIDATORS}" \ + # | grep -v creationTimestamp > "fog-test-client-configMap.yaml" + configMap: + name: fog-test-client + + ### populates enclave measurement .css files + # Generate with: + # kubectl create configmap fog-test-client-measurements -o yaml --dry-run=client \ + # --from-file ./measurements \ + # | grep -v creationTimestamp > fog-test-client-measurements-configMap.yaml + measurementsConfigMap: + name: fog-test-client-measurements + + ### Enable for Signal Fog environments. + # Secret used to generate token when communicating with signal view/ledger services. + # Generate with: + # kubectl create secret generic fog-client-auth-token -o yaml --dry-run=client \ + # --from-literal=token="${CLIENT_AUTH_TOKEN_SECRET}" \ + # | grep -v creationTimestamp > fog-client-auth-token-secret.yaml + fogClientAuthTokenSecret: + name: fog-client-auth-token + enabled: false + + +### Deployments +fogTestClient: + replicaCount: 1 + image: + repository: mobilecoin/fog-test-client + tag: "" + podAnnotations: + fluentbit.io/include: 'true' + resources: {} + nodeSelector: {} + tolerations: [] + affinity: {} + +mobileCoinNetwork: + configMap: + external: true + name: mobilecoin-network + # test, prod, alpha... + network: "" + # mc, mcww, signal... + partner: "" + +serviceMonitor: + enabled: true \ No newline at end of file diff --git a/.internal-ci/helm/mc-core-common-config/.helmignore b/.internal-ci/helm/mc-core-common-config/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/.internal-ci/helm/mc-core-common-config/Chart.yaml b/.internal-ci/helm/mc-core-common-config/Chart.yaml new file mode 100644 index 0000000000..380f64f4e7 --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/Chart.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: mc-core-common-config +description: Set up common configMaps and Secrets for core apps. +type: application +version: 0.0.0 +appVersion: 0.0.0 diff --git a/.internal-ci/helm/mc-core-common-config/templates/NOTES.txt b/.internal-ci/helm/mc-core-common-config/templates/NOTES.txt new file mode 100644 index 0000000000..d8f3902d3d --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/NOTES.txt @@ -0,0 +1 @@ +MC Common Core Config diff --git a/.internal-ci/helm/mc-core-common-config/templates/_helpers.tpl b/.internal-ci/helm/mc-core-common-config/templates/_helpers.tpl new file mode 100644 index 0000000000..ddb4f1c3e6 --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/_helpers.tpl @@ -0,0 +1,71 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* +Expand the name of the mcCoreCommonConfig. +*/}} +{{- define "mcCoreCommonConfig.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mcCoreCommonConfig.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mcCoreCommonConfig.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mcCoreCommonConfig.labels" -}} +helm.sh/chart: {{ include "mcCoreCommonConfig.chart" . }} +{{ include "mcCoreCommonConfig.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mcCoreCommonConfig.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mcCoreCommonConfig.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +mobilecoind quorum value +*/}} +{{- define "mcCoreCommonConfig.mobilecoindQuorum" -}} +{ "threshold": {{ tpl .Values.mobilecoind.threshold . }}, "members": {{ include "mcCoreCommonConfig.mobilecoindQuorumMembers" . }} } +{{- end }} + +{{/* +Generate mobilecoind quorum value +*/}} +{{- define "mcCoreCommonConfig.mobilecoindQuorumMembers" }} + {{- $members := list }} + {{- range .Values.mobilecoind.nodes }} + {{- $members = append $members (dict "type" "Node" "args" (tpl .client $)) }} + {{- end }} + {{- toJson $members }} +{{- end }} diff --git a/.internal-ci/helm/mc-core-common-config/templates/client-auth-token-secret.yaml b/.internal-ci/helm/mc-core-common-config/templates/client-auth-token-secret.yaml new file mode 100644 index 0000000000..4091291821 --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/client-auth-token-secret.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: client-auth-token + labels: + {{- include "mcCoreCommonConfig.labels" . | nindent 4 }} +type: Opaque +stringData: + token: {{ .Values.clientAuth.token | quote }} diff --git a/.internal-ci/helm/mc-core-common-config/templates/fog-supervisord-mobilecoind-configmap.yaml b/.internal-ci/helm/mc-core-common-config/templates/fog-supervisord-mobilecoind-configmap.yaml new file mode 100644 index 0000000000..96b737a617 --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/fog-supervisord-mobilecoind-configmap.yaml @@ -0,0 +1,26 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: fog-supervisord-mobilecoind + labels: + {{- include "mcCoreCommonConfig.labels" . | nindent 4 }} +data: + mobilecoind.conf: | + [program:mobilecoind-sync] + priority=10 + command=/usr/bin/mobilecoind +{{- range .Values.mobilecoind.nodes }} + --peer mc://{{ tpl .client $ }}/ + --tx-source-url {{ tpl .txSourceUrl $ }} +{{- end }} + --poll-interval 1 + --quorum-set {{ include "mcCoreCommonConfig.mobilecoindQuorum" . | squote }} + --ledger-db /fog-data/ledger + --watcher-db /fog-data/watcher + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/mc-core-common-config/templates/ias-secret.yaml b/.internal-ci/helm/mc-core-common-config/templates/ias-secret.yaml new file mode 100644 index 0000000000..6367979026 --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/ias-secret.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: ias + labels: + {{- include "mcCoreCommonConfig.labels" . | nindent 4 }} +type: Opaque +stringData: + IAS_API_KEY: {{ .Values.ias.key | quote }} + IAS_SPID: {{ .Values.ias.spid | quote }} diff --git a/.internal-ci/helm/mc-core-common-config/templates/ipinfo-secret.yaml b/.internal-ci/helm/mc-core-common-config/templates/ipinfo-secret.yaml new file mode 100644 index 0000000000..53c3525c3f --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/ipinfo-secret.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Secret +metadata: + name: ipinfo + labels: + {{- include "mcCoreCommonConfig.labels" . | nindent 4 }} +type: Opaque +stringData: + MC_IP_INFO_TOKEN: {{ .Values.ipinfo.token | quote }} diff --git a/.internal-ci/helm/mc-core-common-config/templates/mobilecoin-network-configmap.yaml b/.internal-ci/helm/mc-core-common-config/templates/mobilecoin-network-configmap.yaml new file mode 100644 index 0000000000..28857b78ac --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/mobilecoin-network-configmap.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: mobilecoin-network + labels: + {{- include "mcCoreCommonConfig.labels" . | nindent 4 }} +data: + network: {{ tpl .Values.mobileCoinNetwork.network . | default "" | quote }} + partner: {{ tpl .Values.mobileCoinNetwork.partner . | default "" | quote }} diff --git a/.internal-ci/helm/mc-core-common-config/templates/mobilecoind-supervisord-mobilecoind-configmap.yaml b/.internal-ci/helm/mc-core-common-config/templates/mobilecoind-supervisord-mobilecoind-configmap.yaml new file mode 100644 index 0000000000..5d99ceac7a --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/mobilecoind-supervisord-mobilecoind-configmap.yaml @@ -0,0 +1,27 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: mobilecoind-supervisord-mobilecoind + labels: + {{- include "mcCoreCommonConfig.labels" . | nindent 4 }} +data: + mobilecoind.conf: | + [program:mobilecoind-sync] + command=/usr/bin/mobilecoind +{{- range .Values.mobilecoind.nodes }} + --peer mc://{{ tpl .client $ }}/ + --tx-source-url {{ tpl .txSourceUrl $ }} +{{- end }} + --poll-interval 1 + --quorum-set {{ include "mcCoreCommonConfig.mobilecoindQuorum" . | squote }} + --ledger-db /data/ledger + --watcher-db /data/watcher + --mobilecoind-db /data/mobilecoind + --listen-uri insecure-mobilecoind://0.0.0.0:3229/ + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/mc-core-common-config/templates/sentry-configmap.yaml b/.internal-ci/helm/mc-core-common-config/templates/sentry-configmap.yaml new file mode 100644 index 0000000000..6d0271daff --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/templates/sentry-configmap.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +kind: ConfigMap +apiVersion: v1 +metadata: + name: sentry + labels: + {{- include "mcCoreCommonConfig.labels" . | nindent 4 }} +data: + {{- toYaml .Values.sentry | nindent 2 }} diff --git a/.internal-ci/helm/mc-core-common-config/values.yaml b/.internal-ci/helm/mc-core-common-config/values.yaml new file mode 100644 index 0000000000..562a2d14e8 --- /dev/null +++ b/.internal-ci/helm/mc-core-common-config/values.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +clientAuth: + token: '' + +ias: + key: '' + spid: '' + +mobileCoinNetwork: + network: '' + partner: '' + +ipinfo: + token: '' + +sentry: + consensus-sentry-dsn: '' + ledger-distribution-sentry-dsn: '' + fog-report-sentry-dsn: '' + fog-view-sentry-dsn: '' + fog-ledger-sentry-dsn: '' + fog-ingest-sentry-dsn: '' + +### Consensus nodes for mobilecoind processes (managed by superviosrd) +# Configure with chart external ConfigMap or values here. +# peer url must have '?responder-id=' query string if 'load balanced' +# tx-source-id is the public url for the s3 bucket containing the ledger from the node. +mobilecoind: + threshold: '' + nodes: [] + # - client: 'node1.prod.mobilecoinww.com:443' + # txSourceUrl: https://ledger.mobilecoinww.com/node1.prod.mobilecoinww.com + # - client: 'node2.prod.mobilecoinww.com:443' + # txSourceUrl: https://ledger.mobilecoinww.com/node2.prod.mobilecoinww.com + # - client: 'node3.prod.mobilecoinww.com:443' + # txSourceUrl: https://ledger.mobilecoinww.com/node3.prod.mobilecoinww.com diff --git a/.internal-ci/helm/mc-core-dev-env-setup/Chart.yaml b/.internal-ci/helm/mc-core-dev-env-setup/Chart.yaml new file mode 100644 index 0000000000..b517185c27 --- /dev/null +++ b/.internal-ci/helm/mc-core-dev-env-setup/Chart.yaml @@ -0,0 +1,48 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: mc-core-dev-env-setup +description: Populate configuration for a dev environment. +type: application +version: 0.0.0 +appVersion: 0.0.0 +dependencies: +- name: mc-core-common-config + alias: mcCoreCommonConfig + repository: file://../mc-core-common-config + version: 0.0.0 + condition: mcCoreCommonConfig.enabled +- name: consensus-node-config + alias: consensusNodeConfig1 + repository: file://../consensus-node-config + version: 0.0.0 + condition: consensusNodeConfig1.enabled +- name: consensus-node-config + repository: file://../consensus-node-config + version: 0.0.0 + alias: consensusNodeConfig2 + condition: consensusNodeConfig2.enabled +- name: consensus-node-config + alias: consensusNodeConfig3 + repository: file://../consensus-node-config + version: 0.0.0 + condition: consensusNodeConfig3.enabled +- name: consensus-node-config + alias: consensusNodeConfig4 + repository: file://../consensus-node-config + version: 0.0.0 + condition: consensusNodeConfig4.enabled +- name: consensus-node-config + alias: consensusNodeConfig5 + repository: file://../consensus-node-config + version: 0.0.0 + condition: consensusNodeConfig5.enabled +- name: fog-ingest-config + alias: fogIngestConfig + repository: file://../fog-ingest-config + version: 0.0.0 + condition: fogIngestConfig.enabled +- name: fog-services-config + alias: fogServicesConfig + repository: file://../fog-services-config + version: 0.0.0 + condition: fogServicesConfig.enabled diff --git a/.internal-ci/helm/mc-core-dev-env-setup/README.md b/.internal-ci/helm/mc-core-dev-env-setup/README.md new file mode 100644 index 0000000000..f237d4d171 --- /dev/null +++ b/.internal-ci/helm/mc-core-dev-env-setup/README.md @@ -0,0 +1,26 @@ +# consensus-node Helm Chart + +Deploy a single node of the consensus service + +```sh +helm upgrade node1 ./ -i -n \ + --set image.tag=prod-1.0.1-pre2 +``` +Note: generated PersistentVolumeClaims will stick around if the Helm Chart is removed or the pods are deleted and allowed to regenerate. + +## Setup + +Configure a `values.yaml` file or pre-populate your namespace with the following ConfigMaps and Secrets. + +- `mobilecoin-network` + + Mobilecoin network value for monitoring: mainnet, testnet, alpha... + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: mobilecoin-network + data: + network: testnet + ``` \ No newline at end of file diff --git a/.internal-ci/helm/mc-core-dev-env-setup/templates/NOTES.txt b/.internal-ci/helm/mc-core-dev-env-setup/templates/NOTES.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.internal-ci/helm/mc-core-dev-env-setup/templates/_helpers.tpl b/.internal-ci/helm/mc-core-dev-env-setup/templates/_helpers.tpl new file mode 100644 index 0000000000..4a97dd9a25 --- /dev/null +++ b/.internal-ci/helm/mc-core-dev-env-setup/templates/_helpers.tpl @@ -0,0 +1,45 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* Expand the name of the devEnvSetup. */}} +{{- define "devEnvSetup.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "devEnvSetup.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "devEnvSetup.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Common labels */}} +{{- define "devEnvSetup.labels" -}} +helm.sh/chart: {{ include "devEnvSetup.chart" . }} +{{ include "devEnvSetup.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* Selector labels */}} +{{- define "devEnvSetup.selectorLabels" -}} +app.kubernetes.io/name: {{ include "devEnvSetup.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/.internal-ci/helm/mc-core-dev-env-setup/values.yaml b/.internal-ci/helm/mc-core-dev-env-setup/values.yaml new file mode 100644 index 0000000000..b02082c7d7 --- /dev/null +++ b/.internal-ci/helm/mc-core-dev-env-setup/values.yaml @@ -0,0 +1,129 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation + +global: + node: + ledgerDistribution: + awsRegion: eu-central-1 + s3Bucket: mobilecoin.eu.development.chain + startFrom: last + + networkConfig: + threshold: '3' + peers: + 1: + peer: + hostname: '{{ printf "peer1.%s.development.mobilecoin.com" .Release.Namespace }}' + port: '443' + signerPublicKey: '' + ledgerArchiveLocation: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node1.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + 2: + peer: + hostname: '{{ printf "peer2.%s.development.mobilecoin.com" .Release.Namespace }}' + port: '443' + signerPublicKey: '' + ledgerArchiveLocation: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node2.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + 3: + peer: + hostname: '{{ printf "peer3.%s.development.mobilecoin.com" .Release.Namespace }}' + port: '443' + signerPublicKey: '' + ledgerArchiveLocation: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node3.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + 4: + peer: + hostname: '{{ printf "peer4.%s.development.mobilecoin.com" .Release.Namespace }}' + port: '443' + signerPublicKey: '' + ledgerArchiveLocation: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node4.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + 5: + peer: + hostname: '{{ printf "peer5.%s.development.mobilecoin.com" .Release.Namespace }}' + port: '443' + signerPublicKey: '' + ledgerArchiveLocation: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node5.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + + # Add signed tokens.json with --set-file=global.node.tokensConfig."tokens\.signed\.json"=tokens.signed.json + tokensConfig: + tokensSignedJson: "" + +mcCoreCommonConfig: + enabled: true + fullnameOverride: mc-core-common-config + mobileCoinNetwork: + network: '{{ .Release.Namespace }}' + partner: 'dev' + mobilecoind: + threshold: '3' + nodes: + - client: '{{ printf "node1.%s.development.mobilecoin.com:443" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node1.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + - client: '{{ printf "node2.%s.development.mobilecoin.com:443" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node2.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + - client: '{{ printf "node3.%s.development.mobilecoin.com:443" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node3.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + - client: '{{ printf "node4.%s.development.mobilecoin.com:443" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node4.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + - client: '{{ printf "node5.%s.development.mobilecoin.com:443" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node5.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' + + +consensusNodeConfig1: + enabled: true + fullnameOverride: consensus-node-1 + node: + client: + hostname: '{{ printf "node1.%s.development.mobilecoin.com" .Release.Namespace }}' + peer: + hostname: '{{ printf "peer1.%s.development.mobilecoin.com" .Release.Namespace }}' + +consensusNodeConfig2: + enabled: true + fullnameOverride: consensus-node-2 + node: + client: + hostname: '{{ printf "node2.%s.development.mobilecoin.com" .Release.Namespace }}' + peer: + hostname: '{{ printf "peer2.%s.development.mobilecoin.com" .Release.Namespace }}' + +consensusNodeConfig3: + enabled: true + fullnameOverride: 'consensus-node-3' + node: + client: + hostname: '{{ printf "node3.%s.development.mobilecoin.com" .Release.Namespace }}' + peer: + hostname: '{{ printf "peer3.%s.development.mobilecoin.com" .Release.Namespace }}' + +consensusNodeConfig4: + enabled: true + fullnameOverride: 'consensus-node-4' + node: + client: + hostname: '{{ printf "node4.%s.development.mobilecoin.com" .Release.Namespace }}' + peer: + hostname: '{{ printf "peer4.%s.development.mobilecoin.com" .Release.Namespace }}' + +consensusNodeConfig5: + enabled: true + fullnameOverride: 'consensus-node-5' + node: + client: + hostname: '{{ printf "node5.%s.development.mobilecoin.com" .Release.Namespace }}' + peer: + hostname: '{{ printf "peer5.%s.development.mobilecoin.com" .Release.Namespace }}' + +fogIngestConfig: + enabled: true + fogRecoveryDatabase: + configMap: + enabled: true + secret: + enabled: true + +fogServicesConfig: + enabled: true + fogRecoveryDatabaseReader: + configMap: + enabled: true + fogPublicFQDN: + domainname: '{{ printf "fog.%s.development.mobilecoin.com" .Release.Namespace }}' + fogReportSANs: '{{ printf "fog-report.%s.development.mobilecoin.com" .Release.Namespace }}' diff --git a/.internal-ci/helm/mobilecoind/Chart.yaml b/.internal-ci/helm/mobilecoind/Chart.yaml new file mode 100644 index 0000000000..d115789033 --- /dev/null +++ b/.internal-ci/helm/mobilecoind/Chart.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: mobilecoind +description: MobileCoin mobilecoind service +type: application +version: 0.0.0 +appVersion: 0.0.0 +dependencies: +- name: mc-core-common-config + repository: file://../mc-core-common-config + version: 0.0.0 + condition: mcCoreCommonConfig.enabled + alias: mcCoreCommonConfig diff --git a/.internal-ci/helm/mobilecoind/templates/_helpers.tpl b/.internal-ci/helm/mobilecoind/templates/_helpers.tpl new file mode 100644 index 0000000000..5a93a340e6 --- /dev/null +++ b/.internal-ci/helm/mobilecoind/templates/_helpers.tpl @@ -0,0 +1,57 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* Expand the name of the Chart. */}} +{{- define "mobilecoind.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mobilecoind.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "mobilecoind.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* Common labels */}} +{{- define "mobilecoind.labels" -}} +helm.sh/chart: {{ include "mobilecoind.chart" . }} +{{ include "mobilecoind.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* Selector labels */}} +{{- define "mobilecoind.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mobilecoind.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +hostnames - we need this for ingress. +lookup name from configmap if we have created the objects in mobilecoind-config separately. +*/}} +{{- define "mobilecoind.hostname" -}} + {{- if eq .Values.mobilecoindConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace "mobilecoind").data.hostname | default "" }} + {{- else }} + {{- tpl .Values.mobilecoindConfig.hostname . }} + {{- end }} +{{- end }} diff --git a/.internal-ci/helm/mobilecoind/templates/mint-auditor-service.yaml b/.internal-ci/helm/mobilecoind/templates/mint-auditor-service.yaml new file mode 100644 index 0000000000..c62e0bd52f --- /dev/null +++ b/.internal-ci/helm/mobilecoind/templates/mint-auditor-service.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mobilecoind.fullname" . }}-mint-auditor + labels: + {{- include "mobilecoind.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: mobilecoind + {{- include "mobilecoind.selectorLabels" . | nindent 4 }} + ports: + - name: grpc + port: 7774 + targetPort: auditor-grpc diff --git a/.internal-ci/helm/mobilecoind/templates/mobilecoind-deployment.yaml b/.internal-ci/helm/mobilecoind/templates/mobilecoind-deployment.yaml new file mode 100644 index 0000000000..ca4e5fceae --- /dev/null +++ b/.internal-ci/helm/mobilecoind/templates/mobilecoind-deployment.yaml @@ -0,0 +1,131 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mobilecoind.fullname" . }} + labels: + app: mobilecoind + {{- include "mobilecoind.labels" . | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: mobilecoind + {{- include "mobilecoind.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- toYaml .Values.podAnnotations | nindent 8 }} + labels: + app: mobilecoind + {{- include "mobilecoind.labels" . | nindent 8 }} + spec: + nodeSelector: + {{- toYaml .Values.mobilecoindNodeSelector | nindent 8 }} + imagePullSecrets: + {{- toYaml .Values.imagePullSecrets | nindent 6 }} + initContainers: + {{- tpl (toYaml .Values.mobilecoind.initContainers) . | nindent 6 }} + containers: + - name: mobilecoind + image: '{{ .Values.mobilecoind.image.org | default .Values.image.org }}/{{ .Values.mobilecoind.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' + imagePullPolicy: Always + command: [ "/usr/bin/supervisord" ] + ports: + - name: grpc + containerPort: 3229 + - name: json + containerPort: 9090 + - name: auditor-grpc + containerPort: 7774 + # Hold liveness and readiness until this probe passes. + startupProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3229" + failureThreshold: 30 + periodSeconds: 10 + # Will wait for startup probe to succeed. When this passes k8s won't kill the service. + livenessProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3229" + failureThreshold: 3 + periodSeconds: 30 + # Will wait for startup probe to succeed. When this passes services/ingress will pass traffic + readinessProbe: + exec: + command: + - "/usr/local/bin/grpc_health_probe" + - "-addr=:3229" + failureThreshold: 4 + periodSeconds: 30 + envFrom: + - secretRef: + name: ipinfo + optional: true + env: + - name: "RUST_BACKTRACE" + value: "full" + - name: "RUST_LOG" + value: "info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn" + volumeMounts: + - name: data + mountPath: /data + - name: supervisor-conf + mountPath: /etc/supervisor/conf.d + readOnly: true + {{- if eq .Values.jaegerTracing.enabled true }} + - name: jaeger-agent + image: jaegertracing/jaeger-agent:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5775 + name: zk-compact-trft + protocol: UDP + - containerPort: 5778 + name: config-rest + protocol: TCP + - containerPort: 6831 + name: jg-compact-trft + protocol: UDP + - containerPort: 6832 + name: jg-binary-trft + protocol: UDP + - containerPort: 14271 + name: admin-http + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + args: + - --reporter.grpc.host-port={{ .Values.jaegerTracing.collector }} + - --reporter.type=grpc + - --agent.tags=cluster=undefined,container.name=node,deployment.name={{ include "mobilecoind.fullname" . }},host.ip=${HOST_IP:},pod.name=${POD_NAME:},pod.namespace={{ .Release.Namespace }} + {{- end }} + volumes: + - name: data + emptyDir: {} + - name: supervisor-conf + projected: + sources: + - configMap: + name: {{ include "mobilecoind.fullname" . }}-supervisord-daemon + - configMap: + name: mobilecoind-supervisord-mobilecoind + - configMap: + name: {{ include "mobilecoind.fullname" . }}-supervisord-mint-auditor + - configMap: + name: {{ include "mobilecoind.fullname" . }}-supervisord-mobilecoind-json diff --git a/.internal-ci/helm/mobilecoind/templates/mobilecoind-json-service.yaml b/.internal-ci/helm/mobilecoind/templates/mobilecoind-json-service.yaml new file mode 100644 index 0000000000..b4d16a6b66 --- /dev/null +++ b/.internal-ci/helm/mobilecoind/templates/mobilecoind-json-service.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mobilecoind.fullname" . }}-json + labels: + {{- include "mobilecoind.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: mobilecoind + {{- include "mobilecoind.selectorLabels" . | nindent 4 }} + ports: + - name: json + port: 9090 + targetPort: json diff --git a/.internal-ci/helm/mobilecoind/templates/mobilecoind-service.yaml b/.internal-ci/helm/mobilecoind/templates/mobilecoind-service.yaml new file mode 100644 index 0000000000..903a1a8a7c --- /dev/null +++ b/.internal-ci/helm/mobilecoind/templates/mobilecoind-service.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mobilecoind.fullname" . }} + labels: + {{- include "mobilecoind.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: mobilecoind + {{- include "mobilecoind.selectorLabels" . | nindent 4 }} + ports: + - name: grpc + port: 3229 + targetPort: grpc diff --git a/.internal-ci/helm/mobilecoind/templates/supervisord-daemon-configmap.yaml b/.internal-ci/helm/mobilecoind/templates/supervisord-daemon-configmap.yaml new file mode 100644 index 0000000000..7a9bc4c785 --- /dev/null +++ b/.internal-ci/helm/mobilecoind/templates/supervisord-daemon-configmap.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mobilecoind.fullname" . }}-supervisord-daemon + labels: + {{- include "mobilecoind.labels" . | nindent 4 }} +data: + supervisor.conf: | + [supervisord] + nodaemon=true diff --git a/.internal-ci/helm/mobilecoind/templates/supervisord-mint-auditor-configmap.yaml b/.internal-ci/helm/mobilecoind/templates/supervisord-mint-auditor-configmap.yaml new file mode 100644 index 0000000000..a121a4c26f --- /dev/null +++ b/.internal-ci/helm/mobilecoind/templates/supervisord-mint-auditor-configmap.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mobilecoind.fullname" . }}-supervisord-mint-auditor + labels: + {{- include "mobilecoind.labels" . | nindent 4 }} +data: + mint-auditor.conf: | + [program:mint-auditor] + command=/usr/bin/mc-mint-auditor + scan-ledger + --ledger-db /data/ledger + --mint-auditor-db /data/mint-auditor + --listen-uri insecure-mint-auditor://0.0.0.0:7774/ + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/mobilecoind/templates/supervisord-mobilecoind-json-configmap.yaml b/.internal-ci/helm/mobilecoind/templates/supervisord-mobilecoind-json-configmap.yaml new file mode 100644 index 0000000000..7b53e19573 --- /dev/null +++ b/.internal-ci/helm/mobilecoind/templates/supervisord-mobilecoind-json-configmap.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "mobilecoind.fullname" . }}-supervisord-mobilecoind-json + labels: + {{- include "mobilecoind.labels" . | nindent 4 }} +data: + mobilecoind-json.conf: | + [program:mobilecoind-json] + command=/usr/bin/mobilecoind-json + --listen-host 0.0.0.0 + --mobilecoind-uri insecure-mobilecoind://localhost:3229 + + stdout_logfile=/dev/fd/1 + stdout_logfile_maxbytes=0 + stderr_logfile=/dev/fd/2 + stderr_logfile_maxbytes=0 + autorestart=true diff --git a/.internal-ci/helm/mobilecoind/values.yaml b/.internal-ci/helm/mobilecoind/values.yaml new file mode 100644 index 0000000000..52adb53d5c --- /dev/null +++ b/.internal-ci/helm/mobilecoind/values.yaml @@ -0,0 +1,76 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +fullnameOverride: '' + +### mc-core-common-config child chart configuration. +# See ../mc-core-common-config for details. +mcCoreCommonConfig: + enabled: false + +### mobilecoind-config child chart configuration. +# See ../mc-core-common-config for details. +mobilecoindConfig: + enabled: false + +# Pods share the image tag. +image: + org: mobilecoin + tag: '' # Overrides the image tag whose default is the chart appVersion. + +imagePullSecrets: + - name: docker-credentials + +mobilecoind: + image: + org: '' + name: mobilecoind + + ingress: + annotations: + cert-manager.io/cluster-issuer: letsencrypt-production-http + haproxy.org/server-proto: "h2" # Force GRPC/H2 mode + haproxy.org/server-ssl: "false" # The backend (server) is http + haproxy.org/timeout-client: 239s # 4 min timeout on azure + haproxy.org/timeout-server: 239s + haproxy.org/timeout-http-keep-alive: 120s + haproxy.org/abortonclose: "true" + haproxy.org/backend-config-snippet: |- + http-reuse aggressive + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/backend-protocol: "GRPC" + + # TODO: enable persistence, need a pvc + # persistence: + # enabled: false + # spec: + # storageClassName: fast + # accessModes: + # - ReadWriteOnce + # resources: + # requests: + # storage: 128Gi + + initContainers: + - name: migrate-ledger + image: '{{ .Values.mobilecoind.image.org | default .Values.image.org }}/{{ .Values.mobilecoind.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' + imagePullPolicy: IfNotPresent + command: [ "/bin/bash" ] + args: + - -c + - | + set -x + if [ -f /mobilecoin/ledger/data.mdb ]; then + /usr/bin/mc-ledger-migration --ledger-db /data/ledger + fi + volumeMounts: + - name: data + mountPath: /data + + nodeSelector: {} + + podAnnotations: + fluentbit.io/include: 'true' # collect logs with fluentbit + fluentbit.io/exclude-jaeger-agent: 'true' + +jaegerTracing: + enabled: true + collector: 'dns:///jaeger-collector:14250' \ No newline at end of file diff --git a/.internal-ci/helm/watcher/Chart.yaml b/.internal-ci/helm/watcher/Chart.yaml new file mode 100644 index 0000000000..2a42f46f91 --- /dev/null +++ b/.internal-ci/helm/watcher/Chart.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +apiVersion: v2 +name: watcher +description: MobileCoin Consensus Watcher +type: application +version: 0.0.0 +appVersion: 0.0.0 diff --git a/.internal-ci/helm/watcher/templates/_helpers.tpl b/.internal-ci/helm/watcher/templates/_helpers.tpl new file mode 100644 index 0000000000..9d7ef2cd04 --- /dev/null +++ b/.internal-ci/helm/watcher/templates/_helpers.tpl @@ -0,0 +1,97 @@ +{{/* Copyright (c) 2018-2022 The MobileCoin Foundation */}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "chart.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "chart.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "chart.labels" -}} +helm.sh/chart: {{ include "chart.chart" . }} +{{ include "chart.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "chart.selectorLabels" -}} +app.kubernetes.io/name: {{ include "chart.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "chart.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "chart.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +IAS Secret Name +*/}} +{{- define "chart.iasSecretName" -}} + {{- if .Values.ias.secret.external }} + {{- .Values.ias.secret.name }} + {{- else }} + {{- include "chart.fullname" . }}-{{ .Values.ias.secret.name }} + {{- end }} +{{- end }} + +{{/* +Sentry ConfigMap Name +*/}} +{{- define "chart.sentryConfigMapName" -}} + {{- if .Values.sentry.configMap.external }} + {{- .Values.sentry.configMap.name }} + {{- else }} + {{- include "chart.fullname" . }}-{{ .Values.sentry.configMap.name }} + {{- end }} +{{- end }} + +{{/* +supervisord-mobilecoind ConfigMap Name +*/}} +{{- define "chart.mobilecoindConfigMapName" -}} + {{- if .Values.mobilecoind.configMap.external }} + {{- .Values.mobilecoind.configMap.name }} + {{- else }} + {{- include "chart.fullname" . }}-{{ .Values.mobilecoind.configMap.name }} + {{- end }} +{{- end }} diff --git a/.internal-ci/helm/watcher/templates/watcher-backup-scripts.yaml b/.internal-ci/helm/watcher/templates/watcher-backup-scripts.yaml new file mode 100644 index 0000000000..9498114f14 --- /dev/null +++ b/.internal-ci/helm/watcher/templates/watcher-backup-scripts.yaml @@ -0,0 +1,94 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if eq .Values.watcher.backupEnabled true }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "chart.fullname" . }}-watcher-backup-scripts + labels: + {{- include "chart.labels" . | nindent 4 }} +data: + backup.sh: | + #!/bin/bash + set -e + + YEAR=$(date '+%Y') + MONTH=$(date '+%m') + DAY=$(date '+%d') + HOUR=$(date '+%H') + MINUTE=$(date '+%M') + SECOND=$(date '+%S') + + BACKUP_FILEPATH="watcher/db-backup/${WATCHER_NETWORK}/${WATCHER_REGION_ID}/${WATCHER_INSTANCE_NAME}/${YEAR}/${MONTH}/${DAY}/backup-${YEAR}${MONTH}${DAY}${HOUR}${MINUTE}${SECOND}-data.mdb" + LATEST_FILEPATH="watcher/db-backup/${WATCHER_NETWORK}/${WATCHER_REGION_ID}/${WATCHER_INSTANCE_NAME}/latest-backup-data.mdb" + + AWS="aws" + if [ -n "${AWS_ENDPOINT_URL}" ]; then + AWS="aws --endpoint-url ${AWS_ENDPOINT_URL}" + fi + + # Don't compete with an alredy-running backup + PIDFILE="/var/run/watcherdb-backup.pid" + if [ -f ${PIDFILE} ]; then + echo "Current backup already running. Exiting." + exit 0 + fi + + # Check that the db file exists + if [ ! -f /watcher/data.mdb ]; then + echo "Database file does not exist" + exit 0 + fi + + trap "rm -f ${PIDFILE}" EXIT + + # Create pidfile for lock + echo $$ > ${PIDFILE} + echo "$(date) S3 backup storage path: s3://${AWS_BUCKET}/${BACKUP_FILEPATH}" + echo "$(date) S3 latest storage path: s3://${AWS_BUCKET}/${LATEST_FILEPATH}" + + # Set sha256 signing + ${AWS} configure set default payload_signing_enabled=true + + # Copy the db file for stable upload + cp /watcher/data.mdb /tmp/data.mdb + + # Copy to S3 + ${AWS} s3 cp /tmp/data.mdb s3://${AWS_BUCKET}/${BACKUP_FILEPATH} + ${AWS} s3 cp /tmp/data.mdb s3://${AWS_BUCKET}/${LATEST_FILEPATH} + + restore.sh: | + #!/bin/bash + set -e + + LATEST_FILEPATH="watcher/db-backup/${WATCHER_NETWORK}/${WATCHER_REGION_ID}/${WATCHER_INSTANCE_NAME}/latest-backup-data.mdb" + + AWS="aws" + if [ -n "${AWS_ENDPOINT_URL}" ]; then + AWS="aws --endpoint-url ${AWS_ENDPOINT_URL}" + fi + + # Don't compete with an alredy-running backup + PIDFILE="/var/run/watcherdb-restore.pid" + if [ -f ${PIDFILE} ]; then + echo "Current restore already running. Exiting." + exit 0 + fi + + # Don't restore if the database already exists + if [ -f /watcher/data.mdb ]; then + echo "Database file does already exists" + exit 0 + fi + + trap "rm -f ${PIDFILE}" EXIT + + # Create pidfile for lock + echo $$ > ${PIDFILE} + echo "$(date) S3 latest storage path: s3://${AWS_BUCKET}/${LATEST_FILEPATH}" + + # Set sha256 signing + ${AWS} configure set default payload_signing_enabled=true + + # Copy from S3 + ${AWS} s3 cp s3://${AWS_BUCKET}/${LATEST_FILEPATH} /watcher/data.mdb +{{- end }} \ No newline at end of file diff --git a/.internal-ci/helm/watcher/templates/watcher-config.yaml b/.internal-ci/helm/watcher/templates/watcher-config.yaml new file mode 100644 index 0000000000..2e0943be1a --- /dev/null +++ b/.internal-ci/helm/watcher/templates/watcher-config.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- $peers := $.Values.consensusPeers }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "chart.fullname" . }}-config-watcher + labels: + {{- include "chart.labels" . | nindent 4 }} +data: + sources.toml: | +{{- range $peers }} + [[sources]] + tx_source_url = "{{ .ledgerArchiveLocation }}" +{{- if .loadBalanced }} + consensus_client_url = "mc://{{ .clientHostname }}:{{ .clientPort }}/?responder-id={{ $.Values.loadBalancedConsensusHostname }}:{{ $.Values.loadBalancedConsensusPort }}" +{{- else }} + consensus_client_url = "mc://{{ .clientHostname }}:{{ .clientPort }}/" +{{- end }} +{{- end }} \ No newline at end of file diff --git a/.internal-ci/helm/watcher/templates/watcher-deployment.yaml b/.internal-ci/helm/watcher/templates/watcher-deployment.yaml new file mode 100644 index 0000000000..992e313d30 --- /dev/null +++ b/.internal-ci/helm/watcher/templates/watcher-deployment.yaml @@ -0,0 +1,159 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- range .Values.watcher.instances }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .watchername }}-{{ include "chart.fullname" $ }} + labels: + app: watcher + instance: {{ .watchername }} + {{- include "chart.labels" $ | nindent 4 }} +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: watcher + instance: {{ .watchername }} + {{- include "chart.selectorLabels" $ | nindent 6 }} + template: + metadata: + annotations: + {{- toYaml .Values.watcher.podAnnotations | nindent 8 }} + labels: + app: watcher + instance: {{ .watchername }} + {{- include "chart.labels" $ | nindent 8 }} + spec: + nodeSelector: + {{- toYaml $.Values.watcherNodeSelector | nindent 8 }} + imagePullSecrets: + {{- toYaml $.Values.imagePullSecrets | nindent 8 }} +{{- if eq $.Values.watcher.backupEnabled true }} + initContainers: + - name: watcherdb-restore + image: "amazon/aws-cli:2.0.19" + imagePullPolicy: IfNotPresent + command: [ "/bin/bash" ] + env: +{{- if .s3EndpointUrl }} + - name: AWS_ENDPOINT_URL + value: {{ .s3EndpointUrl }} +{{- end }} + - name: AWS_REGION + value: {{ .s3Region }} + - name: AWS_BUCKET + value: {{ .s3Bucket }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .watchername }}-{{ include "chart.fullname" $ }}-s3-bucket-credentials + key: aws-access-key-id + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .watchername }}-{{ include "chart.fullname" $ }}-s3-bucket-credentials + key: aws-secret-access-key + - name: WATCHER_INSTANCE_NAME + value: {{ .watchername }} + - name: WATCHER_NETWORK + value: {{ $.Values.networkname }} + - name: WATCHER_REGION_ID + value: {{ .watcherRegionId }} + args: + - -c + - | + set -ex + if [ ! -f /watcher/data.mdb ]; then + /scripts/restore.sh + fi + volumeMounts: + - name: watcher-db-dir + mountPath: /watcher + - name: watcher-backup-scripts + mountPath: /scripts +{{- end}} + containers: + - name: watcher + image: mobilecoin/watcher:{{ $.Values.images.tag }} + imagePullPolicy: IfNotPresent + command: ["/usr/bin/mc-watcher", "--watcher-db", "/watcher", "--sources-path", "/config/sources.toml", "--store-block-data"] + ports: + - name: watcher-mgmt + containerPort: 8000 + env: + - name: "RUST_BACKTRACE" + value: "full" + - name: "RUST_LOG" + value: "info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error" + volumeMounts: + - name: watcher-db-dir + mountPath: /watcher + - name: config + mountPath: /config +{{- if eq $.Values.watcher.backupEnabled true }} + - name: watcherdb-backup + image: "amazon/aws-cli:2.0.19" + imagePullPolicy: IfNotPresent + command: [ "/bin/bash" ] + env: +{{- if .s3EndpointUrl }} + - name: AWS_ENDPOINT_URL + value: {{ .s3EndpointUrl }} +{{- end }} + - name: AWS_REGION + value: {{ .s3Region }} + - name: AWS_BUCKET + value: {{ .s3Bucket }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .watchername }}-{{ include "chart.fullname" $ }}-s3-bucket-credentials + key: aws-access-key-id + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .watchername }}-{{ include "chart.fullname" $ }}-s3-bucket-credentials + key: aws-secret-access-key + - name: WATCHER_INSTANCE_NAME + value: {{ .watchername }} + - name: WATCHER_NETWORK + value: {{ $.Values.networkname }} + - name: WATCHER_REGION_ID + value: {{ .watcherRegionId }} + args: + - -c + - | + set -e + while true; do /scripts/backup.sh ; sleep 3600; done + lifecycle: + preStop: + exec: + command: ["/bin/sh","-c","/scripts/backup.sh"] + volumeMounts: + - name: watcher-db-dir + mountPath: /watcher + - name: watcher-backup-scripts + mountPath: /scripts +{{- end }} + volumes: + - name: watcher-db-dir +{{- if eq $.Values.watcher.persistenceEnabled true }} + persistentVolumeClaim: + claimName: {{ .watchername }}-{{ include "chart.fullname" $ }}-data +{{- else }} + emptyDir: {} +{{- end }} + - name: config + configMap: + name: {{ include "chart.fullname" $ }}-config-watcher +{{- if eq $.Values.watcher.backupEnabled true }} + - name: watcher-backup-scripts + configMap: + name: {{ include "chart.fullname" $ }}-watcher-backup-scripts + defaultMode: 0755 +{{- end }} +--- +{{- end }} + diff --git a/.internal-ci/helm/watcher/templates/watcher-s3-credentials-secret.yaml b/.internal-ci/helm/watcher/templates/watcher-s3-credentials-secret.yaml new file mode 100644 index 0000000000..49d4051042 --- /dev/null +++ b/.internal-ci/helm/watcher/templates/watcher-s3-credentials-secret.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if eq .Values.watcher.backupEnabled true }} +{{- range .Values.watcher.instances }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .watchername }}-{{ include "chart.fullname" $ }}-s3-bucket-credentials + labels: + {{- include "chart.labels" $ | nindent 4 }} +type: Opaque +data: + aws-access-key-id: "{{ .awsAccessKeyId | b64enc}}" + aws-secret-access-key: "{{ .awsSecretAccessKey | b64enc }}" +--- +{{- end }} +{{- end }} diff --git a/.internal-ci/helm/watcher/templates/watcher-service.yaml b/.internal-ci/helm/watcher/templates/watcher-service.yaml new file mode 100644 index 0000000000..a087a126c1 --- /dev/null +++ b/.internal-ci/helm/watcher/templates/watcher-service.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- range .Values.instances }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .watchername }}-{{ include "chart.fullname" . }} + labels: + {{- include "chart.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + app: watcher + instance: {{ .watchername }} + ports: + - name: watcher-rpc + port: 3229 +--- +{{- end }} diff --git a/.internal-ci/helm/watcher/templates/watcher-volume.yaml b/.internal-ci/helm/watcher/templates/watcher-volume.yaml new file mode 100644 index 0000000000..502f87a601 --- /dev/null +++ b/.internal-ci/helm/watcher/templates/watcher-volume.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +{{- if eq .Values.watcher.persistenceEnabled true }} +{{- range .Values.watcher.instances }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .watchername }}-{{ include "chart.fullname" $ }}-data + labels: + {{- include "chart.labels" $ | nindent 4 }} +spec: + storageClassName: {{ $.Values.watcher.storageClass }} + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 512Gi +--- +{{- end }} +{{- end }} diff --git a/.internal-ci/helm/watcher/values.yaml b/.internal-ci/helm/watcher/values.yaml new file mode 100644 index 0000000000..f947fc8e5c --- /dev/null +++ b/.internal-ci/helm/watcher/values.yaml @@ -0,0 +1,37 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +images: + tag: "" + +consensusPeers: [] + # - peerHostname: peer1.test.example.com + # clientHostname: client1.test.example.com + # peerPort: 443 + # clientPort: 443 + # signerPublicKey: public-key + # ledgerArchiveLocation: https://s3-location-hostname/ledger/peer1.test.example.com + +imagePullSecrets: [] + # - name: "credentials" + +watcher: + backupEnabled: false + persistenceEnabled: false + storageClass: "" + instances: [] + # - watchername: watcher1 + # s3Bucket: bucket-name + # awsAccessKeyId: access-key-id-string + # awsSecretAccessKey: secret-access-key-string + # s3Region: eu-central-1 + # s3EndpointUrl: "http://your-s3-server:5555" + # watcherRegionId: aws-eu-central-1 + # - watchername: watcher2 + # s3Bucket: bucket-name + # awsAccessKeyId: access-key-id-string + # awsSecretAccessKey: secret-access-key-string + # s3Region: eu-central-1 + # watcherRegionId: aws-eu-central-1 + podAnnotations: + fluentbit.io/include: 'true' # collect logs with fluentbit + +watcherNodeSelector: {} \ No newline at end of file diff --git a/.internal-ci/sample_data/ledger/.keep b/.internal-ci/sample_data/ledger/.keep new file mode 100644 index 0000000000..f42724f8c3 --- /dev/null +++ b/.internal-ci/sample_data/ledger/.keep @@ -0,0 +1 @@ +keep this directory/structure so we can build consensus node_hw dockerfile without a integrated origin ledger. \ No newline at end of file diff --git a/.internal-ci/test/fog-distribution-test.sh b/.internal-ci/test/fog-distribution-test.sh new file mode 100755 index 0000000000..be890078bb --- /dev/null +++ b/.internal-ci/test/fog-distribution-test.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Wrapper around fog-distribution binary to add some simple checks and clean defaults. +# + +set -e + +run_file=/var/tmp/.fog-distribution-already-ran + +if [ -f "${run_file}" ] +then + echo "-- Cowardly refusing to run fog-distribution a second time." + exit 0 +fi + +touch "${run_file}" + +fog-distribution --sample-data-dir /tmp/sample_data \ + --peer "mc://node1.${NAMESPACE}.development.mobilecoin.com:443" \ + --peer "mc://node2.${NAMESPACE}.development.mobilecoin.com:443" \ + --peer "mc://node3.${NAMESPACE}.development.mobilecoin.com:443" \ + --num-tx-to-send 20 + + +# assumes +# /tmp/sample_data/keys - path to init keys where funds are coming from +# /tmp/sample_data/fog_keys - path to destination keys diff --git a/.internal-ci/test/fog-test-client.sh b/.internal-ci/test/fog-test-client.sh new file mode 100755 index 0000000000..4af3fecd20 --- /dev/null +++ b/.internal-ci/test/fog-test-client.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Wrapper around fog test-client binary to set up environment for testing. +# + +set -e + +usage() +{ + echo "Usage --key-dir --token-id " + echo " --key-dir - source keys directory (keys to test)" + echo " --token-id - token id to transfer" +} + +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) +do + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --key-dir ) + key_dir="${2}" + shift 2 + ;; + --token-id ) + token_id="${2}" + shift 2 + ;; + *) + echo "${1} unknown option" + usage + exit 1 + ;; + esac +done + +is_set key_dir +is_set token_id +is_set NAMESPACE + +if [ -n "${CLIENT_AUTH_TOKEN_SECRET}" ] +then + echo "Generating Client Auth Creds" + pw=$(mc-util-grpc-token-generator --shared-secret "${CLIENT_AUTH_TOKEN_SECRET}" --username user1 | grep Password: | awk '{print $2}') + user="user1:${pw}@" +fi + +test_client \ + --key-dir "${key_dir}" \ + --consensus "mc://node1.${NAMESPACE}.development.mobilecoin.com/" \ + --consensus "mc://node2.${NAMESPACE}.development.mobilecoin.com/" \ + --consensus "mc://node3.${NAMESPACE}.development.mobilecoin.com/" \ + --token-id "${token_id}" \ + --num-clients 6 \ + --num-transactions 32 \ + --consensus-wait 300 \ + --transfer-amount 20 \ + --fog-view "fog-view://${user}fog.${NAMESPACE}.development.mobilecoin.com:443" \ + --fog-ledger "fog-ledger://${user}fog.${NAMESPACE}.development.mobilecoin.com:443" diff --git a/.internal-ci/test/mint-auditor-test.sh b/.internal-ci/test/mint-auditor-test.sh new file mode 100755 index 0000000000..90b3631273 --- /dev/null +++ b/.internal-ci/test/mint-auditor-test.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Wrapper around mint-auditor integration_test.py to set up environment for testing. +# + +set -e + +usage() +{ + echo "Usage --token-id " + echo " --token-id - token id to test" +} + +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) +do + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --token-id ) + token_id="${2}" + shift 2 + ;; + *) + echo "${1} unknown option" + usage + exit 1 + ;; + esac +done + +is_set token_id +is_set NAMESPACE + + +echo "-- Install python packages" +echo "" +pip3 install grpcio grpcio-tools + +echo "" +echo "-- Set up proto files" +echo "" + +pushd /test/mint-auditor || exit 1 + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + --python_out=. \ + "/proto/api/external.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + --python_out=. \ + "/proto/api/blockchain.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + -I"/proto/mobilecoind" \ + -I"/proto/consensus" \ + --python_out=. --grpc_python_out=. \ + "/proto/mobilecoind/mobilecoind_api.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/mint-auditor" \ + --python_out=. --grpc_python_out=. \ + "/proto/mint-auditor/mint_auditor.proto" + +echo "" +echo "-- Run integration_test.py" +echo "" +token_signer_key="/minting-keys/token${token_id}_signer.private.pem" + +python3 integration_test.py \ + --mobilecoind-addr "mobilecoind:3229" \ + --mint-auditor-addr "mobilecoind-mint-auditor:7774" \ + --mint-client-bin /usr/local/bin/mc-consensus-mint-client \ + --node-url "mc://node1.${NAMESPACE}.development.mobilecoin.com/" \ + --mint-signing-key "${token_signer_key}" + +popd >/dev/null || exit 1 diff --git a/.internal-ci/test/minting-config-tx-test.sh b/.internal-ci/test/minting-config-tx-test.sh new file mode 100755 index 0000000000..3bdad0db12 --- /dev/null +++ b/.internal-ci/test/minting-config-tx-test.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Wrapper around mc-consensus-mint-client to set up environment for testing. +# + +set -e + +usage() +{ + echo "Usage --token-id " + echo " --token-id - token id to transfer" +} + +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) +do + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --token-id ) + token_id="${2}" + shift 2 + ;; + *) + echo "${1} unknown option" + usage + exit 1 + ;; + esac +done + +is_set token_id +is_set NAMESPACE + +# These should be populated by volume in toolbox container. +governor_signer_key="/minting-keys/minter${token_id}_governor.private.pem" +token_signer_key="/minting-keys/token${token_id}_signer.public.pem" + +mc-consensus-mint-client generate-and-submit-mint-config-tx \ + --node "mc://node1.${NAMESPACE}.development.mobilecoin.com/" \ + --signing-key "${governor_signer_key}" \ + --token-id "${token_id}" \ + --config "1000000000:${token_id}:${token_signer_key}" \ + --total-mint-limit 10000000000 + +echo "-- sleep and wait for tx/blocks to sync" +sleep 15 diff --git a/.internal-ci/test/minting-tx-test.sh b/.internal-ci/test/minting-tx-test.sh new file mode 100755 index 0000000000..2539b89d03 --- /dev/null +++ b/.internal-ci/test/minting-tx-test.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Wrapper around mc-consensus-mint-client binary to set up environment for testing. +# + +set -e + +usage() +{ + echo "Usage --key-dir --token-id " + echo " --key-dir - source keys directory (keys to test)" + echo " --token-id - token id to transfer" +} + +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) +do + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --key-dir ) + key_dir="${2}" + shift 2 + ;; + --token-id ) + token_id="${2}" + shift 2 + ;; + *) + echo "${1} unknown option" + usage + exit 1 + ;; + esac +done + +is_set key_dir +is_set token_id +is_set NAMESPACE + +# These should be populated by volume in toolbox container. +token_signer_key="/minting-keys/token${token_id}_signer.private.pem" + +keys=$(find "${key_dir}" -name "*.b58pub") + +if [[ -z "${keys}" ]] +then + echo "-- Error: no b58pub keys found" + exit 1 +fi + +# For each b58pub in key dir run a mint-tx +for k in ${keys} +do + echo "-- sending mint tx for account key ${k}" + + mc-consensus-mint-client generate-and-submit-mint-tx \ + --node "mc://node1.${NAMESPACE}.development.mobilecoin.com/" \ + --signing-key "${token_signer_key}" \ + --recipient "$(cat "${k}")" \ + --token-id "${token_id}" \ + --amount 1000000 + + sleep 10 +done diff --git a/.internal-ci/test/mobilecoind-integration-test.sh b/.internal-ci/test/mobilecoind-integration-test.sh new file mode 100755 index 0000000000..51403a737c --- /dev/null +++ b/.internal-ci/test/mobilecoind-integration-test.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Wrapper around the mobilecoind test_client.py to set up environment for testing. +# + +set -e + +strategies_dir=/tmp/mobilecoind/strategies +keys_dir="${strategies_dir}/keys" + +mkdir -p "${keys_dir}" + +echo "-- Copy account keys" +echo "" +for i in {0..4} +do + # shellcheck disable=SC2086 + cp /tmp/sample_data/keys/*_${i}.* "${keys_dir}" +done + +cp /test/mobilecoind/strategies/* "${strategies_dir}" + +pushd "${strategies_dir}" >/dev/null || exit 1 + +echo "-- Install requirements" +echo "" +pip3 install -r requirements.txt + +echo "" +echo "-- Set up proto files" +echo "" + +if [[ -f "/proto/api/external.proto" ]] +then + python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + --python_out=. "/proto/api/external.proto" +fi + +if [[ -f "/proto/api/blockchain.proto" ]] +then + python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + --python_out=. "/proto/api/blockchain.proto" +fi + +if [[ -f "/proto/mobilecoind/mobilecoind_api.proto" ]] +then + python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + -I"/proto/mobilecoind" \ + -I"/proto/consensus" \ + --python_out=. --grpc_python_out=. "/proto/mobilecoind/mobilecoind_api.proto" +fi + +echo "" +echo "-- Run test_client.py" +echo "" +python3 test_client.py \ + --key-dir "${keys_dir}" \ + --mobilecoind-host "mobilecoind" \ + --mobilecoind-port 3229 + +popd >/dev/null || exit 1 diff --git a/.internal-ci/test/mobilecoind-json-integration-test.sh b/.internal-ci/test/mobilecoind-json-integration-test.sh new file mode 100755 index 0000000000..c227eae572 --- /dev/null +++ b/.internal-ci/test/mobilecoind-json-integration-test.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Wrapper around the mobilecoind-json integration_test.py to set up environment for testing. +# + +set -e +usage() +{ + echo "Usage --key-dir " + echo " --key-dir - source keys directory (keys to test)" +} + +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) +do + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --key-dir ) + key_dir="${2}" + shift 2 + ;; + *) + echo "${1} unknown option" + usage + exit 1 + ;; + esac +done + +is_set key_dir +is_set NAMESPACE + +# This uses some of the same lib py files as mobilecoind tests. +strategies_dir=/tmp/mobilecoind-json/strategies +mkdir -p "${strategies_dir}" +cp /test/mobilecoind/strategies/* "${strategies_dir}" + +pushd "${strategies_dir}" >/dev/null || exit 1 + +echo "-- Install requirements" +echo "" +pip3 install -r requirements.txt + +echo "" +echo "-- Set up proto files" +echo "" + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + --python_out=. \ + "/proto/api/external.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + --python_out=. \ + "/proto/api/blockchain.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + -I"/proto/mobilecoind" \ + -I"/proto/consensus" \ + --python_out=. --grpc_python_out=. \ + "/proto/mobilecoind/mobilecoind_api.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/mint-auditor" \ + --python_out=. --grpc_python_out=. \ + "/proto/mint-auditor/mint_auditor.proto" + +echo "" +echo "-- Run integration_test.py" +echo "" +python3 /test/mobilecoind-json/integration_test.py \ + --key-dir "${key_dir}" \ + --mobilecoind-json-url http://mobilecoind-json:9090 + +popd >/dev/null || exit 1 diff --git a/.internal-ci/util/copy_account_keys.sh b/.internal-ci/util/copy_account_keys.sh new file mode 100755 index 0000000000..e51fc1cb36 --- /dev/null +++ b/.internal-ci/util/copy_account_keys.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Copy a set of keys from one folder to another - useful for grabbing a subset of keys for drain/test tools. +# + +set -e + +usage() +{ + echo "Usage:" + echo "${0} --src /tmp/sample_keys/keys --dst /tmp/smaller_key_set --start 0 --end 6" + echo " --src - source keys directory (keys to drain)" + echo " --dst - destination keys directory (keys to fund)" + echo " --start - key number to start" + echo " --end - key number to end" +} + +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) +do + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --src ) + src="${2}" + shift 2 + ;; + --dst ) + dst="${2}" + shift 2 + ;; + --start ) + start="${2}" + shift 2 + ;; + --end ) + end="${2}" + shift 2 + ;; + *) + break + ;; + esac +done + +is_set src +is_set dst +is_set start +is_set end + +num_of_keys=$((end - start + 1)) + +mkdir -p "${dst}" + +echo "-- Copy ${num_of_keys} account keys from ${src} to ${dst}" +echo "" +for i in $(seq "${start}" "${end}") +do + echo "-- copy key ${i}" + find "${src}" -name "*_${i}.*" -exec cp {} "${dst}" \; +done diff --git a/.internal-ci/util/drain_accounts.sh b/.internal-ci/util/drain_accounts.sh new file mode 100755 index 0000000000..a621db74a8 --- /dev/null +++ b/.internal-ci/util/drain_accounts.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Wrapper around the mobilecoind drain-accounts.py to set up environment for testing. +# + +set -e + +usage() +{ + echo "Usage:" + echo "${0} --src --dst " + echo " --src - source keys directory (keys to drain)" + echo " --dst - destination keys directory (keys to fund)" + echo " --token-id - token id to transfer" +} + +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) +do + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --src ) + src="${2}" + shift 2 + ;; + --dst ) + dst="${2}" + shift 2 + ;; + --token-id ) + token_id="${2}" + shift 2 + ;; + --fee ) + fee="${2}" + shift 2 + ;; + *) + echo "${1} unknown option" + usage + ;; + esac +done + +is_set src +is_set dst +is_set token_id +is_set fee + +strategies_dir=/tmp/drain-accounts/strategies + +# This uses some of the same lib py files as mobilecoind tests. +mkdir -p "${strategies_dir}" +cp /test/mobilecoind/strategies/* "${strategies_dir}" + +pushd "${strategies_dir}" >/dev/null || exit 1 + +echo "-- Install requirements" +echo "" +pip3 install -r requirements.txt + +echo "" +echo "-- Set up proto files" +echo "" + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + --python_out=. \ + "/proto/api/external.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + --python_out=. \ + "/proto/api/blockchain.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/api" \ + -I"/proto/mobilecoind" \ + -I"/proto/consensus" \ + --python_out=. --grpc_python_out=. \ + "/proto/mobilecoind/mobilecoind_api.proto" + +python3 -m grpc_tools.protoc \ + -I"/proto/mint-auditor" \ + --python_out=. --grpc_python_out=. \ + "/proto/mint-auditor/mint_auditor.proto" + +echo "" +echo "-- Run integration_test.py" +echo "" +python3 drain-accounts.py \ + --key-dir "${src}" \ + --dest-key-dir "${dst}" \ + --mobilecoind-host "mobilecoind" \ + --mobilecoind-port 3229 \ + --token-id "${token_id}" \ + --fee "${fee}" + +popd >/dev/null || exit 1 diff --git a/.internal-ci/util/generate_dev_values.sh b/.internal-ci/util/generate_dev_values.sh new file mode 100755 index 0000000000..ba1136c92e --- /dev/null +++ b/.internal-ci/util/generate_dev_values.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Generates message signer keys and populates other variables. + +location=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +BASE_PATH=${BASE_PATH:-.tmp} + +# generate msg signer keys +declare -a signer_keys_pub +declare -a signer_keys_pri + +count=1 +while [ ${count} -le 5 ] +do + key=$("${location}/generate_ed25519_keys.sh") + signer_keys_pub+=("$(echo -n "${key}" | grep public | awk -F': ' '{print $2}')") + signer_keys_pri+=("$(echo -n "${key}" | grep private | awk -F': ' '{print $2}')") + ((count++)) +done + +# Get token config or set empty for older configs. +tokens_signed_json="{}" +if [[ -f "${BASE_PATH}/tokens.signed.json" ]] +then + tokens_signed_json=$(cat "${BASE_PATH}/tokens.signed.json") +fi + +cat << EOF +global: + node: + ledgerDistribution: + awsAccessKeyId: '${LEDGER_AWS_ACCESS_KEY_ID}' + awsSecretAccessKey: '${LEDGER_AWS_SECRET_ACCESS_KEY}' + + networkConfig: + peers: + 1: + signerPublicKey: ${signer_keys_pub[0]} + 2: + signerPublicKey: ${signer_keys_pub[1]} + 3: + signerPublicKey: ${signer_keys_pub[2]} + 4: + signerPublicKey: ${signer_keys_pub[3]} + 5: + signerPublicKey: ${signer_keys_pub[4]} + + tokensConfig: + tokensSignedJson: | +$(echo -n "${tokens_signed_json}" | sed 's/^/ /') + +mcCoreCommonConfig: + ipinfo: + token: '${IP_INFO_TOKEN}' + ias: + key: '${IAS_KEY}' + spid: '${IAS_SPID}' + clientAuth: + token: '${CLIENT_AUTH_TOKEN}' + sentry: + consensus-sentry-dsn: '${SENTRY_DSN_CONSENSUS}' + ledger-distribution-sentry-dsn: '${SENTRY_DSN_LEDGER_DISTRIBUTION}' + fog-report-sentry-dsn: '${SENTRY_DSN_FOG_INGEST}' + fog-view-sentry-dsn: '${SENTRY_DSN_FOG_VIEW}' + fog-ledger-sentry-dsn: '${SENTRY_DSN_FOG_LEDGER}' + fog-ingest-sentry-dsn: '${SENTRY_DSN_FOG_INGEST}' + +consensusNodeConfig1: + node: + msgSignerKey: + privateKey: ${signer_keys_pri[0]} + +consensusNodeConfig2: + node: + msgSignerKey: + privateKey: ${signer_keys_pri[1]} + +consensusNodeConfig3: + node: + msgSignerKey: + privateKey: ${signer_keys_pri[2]} + +consensusNodeConfig4: + node: + msgSignerKey: + privateKey: ${signer_keys_pri[3]} + +consensusNodeConfig5: + node: + msgSignerKey: + privateKey: ${signer_keys_pri[4]} + +fogServicesConfig: + fogReport: + signingCert: + key: |- +$(echo -n "${FOG_REPORT_SIGNING_CERT_KEY}" | sed 's/^/ /') + crt: |- +$(echo -n "${FOG_REPORT_SIGNING_CERT}" | sed 's/^/ /') + +EOF diff --git a/.internal-ci/util/generate_ed25519_keys.sh b/.internal-ci/util/generate_ed25519_keys.sh new file mode 100755 index 0000000000..fae678d746 --- /dev/null +++ b/.internal-ci/util/generate_ed25519_keys.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Script to generate ED25519 keys. +# consensus node message signer keys: +# echoes the private key in der form, and the public key in pem format. +# consensus node minting: +# use options to output pem files. + +set -e + +# we want header or no headers. +while (( "$#" )) +do + case "${1}" in + --help | -h) + echo "usage: ${0} [--public-out ] [--private-out ]" + exit 0 + ;; + # Path to public key + --public-out ) + public_out="${2}" + shift 2 + ;; + # Path to private key + --private-out ) + private_out="${2}" + shift 2 + ;; + *) + echo "${1} unknown option" + exit 1 + ;; + esac +done + +pri_pem=$(openssl genpkey -algorithm ED25519) +pub_pem=$(echo -n "${pri_pem}" | openssl pkey -pubout) + +if [[ -n "${private_out}" ]] +then + echo -n "${pri_pem}" > "${private_out}" +else + pri_der=$(echo -n "${pri_pem}" | openssl pkey -outform DER | openssl base64) + echo "private (DER base64): ${pri_der}" +fi + +if [[ -n "${public_out}" ]] +then + echo -n "${pub_pem}" > "${public_out}" +else + pub=$(echo -n "${pub_pem}" | grep -v "^-----" | sed 's/+/-/g; s/\//_/g') + echo "public (PEM w/o headers): ${pub}" +fi diff --git a/.internal-ci/util/generate_minting_keys.sh b/.internal-ci/util/generate_minting_keys.sh new file mode 100755 index 0000000000..eb3ead90e8 --- /dev/null +++ b/.internal-ci/util/generate_minting_keys.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Generate minting keys +# See for notes on what keys do what: +# https://www.notion.so/mobilecoin/Consensus-tokens-config-and-Minting-keys-45def9fb96ff4c41ba1ec513934c45a2 + +set -e + +location=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +BASE_PATH="${BASE_PATH:-.tmp/seeds/minting}" +mkdir -p "${BASE_PATH}" + +# Token 1 governor keys +# This key pair is used to validate MintConfigTxs +if [[ ! -f "${BASE_PATH}/minter1_governor.private.pem" ]] +then + "${location}/generate_ed25519_keys.sh" \ + --public-out "${BASE_PATH}/minter1_governor.public.pem" \ + --private-out "${BASE_PATH}/minter1_governor.private.pem" +else + echo "minter1_governor keys already exist" +fi +sha256sum "${BASE_PATH}/minter1_governor.private.pem" +sha256sum "${BASE_PATH}/minter1_governor.public.pem" + +# Token 1 signer keys +# This key pair is used to validate MintTX +if [[ ! -f "${BASE_PATH}/token_signer.private.pem" ]] +then + echo "Writing token1_signer keys" + "${location}/generate_ed25519_keys.sh" \ + --public-out "${BASE_PATH}/token1_signer.public.pem" \ + --private-out "${BASE_PATH}/token1_signer.private.pem" +else + echo "token1_signer keys already exist" +fi +sha256sum "${BASE_PATH}/token1_signer.private.pem" +sha256sum "${BASE_PATH}/token1_signer.public.pem" + +# Write minting trust root private key if its defined. +if [[ -n "${MINTING_TRUST_ROOT_PRIVATE}" ]] +then + echo "Writing minting_trust_root.private.pem" + echo "${MINTING_TRUST_ROOT_PRIVATE}" > "${BASE_PATH}/minting_trust_root.private.pem" + sha256sum "${BASE_PATH}/minting_trust_root.private.pem" +else + echo "MINTING_TRUST_ROOT_PRIVATE not defined" +fi diff --git a/.internal-ci/util/generate_origin_data.sh b/.internal-ci/util/generate_origin_data.sh new file mode 100755 index 0000000000..e340483c5a --- /dev/null +++ b/.internal-ci/util/generate_origin_data.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Generate ledger/data.mdb, initial/fog keys for development builds +# +# TODO: Restore ledger/data.mdb for persistent builds. + +set -e + +is_set() +{ + var_name="${1}" + + if [ -z "${!var_name}" ]; then + echo "${var_name} is not set." + exit 1 + fi +} + +BASE_PATH=${BASE_PATH:-/tmp} +is_set INITIAL_KEYS_SEED + +mkdir -p "${BASE_PATH}/sample_data/ledger" +mkdir -p "${BASE_PATH}/sample_data/keys" +mkdir -p "${BASE_PATH}/sample_data/fog_keys" +mkdir -p "${BASE_PATH}/sample_data/mnemonic_keys" +mkdir -p "${BASE_PATH}/sample_data/mnemonic_fog_keys" + +pushd "${BASE_PATH}/sample_data" > /dev/null || exit 1 + +echo "-- Generate initial keys" +/util/sample-keys.1.1.3 --num 1000 \ + --seed "${INITIAL_KEYS_SEED}" \ + --output-dir ./keys + +echo "-- Generate b58pub files for initial keys" +for i in {0..999} +do + read-pubfile --pubfile "./keys/account_keys_${i}.pub" \ + --out-b58 "./keys/account_keys_${i}.b58pub" >/dev/null 2>&1 +done + +if [[ "${INITIALIZE_LEDGER}" == "true" ]] +then + echo "" + echo "-- Initialize ledger" + generate-sample-ledger --txs 100 + rm -f ./ledger/lock.mdb +fi + +if [[ -n "${FOG_KEYS_SEED}" ]] +then + is_set FOG_REPORT_SIGNING_CA_CERT_PATH + is_set FOG_REPORT_URL + + echo "" + echo "-- Generate keys for fog-distribution" + + /util/sample-keys.1.1.3 --num 500 \ + --seed "${FOG_KEYS_SEED}" \ + --fog-report-url "${FOG_REPORT_URL}" \ + --fog-authority-root "${FOG_REPORT_SIGNING_CA_CERT_PATH}" \ + --output-dir ./fog_keys + + echo "-- Generate b58pub files for fog keys" + for i in {0..499} + do + read-pubfile --pubfile "./fog_keys/account_keys_${i}.pub" \ + --out-b58 "./fog_keys/account_keys_${i}.b58pub" >/dev/null 2>&1 + done +fi + +if [[ -n "${MNEMONIC_KEYS_SEED}" ]] +then + echo "" + echo "-- Generate mnemonic non-fog keys" + + sample-keys --num 6 \ + --seed "${MNEMONIC_KEYS_SEED}" \ + --output-dir ./mnemonic_keys +fi + +if [[ -n "${MNEMONIC_FOG_KEYS_SEED}" ]] +then + is_set FOG_REPORT_SIGNING_CA_CERT_PATH + is_set FOG_REPORT_URL + + echo "" + echo "-- Generate mnemonic fog keys" + + sample-keys --num 6 \ + --seed "${MNEMONIC_FOG_KEYS_SEED}" \ + --fog-report-url "${FOG_REPORT_URL}" \ + --fog-authority-root "${FOG_REPORT_SIGNING_CA_CERT_PATH}" \ + --output-dir ./mnemonic_fog_keys +fi + +popd > /dev/null || exit 1 diff --git a/.internal-ci/util/generate_tokens_config.sh b/.internal-ci/util/generate_tokens_config.sh new file mode 100755 index 0000000000..7e2a05c5c1 --- /dev/null +++ b/.internal-ci/util/generate_tokens_config.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Create tokens.json with generated governor keys. + +set -e + +exists() +{ + if [[ ! -f "${1}" ]] + then + echo "${1} doesn't exist" + exit 1 + fi +} + +location=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +BASE_PATH="${BASE_PATH:-.tmp}" +minting_path="${BASE_PATH}/seeds/minting" + +# check for required files +exists "${location}/tokens.base.json" + +exists "${minting_path}/minter1_governor.public.pem" +sha256sum "${minting_path}/minter1_governor.public.pem" + +exists "${minting_path}/minting_trust_root.private.pem" +sha256sum "${minting_path}/minting_trust_root.private.pem" + +# Grab base json +json=$(cat "${location}/tokens.base.json") + +# Set minter1 pub keys and threshold +minter1_governor=$(cat "${minting_path}/minter1_governor.public.pem") +json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == 1) | .governors.signers) |= \"${minter1_governor}\"") +json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == 1) | .governors.threshold) |= 1") + +#output unsigned tokens +echo "$json" | jq . > .tmp/tokens.json + +# Sign tokens file +echo "Signing tokens file" +mc-consensus-mint-client sign-governors --tokens "${BASE_PATH}/tokens.json" \ + --signing-key "${minting_path}/minting_trust_root.private.pem" \ + --output-json "${BASE_PATH}/tokens.signed.json" >/dev/null diff --git a/.internal-ci/util/generate_wallet_seeds.sh b/.internal-ci/util/generate_wallet_seeds.sh new file mode 100755 index 0000000000..e22cbab334 --- /dev/null +++ b/.internal-ci/util/generate_wallet_seeds.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Generate and output seeds for initial and fog wallets. +# Checks for to see if seed values exist. If not generate a random seed values. + +# CBB make this a loop instead of copy/paste key + +set -e + +gen_seed() +{ + openssl rand -hex 32 +} + +BASE_PATH="${BASE_PATH:-.tmp/seeds}" +mkdir -p "${BASE_PATH}" + +# if INITIAL_KEYS_SEED is set then use that. +if [[ -n "${INITIAL_KEYS_SEED}" ]] +then + echo "-- Using INITIAL_KEYS_SEED variable" +elif [[ ! -f "${BASE_PATH}/INITIAL_KEYS_SEED" ]] && [[ ! -s "${BASE_PATH}/INITIAL_KEYS_SEED" ]] +then + # we didn't find the seed value or existing files - so create them + echo "-- Create initial keys seed at ${BASE_PATH}/INITIAL_KEYS_SEED" + INITIAL_KEYS_SEED=$(gen_seed) +else + echo "-- Initial ${BASE_PATH}/INITIAL_KEYS_SEED already exists" + INITIAL_KEYS_SEED=$(cat "${BASE_PATH}/INITIAL_KEYS_SEED") +fi +# Write key +echo -n "${INITIAL_KEYS_SEED}" > "${BASE_PATH}/INITIAL_KEYS_SEED" + + +# if FOG_KEYS_SEED is set then use that. +if [[ -n "${FOG_KEYS_SEED}" ]] +then + echo "-- Using FOG_KEYS_SEED variable" +elif [[ ! -f "${BASE_PATH}/FOG_KEYS_SEED" ]] && [[ ! -s "${BASE_PATH}/FOG_KEYS_SEED" ]] +then + # we didn't find the seed value or existing files - so create them + echo "-- Create initial keys seed at ${BASE_PATH}/FOG_KEYS_SEED" + FOG_KEYS_SEED=$(gen_seed) +else + echo "-- Initial ${BASE_PATH}/FOG_KEYS_SEED already exists" + FOG_KEYS_SEED=$(cat "${BASE_PATH}/FOG_KEYS_SEED") +fi +# Write key +echo -n "${FOG_KEYS_SEED}" > "${BASE_PATH}/FOG_KEYS_SEED" + +# if MNEMONIC_KEYS_SEED is set then use that. +if [[ -n "${MNEMONIC_KEYS_SEED}" ]] +then + echo "-- Using MNEMONIC_KEYS_SEED variable" +elif [[ ! -f "${BASE_PATH}/MNEMONIC_KEYS_SEED" ]] && [[ ! -s "${BASE_PATH}/MNEMONIC_KEYS_SEED" ]] +then + # we didn't find the seed value or existing files - so create them + echo "-- Create initial keys seed at ${BASE_PATH}/MNEMONIC_KEYS_SEED" + MNEMONIC_KEYS_SEED=$(gen_seed) +else + echo "-- Initial ${BASE_PATH}/MNEMONIC_KEYS_SEED already exists" + MNEMONIC_KEYS_SEED=$(cat "${BASE_PATH}/MNEMONIC_KEYS_SEED") +fi +# Write key +echo -n "${MNEMONIC_KEYS_SEED}" > "${BASE_PATH}/MNEMONIC_KEYS_SEED" + +# if MNEMONIC_FOG_KEYS_SEED is set then use that. +if [[ -n "${MNEMONIC_FOG_KEYS_SEED}" ]] +then + echo "-- Using MNEMONIC_FOG_KEYS_SEED variable" +elif [[ ! -f "${BASE_PATH}/MNEMONIC_FOG_KEYS_SEED" ]] && [[ ! -s "${BASE_PATH}/MNEMONIC_FOG_KEYS_SEED" ]] +then + # we didn't find the seed value or existing files - so create them + echo "-- Create initial keys seed at ${BASE_PATH}/MNEMONIC_FOG_KEYS_SEED" + MNEMONIC_FOG_KEYS_SEED=$(gen_seed) +else + echo "-- Initial ${BASE_PATH}/MNEMONIC_FOG_KEYS_SEED already exists" + MNEMONIC_FOG_KEYS_SEED=$(cat "${BASE_PATH}/MNEMONIC_FOG_KEYS_SEED") +fi +# Write key +echo -n "${MNEMONIC_FOG_KEYS_SEED}" > "${BASE_PATH}/MNEMONIC_FOG_KEYS_SEED" + +# Echo checksum +echo "--- initial_keys_seed sha256 ---" +sha256sum "${BASE_PATH}/INITIAL_KEYS_SEED" + +echo "--- fog_keys_seed sha256 ---" +sha256sum "${BASE_PATH}/FOG_KEYS_SEED" + +echo "--- mnemonic_keys_seed sha256 ---" +sha256sum "${BASE_PATH}/MNEMONIC_KEYS_SEED" + +echo "--- mnemonic_fog_keys_seed sha256 ---" +sha256sum "${BASE_PATH}/MNEMONIC_FOG_KEYS_SEED" diff --git a/.internal-ci/util/manual_republish_existing_build.sh b/.internal-ci/util/manual_republish_existing_build.sh new file mode 100755 index 0000000000..bd5971fd44 --- /dev/null +++ b/.internal-ci/util/manual_republish_existing_build.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# This script will grab binaries from an existing build and rebuild +# the containers/charts with the current configuration. +# Use with caution. + +set -e +set -x + +echo "no foot-guns, check the tag vars and remove this exit 0 to use!" +exit 0 + +source_org=mobilecoin +source_tag=demo-v20220307170316 + +push_org=mobilecoin +push_tag=v1.1.3-dev + +images=(bootstrap-tools fogingest fog-ledger fogreport fogview go-grpc-gateway mobilecoind node_hw fog-test-client) + +charts=(consensus-node consensus-node-config fog-ingest fog-ingest-config fog-services fog-services-config mc-core-common-config mc-core-dev-env-setup mobilecoind ) + +for i in "${images[@]}" +do + docker rm "${i}" || true + docker pull "${source_org}/${i}:${source_tag}" + docker create --name "${i}" "${source_org}/${i}:${source_tag}" +done + +mkdir -p target/release +pushd target/release || exit 1 +docker cp "bootstrap-tools:/usr/local/bin/fog-sql-recovery-db-migrations" ./ +docker cp "bootstrap-tools:/usr/local/bin/generate-sample-ledger" ./ +docker cp "bootstrap-tools:/usr/local/bin/sample-keys" ./ +docker cp "bootstrap-tools:/usr/local/bin/fog-distribution" ./ +docker cp "bootstrap-tools:/usr/local/bin/fog_ingest_client" ./ +# docker cp "bootstrap-tools:/usr/local/bin/mc-consensus-mint-client" ./ +# docker cp "bootstrap-tools:/usr/local/bin/mc-util-seeded-ed25519-key-gen" ./ +docker cp "fog-ledger:/usr/bin/libledger-enclave.signed.so" ./ +docker cp "fog-ledger:/usr/bin/ledger_server" ./ +docker cp "fog-ledger:/usr/bin/mobilecoind" ./ +docker cp "fog-ledger:/usr/bin/mc-admin-http-gateway" ./ +docker cp "fog-ledger:/usr/bin/mc-ledger-migration" ./ +docker cp "fog-ledger:/usr/bin/mc-util-grpc-admin-tool" ./ +docker cp "fogingest:/usr/bin/libingest-enclave.signed.so" ./ +docker cp "fogingest:/usr/bin/fog_ingest_server" ./ +docker cp "fogreport:/usr/bin/report_server" ./ +docker cp "fogview:/usr/bin/libview-enclave.signed.so" ./ +docker cp "fogview:/usr/bin/fog_view_server" ./ +docker cp "go-grpc-gateway:/usr/bin/go-grpc-gateway" ./grpc-proxy +docker cp "node_hw:/usr/bin/consensus-service" ./ +docker cp "node_hw:/usr/bin/ledger-distribution" ./ +docker cp "node_hw:/usr/bin/ledger-from-archive" ./ +docker cp "node_hw:/usr/bin/libconsensus-enclave.signed.so" ./ +docker cp "fog-test-client:/usr/local/bin/test_client" ./ +docker cp "fog-test-client:/usr/local/bin/mc-util-grpc-token-generator" ./ +popd || exit 1 + +for i in "${images[@]}" +do + docker build -t "${push_org}/${i}:${push_tag}" \ + --build-arg="GO_BIN_PATH=target/release" \ + --build-arg="REPO_ORG=${push_org}" \ + -f ".internal-ci/docker/Dockerfile.${i}" \ + . +done + +for i in "${images[@]}" +do + docker push "${push_org}/${i}:${push_tag}" +done + +mkdir -p ".tmp/charts" + +for c in "${charts[@]}" +do + helm dependency update ".internal-ci/helm/${c}" + helm package ".internal-ci/helm/${c}" \ + -d ".tmp/charts" \ + --app-version="${push_tag}" \ + --version="${push_tag}" +done + +for c in "${charts[@]}" +do + # helm repo add mcf-public --username \ + # https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + helm cm-push --force ".tmp/charts/${c}-${push_tag}.tgz" mcf-public +done diff --git a/.internal-ci/util/metadata.sh b/.internal-ci/util/metadata.sh new file mode 100755 index 0000000000..8e89ef6395 --- /dev/null +++ b/.internal-ci/util/metadata.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Generate metadata for GitHub Actions workflows. +# + +set -e + +export TMPDIR=".tmp" + +error_exit() +{ + msg="${1}" + + echo "${msg}" 1>&2 + exit 1 +} + +is_set() +{ + var_name="${1}" + + if [ -z "${!var_name}" ]; then + error_exit "${var_name} is not set." + fi +} + +# check for github reference variables. +is_set GITHUB_REF_NAME +is_set GITHUB_REF_TYPE +is_set GITHUB_RUN_NUMBER +is_set GITHUB_SHA + +if [[ "${GITHUB_REF_TYPE}" != "branch" ]] +then + echo "not a 'branch' reference type - ${GITHUB_REF_TYPE}" + exit 1 +fi + +# Remove leading branch designator. +branch=$(echo "${GITHUB_REF_NAME}" | sed -E 's/(feature|deploy|release)\///') + +if [[ "${GITHUB_REF_NAME}" =~ ^release/ ]] +then + echo "Release Branch detected: ${GITHUB_REF_NAME}" + version="${branch}" + # check to see if remaining version is basic semver + if [[ ! "${version}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] + then + echo "release/ not basic semver: ${version}" + echo "branch name invalid" + exit 1 + fi +else + version="v0.0.0" + echo "Not a release branch, set default version of v0.0.0" +fi + +echo "Clean up branch. Remove feature|deploy|release prefix and replace ._/ with - '${branch}'" +branch=$(echo "${branch}" | sed -e 's/[._/]/-/g') +sha="${GITHUB_SHA:0:8}" + +# Set tag/docker_tag +tag="${version}-${branch}.${GITHUB_RUN_NUMBER}.sha-${sha}" +docker_tag="type=raw,value=${tag}" + +# override tag/docker_tag for release +if [[ "${GITHUB_REF_NAME}" =~ ^release/ ]] +then + docker_tag="type=raw,value=${version}-dev,priority=20%0Atype=raw,value=${version}-${GITHUB_RUN_NUMBER}.sha-${sha},priority=10" + tag=${version}-dev +fi + +# Get commit flags +if [ -f "${GITHUB_EVENT_PATH}" ] +then + # override tag if commit message has [tag="tag"] + msg=$(jq -r '.head_commit.message' < "${GITHUB_EVENT_PATH}") + if [[ "${msg}" =~ /\[tag=.*\]/ ]] + then + tag=$(echo "${msg}" | sed -r 's/.*\[use=(.*)\].*/\1/') + fi +fi + +echo "::set-output name=version::${version}" +echo "::set-output name=branch::${branch}" +echo "::set-output name=namespace::mc-${branch}" +echo "::set-output name=sha::${sha}" +echo "::set-output name=tag::${tag}" +echo "::set-output name=docker_tag::${docker_tag}" diff --git a/.internal-ci/util/print_details.sh b/.internal-ci/util/print_details.sh new file mode 100755 index 0000000000..2a1dd3f302 --- /dev/null +++ b/.internal-ci/util/print_details.sh @@ -0,0 +1,126 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Print generated development environment details. +# +cat << EOF +--- Namespace --- + +${NAMESPACE} + +--- Version --- + +${VERSION} + +--- Dev Environment Logs --- + +https://kibana.logit.io/app/kibana#/discover?_g=()&_a=(columns:!(_source),filters:!(('\$state':(store:appState),meta:(alias:!n,disabled:!f,index:'8ac115c0-aac1-11e8-88ea-0383c11b333c',key:azure.subscription,negate:!f,params:(query:development,type:phrase),type:phrase,value:development),query:(match:(azure.subscription:(query:development,type:phrase)))),('\$state':(store:appState),meta:(alias:!n,disabled:!f,index:'8ac115c0-aac1-11e8-88ea-0383c11b333c',key:kubernetes.namespace_name,negate:!f,params:(query:${NAMESPACE},type:phrase),type:phrase,value:${NAMESPACE}),query:(match:(kubernetes.namespace_name:(query:${NAMESPACE},type:phrase))))),index:'8ac115c0-aac1-11e8-88ea-0383c11b333c',interval:auto,query:(language:kuery,query:''),sort:!('@timestamp',desc)) + +--- Consensus Endpoints --- + +node1.${NAMESPACE}.development.mobilecoin.com +node2.${NAMESPACE}.development.mobilecoin.com +node3.${NAMESPACE}.development.mobilecoin.com +node4.${NAMESPACE}.development.mobilecoin.com +node5.${NAMESPACE}.development.mobilecoin.com + +--- Consensus S3 Buckets --- + +https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node1.${NAMESPACE}.development.mobilecoin.com/ +https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node2.${NAMESPACE}.development.mobilecoin.com/ +https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node3.${NAMESPACE}.development.mobilecoin.com/ +https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node4.${NAMESPACE}.development.mobilecoin.com/ +https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node5.${NAMESPACE}.development.mobilecoin.com/ + +--- Fog Endpoint --- + +fog.${NAMESPACE}.development.mobilecoin.com + +--- mobilecoind --- + +Connect to mobilecoind API with K8s port forwarding + +# mobilecoind grpc +kubectl -n ${NAMESPACE} port-forward service/mobilecoind 3229:3229 + +# mobilecoind json +kubectl -n ${NAMESPACE} port-forward service/mobilecoind-json 9090:9090 + +# mint-auditor server grpc +kubectl -n ${NAMESPACE} port-forward service/mint-auditor 7774:7774 + +Then Connect to localhost: + +--- mobilecoind config options --- + +--peer mc://node1.${NAMESPACE}.development.mobilecoin.com:443/ \ +--tx-source-url https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node1.${NAMESPACE}.development.mobilecoin.com/ \ +--peer mc://node2.${NAMESPACE}.development.mobilecoin.com:443/ \ +--tx-source-url https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node2.${NAMESPACE}.development.mobilecoin.com/ \ +--peer mc://node3.${NAMESPACE}.development.mobilecoin.com:443/ \ +--tx-source-url https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node3.${NAMESPACE}.development.mobilecoin.com/ \ +--peer mc://node4.${NAMESPACE}.development.mobilecoin.com:443/ \ +--tx-source-url https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node4.${NAMESPACE}.development.mobilecoin.com/ \ +--peer mc://node5.${NAMESPACE}.development.mobilecoin.com:443/ \ +--tx-source-url https://s3-eu-central-1.amazonaws.com/mobilecoin.eu.development.chain/node5.${NAMESPACE}.development.mobilecoin.com/ \ +--poll-interval 1 \ +--quorum-set '{ "threshold": 3, "members": [{"args":"node1.${NAMESPACE}.development.mobilecoin.com:443","type":"Node"},{"args":"node2.${NAMESPACE}.development.mobilecoin.com:443","type":"Node"},{"args":"node3.${NAMESPACE}.development.mobilecoin.com:443","type":"Node"},{"args":"node4.${NAMESPACE}.development.mobilecoin.com:443","type":"Node"},{"args":"node5.${NAMESPACE}.development.mobilecoin.com:443","type":"Node"}] }' + +--- Get key seeds --- + +Seeds for wallets are randomly generated for the environment. You can get the seeds from the secret in the deployment and use sample-keys binary to recreate the keys for testing. + +# Set Keys Seeds from k8s secret. +export INITIAL_KEYS_SEED=\$(kubectl -n ${NAMESPACE} get secrets sample-keys-seeds -ojsonpath='{.data.INITIAL_KEYS_SEED}' | base64 -d) + +export FOG_KEYS_SEED=\$(kubectl -n ${NAMESPACE} get secrets sample-keys-seeds -ojsonpath='{.data.FOG_KEYS_SEED}' | base64 -d) + +export MNEMONIC_KEYS_SEED=\$(kubectl -n ${NAMESPACE} get secrets sample-keys-seeds -ojsonpath='{.data.MNEMONIC_KEYS_SEED}' | base64 -d) + +export MNEMONIC_FOG_KEYS_SEED=\$(kubectl -n ${NAMESPACE} get secrets sample-keys-seeds -ojsonpath='{.data.MNEMONIC_FOG_KEYS_SEED}' | base64 -d) + +# Copy singing ca cert to file. +kubectl -n ${NAMESPACE} get secrets sample-keys-seeds -ojsonpath='{.data.FOG_REPORT_SIGNING_CA_CERT}' | base64 -d > /tmp/fog_report_signing_ca_cert.pem + +# Regenerate keys to /tmp/sample_keys: +docker run -it --rm \ + --env FOG_REPORT_URL="fog://fog.${NAMESPACE}.development.mobilecoin.com" \ + --env FOG_REPORT_SIGNING_CA_CERT="\$(cat fog_report_signing_ca_cert.pem)" \ + --env FOG_KEYS_SEED \ + --env INITIAL_KEYS_SEED \ + --env MNEMONIC_KEYS_SEED \ + --env MNEMONIC_FOG_KEYS_SEED \ + --env FOG_REPORT_SIGNING_CA_CERT_PATH=/tmp/fog_report_signing_ca_cert.pem \ + -v /tmp/fog_report_signing_ca_cert.pem:/tmp/fog_report_signing_ca_cert.pem \ + -v /tmp/sample_data:/tmp/sample_data \ + ${DOCKER_ORG}/bootstrap-tools:${VERSION} /util/generate_origin_data.sh + +--- Charts --- + +# Add mobilecoin public helm repo +helm repo add mobilecoin-foundation-public ${CHART_REPO} + +# Update repo if you already have it installed +helm repo update + +# Search repo for helm charts +helm search repo -l --devel --version ${VERSION} mobilecoin-foundation-public + +--- Docker Images --- + +${DOCKER_ORG}/go-grpc-gateway:${VERSION} +${DOCKER_ORG}/node_hw:${VERSION} +${DOCKER_ORG}/fogingest:${VERSION} +${DOCKER_ORG}/bootstrap-tools:${VERSION} +${DOCKER_ORG}/fogreport:${VERSION} +${DOCKER_ORG}/fogview:${VERSION} +${DOCKER_ORG}/fog-ledger:${VERSION} +${DOCKER_ORG}/mobilecoind:${VERSION} +${DOCKER_ORG}/watcher:${VERSION} +${DOCKER_ORG}/fog-test-client:${VERSION} + +--- Binaries --- + +All binaries and enclave .css measurements can be found as attached artifacts to this GitHub Actions Run. + +EOF diff --git a/.internal-ci/util/sample-keys.1.1.3 b/.internal-ci/util/sample-keys.1.1.3 new file mode 100755 index 0000000000000000000000000000000000000000..7b67c54bc8138a78209f8e1a2998e4e9d1741ac4 GIT binary patch literal 6443408 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
  • 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 z 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%0DY+)ME0!KuVs8NY6L$?5s_6sSr!K@4kkG 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

    MPF_=oLpM!1av}D8;oH#3K>D{o@}8 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�X9`APdLf+HFKZ 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 *GRq5RSe8pl+#;NimaegGG!gw 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%0AF^L~+jt22zLm*>&!JrTT(!DSr;Na=Ve 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
    eD54sAO7&R9=> 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≫cvps7nRdfqgkwi-dLlcXK)K91`niS-gs+4ZR(v{u#!eiJrjHIXpOpQ zYY>yddY)*s6MZv^x*xd7ymm;1Pi!{WfGY;9W`Ot+ADSKDM9JHu3VVATGk2kp6+Ad<}>)UhBg< z#CAwwQ`pgQktbk}O4#}W0tfA6FW;HsU4ON5mOc8eR6TFeRuFYdcKtO7Cp!c0S>6=; z9!Cp0kyw#G`hGIDzX;d}khY()+gT8s>{ej^P>@t~dn_i}k~BAxt$1I zQQlu9O{FU7MYDqRw6B}-9x9w(Kd@lZ4~`I4)>#9O1=UgMBB+Pd(TnDbB&WBctRTER zQAa^f9SbJvTr!k87F2a80uPWnIJVXCs`!S zvxr$EaN+n^11?Mlb_*sEc%-nh`)CBVU=o36bsDJ}fh{Nz7@Fie;hB}~V3eOR`64&H zU(Ctn>?Uripy#HK3a9IY`90yLZ6pl&^1H)LyFsv<(#YH&pP9`gb7gz5>B#(&Na9J4 zj?4;r)2=s!(`y|ICav?fuzGH4LF*T7q>lQ<7stl-tG6Dhpc{YalF))l$^Vx8-r}1D ztzU%V7v6+#c>z7YuwddBYgtzH3kxQGahCNq^$QCoe!;Hri&&6d;hxl3j#vtMuJDI& zCa!Q0T%n7MihTJRxI!NY7qRMgz!{BLEktOUel$6A|v2iI|XQCWvs)On^w9nTXHC&rB?ort=!$c>%r9 zV8NsTUKUnw4rxJY0O*~45);**g&*@Jd1iuQ^e721+%X?djp2@|pw}@Qh0}G+=rWjL zyr9h_75SsF=%7;tgwMqjCE9XfL7phlbXGxLOVTYD3i6a&Z!|7ri`Utc1=%t@-L33| z1^^51P;CK`Sb~Gm5h9A~JYRy5f?l1EvxV~X=|b zESLnNy@i#pDK!{bFbPJ7Td6usTF?ZeV=S)*BMTrVwd`b!TUm;Xrd(`0&f21T|YU1EI|WJg7eFOU+!F0cp+FU$eaBt-nE z?^RL+T{60-$F32OR%zYSV-|Ezk16Pl5!Xw0HiSk(3nu;ICSmo)2n!C1jE@LEyFr*9 z$u?Gyt%+*#!*ab=2{L>hujdZhsPf2{KOMf&1%e|ZMW0?eLzlebbPHu?;ZIvRaupB(!EPqKCSOhM1e7EDTBRq~T7xQjOn+UT>s zFvCE}#oK-YdeO&%N%T3~vTF3PU=n>!w5%F^ET|EM{rwlQAMY(pr|bDqbr001A1&zo z*MiP}6=Z)>%l;+>d6u1A6N~xtQjzKVQyrU7~cnq@)0(whI7UVud_fQlhS9MEDZ`qPG6j+c=8BdCKg~x*>o)m#_ zrpwa)t8YXS`*3x7EW5-vr^FqDCoLo7fm#LG4sZ#M5ej;C_+GLncA!U!e-_jWiAx0Z zLZStoODX7u#NTa6Y6lA@E|oepu9N3d7Ib!r2hj%M=jt}3$8mKP^r|~nI9+w~@U)DiMI(WH<5-! z3nn4)^>gBSu~ZF-7Sxc)t6A-2l4H~HYS!6eOfE%NvlR3k;R4}I9D!D|dPtbAW(|N~ zN1)ZLrrr2VyqeWcgsx^?FOt|Y>J3M|(leW1-SUs<>p!JF#Qb)bw>NAG$ z3I#o{uwYX1b&}un3JY4Vcu<%`Ls84ULe^XfbVu4uiM;LfpK)L}<189(cc&{MnCsQ9F-ZtX2SS9whQ&UTG z5ej}~v+&<{$6wL5dLn# z*xz}LtlskKWvK0>UbeDyQg7g2T|h7RSTJdfIl}4<{1%kPKwD-1fgZGv@VoW0Apaejp`Ua* zGc_`MBm_MkDELfRSuYI*7ED6H z?lx-Zgvf#>6wI@{8VW4vLIHJ@ZZe;ClnZ3u<#&`NBJgb6QN{|Z*HJ8}9fe+J)JKJ^ zoNnY06U+mlA*LxN;t_w7SkQzR zdX3R4!tX*1Uv;f55f?ooC?70AKtT=ydex;MyM(UHY$(}X5a0{>O$D7!LXn@}IrkR< zsgJn}c?-I$E(OUx?n-1ETasRNSunB8_QJ}VY8K6#7*VQeU)b(Ov^}N7> zHpq06IvQjaN>1;k6bgF&XThZ8=Oup)RY$FCK^tT~5N7rW-9=C(qZFH1gNy}}Ak!$U z+(a5=ESLnD(`1-r<7tqwpaza0(|vK=1@V1QtigPRHJCZWu_y4H_;rkT$yrR)g7Uet zCaWNaR=75=$yWA*UEvPACfg!Jye9jY7C}O^D=ZMuTY#{j>k0~bLE;(7?lqDHlSX<$ zSUvZ!VA2)%BD9l~KQCR){o(`3%tqIXPzAkyvDj+F{emt+dr6pHga&_=enA(Z%^+|l zz6k9kLN7wU7fILwm2?sX(btlI@T+iooy3BP6@C|1&k7c_ourr4(N1#F-(nA`w}d-RXd3VlTNbdC2_sHPGUjVN#t#J zBAVB0yJWp~v<20-E$G6$1)Xmz$nK>JPK_edv#kXa+m07juT?E*e4Fm54^YEin6BpG zyRttB9ll#)A|Adwi9l`mErdNF-0;bK9rXO0xm)82xK_G5(A)82xK_IyWu zec^Y*caZ55Xb--nv@=2%y>hR7MVeo&Sa$&Gado;jPxrH$iO_J>P6YQ-S|aV1Q#?pV zm&SfE5&rI4&w{S?6eNB(NY_esul^QH>R&Ic97lBcuwYVu4o3T0(Kn`-;x!5nq#8x* zAVwS@tlTuj`Vo56Ap)Ytd`*I#pd;|s!R>IAKgX+k561fj_a@?75C{B@PyPZZ|CA0h z&6mYCxdy6+t=GcL^cutRz40iqxt!%u;yxKA6!b=kJ~2Cw62XDe20UTfL4@!IL+wdz z0(zr_1zlSx==tIvlHF?y3np!`x3GG?Xu+f{c$8=&+G^4~8=y*?x1^I5vL+O#x_fXP;)U>>j*@Et_lY$&lbSuuYLp7iU6EnUb ztn7&zQY`4)I6C&YAXp;oD^Ub{I=w1i4=Kn^`31T&g-8$7?rA|6DlO=`r-F1n>O!T0 zo?}`tsn>6!sMkF$=<0>lB)Y#=mUd%9^x+QqnW%0zdF(T|!rKWgb**q5Mk)=YYoi?E zmj$_{=z#zWQcLlJ0evJ(9}KAL0HF^Cv=9N?^Me7MAh;TQQ?N%*(T$;g5TbTO4+i`p z3h@L34+xa#0Rao@`!79AJ}?zs8T%>qT=(EWkiP`At~&_&JeO|B?}J)56Y+DpK0gMv zZ3n@jhHBYOXI$-waJ4%agsUA9u67_y?erAa4usT>-{x6&2=eJ;56vL-v4?g_OD*p9 zYr${qJpbyX2kIL;JxtzkZ87)8PFN#P9|G;B(t}L=>5zU9_;d(=jihoYKDsfZhQIdE zLTULR$a_*Mg)aRdh==Xm3`5h$dpkK-{6UZ&O3Md9{un}nhdBxToNE|=%6IrRac!xi z=!Ze-4of}^GEL4~y*$iGZRT9@he6h{Qt1PQQ3-vzPBi3bpU#ZoPu*CMK6R5l2AXUp zoGT+;&Sa|jW2@~bpd4lz3(vrryM+j{^h)ukrMw#ANAC+V{eoP99vrrQgc$_A&$#@L z_+G!BrMj0F$-RCBc}T}t$@^gbW9lDI;0}XV_fhG{mtT(NAcq^TZUW)Fx{V0+>TV*` ztNV#iudX}7dUZ1>K1E*L4#IkMH=R_k?gOEHbm#849Vb8^_3pg{qcIMBl)d|C!Kgje zyFE<2+hYI6yMrU4#YgGbyPH9%cXuMK-rYlK@$Q4KjkU90`Z-tZ-E~JL-hJ5+ z5Cuysm(Tu^20VhXCYL50c&BeR>r*cS;Sc?Ey|ayx)M zU|`}*YK~*@alCw{fgdqzA!2NHB9A0pAUM`$F9F{{H^g;E9fS0=?68PFwR5b1H0Y&Q z$galU+OeSf){Y1Aw|4UM@$^0_aK-FM{%U%cNTcDIZnog{;&^|vfTU_EN{y>N4TX8& zd~73*W$bQB624aRqDLC2)VS6_sJJn&iCuN>s} zBvp=u-an;B@#~0Nh)M~ohoLLaT| z2Z27tU!OTlq_Ee?$WeD((zh;?^Q4xJ93JL;xtVjteXE_)GIHEEgai+B61q88+_(BD zEgz15RwVE!A|I}ONigyl{cwCFMrJ-97v6!DX9_wCoaxun%V$3y1lF&G>&zg}{(3x& zof3a-B0~MO69oHff&8_PPQg#v&4Nx4aI?Z+;k2C~$i4F9UOhy>t!l}w`iUTS%9A_Q zoq$YmqawLc3kbLm3+O_+1h;{<_yP>Qkh&L0Wy3M-0Ktju0Q@EAW=de zeL3??0m&flE07+jA0D-!3&_O}pj$giscbYV--mQJ()qzwBbsz`BozQRBy-N2FX5&>tQmmxno*>Ec|m)AdqXobHVwBzTyUFu=Lw^N1(2 z)5X&#N=rchdI)JA=A?CUt~j92yeV#y#2t5_wic9D2Ke)cXP+?$l+PpbyU!u6^5^04 ztIv_9zE9t;-Ch);l?3i)m5bJ>8p|(?UE>9L8pKPodVQ5zZMY`hNC|f zOS1=I8m^U(>gsx}f>geQ>kgL#WXyqeXJr-&)6{?sgR6!$@<48ZX$;w5JBXy@G z1IfBl7>#UBGX;&1QY|#wR+y0tqIL89`8|u(e4DD}4{KY{eZbX%`TZ!#VzR4F#{~E+NZk0lozSXFVWG#wZ(F@4Er>PM2$5PE8 zkUmi`u`-D9U;GJE$SF}MJWOOd4Ef3NUc%lVgj{?>`b zc;&A84HWf*a8jE@f2n6*s=Gbb^G?FHiG9gp>Pw1QUm7iWtuJ{PS(`_<;B>T+_|S4g z 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 z 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%0A~LY`Iq#n8L(kTv384j!a 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≪PY_C_xd`XKb3BF;$k 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

    u1&X(fF?gPhA+D2SVVvR4-Z#m-))0`8xU+ z)lZ~+GEumhuZ)|tBfSCh^(gEs$7`Oq=Utn@$Iy7<_NfkkAF9A`$v^%=&Cfj$=xc-< zKX=f)IKL_nQav3b+^%JtOU%F1U>{3n;W=w$FF(tiOwo#O2W@Hom3 zL;k{e@IJs|T=xdyZvLeF@FI9N`DYJ!E5-Avf2&R%jpugZ2U;&rxLo%8AL#$8tI~1a zgH8pli!T2deTmjzwG*~+JJ#h=2PqHF5^nNIdz04R@wneju#Zq*dbra??O)PLWcBYC zZv4|q_UpkT6jxmjQu_#}Q|DIRAltZ@RDZ4_5v1+UPv|2>2K} zNBRJ~llqw>4^f>Jw6D2bxEW8%EcJu++aWQ^z4ba@c1|Ashp#G$HRNq)N!IeHDOb5?>|U=zHGNc+Nwdbilri_R(i|Q~e^E z_xr(fs6SjU{6PLp?5;YwwBN}S?%Gp7ybShX$^*N>JE?CRdYI}bQQp1{d@0rCRp9(P zwjJPYls87kslIo*#;1K=;y&Rf4>!-z%xph*s52bC{r5j#KxYiC_dbWKzC-nTGI)^2 z^8$D^tKfm4#`&#NN4nInDa;bmF01t+u?{}`Xr*-$aaC6=EJk3{j z9{U`v`bAX7uLmDa>*9IgMkn&TE?hi5>FkDm74;iKdx*Zg=OlvnoY;NG9fnIjtfKYx zHaPdOe}b1%-WwIKI_b1tW(qgs<+b zT)6Q=4Za^?`{AEqUr2FvdV=b=_SAi@eZKcj@LYSc#z_DK6nj{^Gk3a^`9s9Rs9s2 z-znfBs#D9rW9U5R2k;!~dk6PZ{W|I&ZUOgG-&h46OL?F}xQQ$O9G#It@I!uo)o-J? z4GTB(7#OB?@O0RxCMpjer8`->?(P(B)@cdV_tmbwjlTc??-tm%k)L~pX_=-Xz=4JZ`we1NU{`2{-dwPId5< zAx7uFf1`yP`%LQVioug<|FzN8kv^85C%I^-jx(@GM|c(LSCMd|A0~gUg?-IUIx2f# z=cK58HTm;?@HRT1Uk^STdDwp6s>`XWGo1SNi-eo?=w$0c#By|;)6{;h+5}!i^B#A)>eP|nGQis?PnHQc<7xj{_rIsX58Gj1O7*wz2(=IR zwT}0P{VBptocPIp26!3uT`R#I^5?JMwba+0d4^oq)Ts-!vgl|X=S9P1{9&B)+rH(! zhxK=DB8RADE8=-*s*W>2*S!_Ig!+d!z>}#S{SKb-UUa;jbEeUk@7;I!T+hVfJUrlX zd2W#Ar4~Gq)_d$(I?j=l-$pEz@75kHy*Bl4>9DV%`+5RAf#T;=;l`hV1zPv*^V@fv zt^V{(*19tR;|~ir^P5WXv(L3h5d7<(Lr1E867@3|frls_W`h^edifZ>T2(eXRi z={nV}+i{A8n{lSozNrp8Ks;`g+E!}}G3EoWkWIuS-lIVPRW}4BL@7++G+~ab2FCv{ot`%X$OW!&G19 z3O71@-rfoOD%yAZ($(JggRZYjG4IQSoA_*@`}zU=tRZ?nGZFTKE>Zh6bbdHPxLs>7 zb^j@beG=u9I`9~(JBN)|{U#d!rQju$=jVcZDL;H}b;$p{E>(RW)uU^L8-L~`Xn$hw zci!UP5{G*bLRrr}10`&hb_O9;Wd$3peBOjLK(#OKj2AMkJ;xrFPWhFm6RWz1b683mj>`;>H`xp z)ep{YUDsh0?6Ja4+}?VM#^*KgPYL)$ywChD@XgTitc>pGe*+Jnr{}0Qz`pAh@IT&r zVCzCDc*e7;V|jycGoE^?;|UX$r&9jU22Z1Py%^j}dGZ_ZG1Tu3yi)aRo{P?(H-dkG z=Xs{!zFr1Tr2fAhJdg6guq@TDpnQ8Lc!>I+)xu3Y@cY(|y-IZ&DITsCZsOe6s1tiA z9%v|qeF2+-!o;^wZ?>R#2wS7Kkk>RFZ z^iv1l4ISrN<^B!2z8(S}0q%URT)TS5xkgdbD8l3XdeCGHRR9Ng`07P_h=p5f&1MLUW501qAWXaUa$Je zblu;-+~V(`;%`pI`UquZlhff+vj9%a=E+@lj7=C za4*g8FW`lguSVRY;}25adsn!bms~o}JUCx@JH_pV!p*wNDbze~&%GnCPoepWzgh1q zrcE-as~SQS+2duiBP@R0=|OgrN<1_$)VrN$P#YutAh5?6|i^c{XCuE z88}C>-;00bf2vbU_w@mInDWUHe)x^*>E*)RxV=>)JdAZT8}><*S3ib*PLkHC6|nDi zi|RK~zP$vzocfR;cmw&f0X&uJX~M0lzm(Q#Hh3=e8;e~op9|o3y=~ln1^ZOW+ljZS ze($BxeaPm6o6Vx36b z?b9g!r+^pJ{JsFr?{#klPp0t?x_tC<^Lee3jx)GW?dvEX-U8n7Ui7@Y0p39I|2udZ-PbvHss0)|4+#i2 zc{b;l@9n3iZr=h=)=4s7@ip?E~O# zH1F?&*VFp#R-`(W)K6X_+}u}tcinH=K5ZuK9n#+bd(U8vTYJ8A-o2_*lc@WbIT-)5 z!p;14Qr`O(yq)eV={~j3qy1ez_^w#pXW9696}*`4_ZRRis#9m&kNZ7V@3#fxTp-+x zGj>ySAKL``$o<+;$KIm5Q4FI=)2hpX;IXqHuToo1@3y=JEt5@TJeSwE1nwgKFPE_4iic zCLZ{A-#TF5LG^TGvFbcFRj(VwcM7BaL%8 zc*>IK^}YwZnAY{F537DXt?L5eX5BSEuKu+Bb~EgYDK8~HqB@0j(SDu=UPXP*OW5*h=d;%fH#+H* z2c8Gdq4Dnm&!Y2?!H=mvKX3M;;c{Pr`*lIQ1BZSKd+%BL38wY)xLG=$rIcr$0QZvr zKLu~6x_oS@>XgvAA4V&kgP8wwEg92%bZJ zKJ0PTsiru;6g-jmT<{3()3;h3>O*=xq5A0*=aayj$v+|RG8$)#aO0o$$y%@NzJ5SZ z^($z9cO!T;tODPn{ftdKR5@R_mvkuCH9i9cwKK4ZpP!MKKZbD%G1f8mkKx6t$9Q5>ne=1 z1w7*ltyAN0zbDSeINw$K55aqut9~2B?If2cINo0RJ0@P}FNS>{jq@AuX3`nBK(Cu~ zwPwOckvMJ?Ztiys)%RDx_fdY>Yq;Zap2Y7q+CJyJr&TBO5zVV|GUfgigBMX>Q77E^ zEr9oSX2bpu*oSGIj#{YtHB_e_0I#FG^gehw^-J9F>;+tveyZ%{n?(=Ux9-$9dW6P~O-J`^Y@?WCZ?6UZmIE zM}4?oxY2L#)b*mfMaNkJ`*P~@zX!hr-#fbm`X?{OI6u(1Js;#odk-j zLn~E3Om+Ms;dYH+s@#7j!9GMf&w^)B-Dv?2(!33e}Gze`dQp!6~Hor7wbgBHh>5!VffGzrnus zndtGK^|FrBTcdf*{fs&de`F>wfDf!Hg2yFZtRn2e_d|v@!n(WAJ41CUfw@O zewg5LdEWxv*L?5*<^M0i{nTgn3F~;)P#&Hv+{{aJwcf9N@5Dmbm*M^Jw%%RoC01;ed#jrcADSa;5mJ@BkhlPNM5Pq?ICsaNdRR zcg}xZ{oIb<8L@fzA(wlc2D-0J;MFvbaaDTVMzYUvxqN?zp4$n+ek7f%e+u6FxoE!~ z`-a}HKdAdS+vi*-+}v*p#lsTVd+ybGWS>+09`>D7M+UvAI#m?^Gr&hu-CPOYd5PBL zGcYgvz)LB=ov}*w*O1@t7H;A#G+sOWozSU;eH_)1uGOlOMe%$wcrwM+XU^sBaBZ-9LP^|#&MQJr|&PmKq^ zZMy0w;eLbQYv`Q$QRsC;o)^%;y`%WcY=E;5BFcI z`nj~erV2NHNWpv6#$x~A*OQ}(vQd-vq!p*$%dCNZ7SCKzc-&37!=rd97oO^^D zo#r80S?+}+zJPry#ao|ss*^%>c`|r!ivJhDn`u4n0#B!YDS5r>$I$rw;3Z`Lx^Odo zFTH2G1@^fV4+Cpe-+!UTPX_!y9Xy%x|I6TQG%xMoWsj+j_2;nn&HVoNZ>-B@KlOuF zWcxcW3x%8f*+BX`z#ErD>-XKD_MMb}a>3gv-j;zUQ#|jsI@H$<-KhH2RL5^~x%~d= zU;4SH7q|F^a1+nrSG8VG0N)Lr0`mWmI@NEXc(_Hlt8<0!6N?dtE5S3))I4v$U(f-b zvRC&(Kf(TlO-5hN84f$w9f>{PzSiaPyGxXBp99aP@q7zjLi>)S%{tDU6s>FPalfxx z{)Nu(I0Qt(2YSC16erh!XHY&_3|>v^?i=C8KOyYj@4Y1s_9k zmHMITH(#&OyBGd^&~RB_5&ZrFu(Jd9d~SBsM>?KdimNNY3u*tg0Ng{Le{C1;=C{u1 z{oP4hRKJt<>C=T9|3n;}7p>-w^E~X2o}ugLLip`l@O0XzoE$Ma|NXnr<+6Tn)%mS~ z$y?w)JU6lheDud=obtY3>bqtNKal=n*WTjP+bTBi!9zP<}qILH&?K`-o!UW;_nQ zx23ZtVxOr_Esf`V;coojsN??)fmj6Y>(KmTKW|+R9UsM8*Uwcyp5}cVxR3JQ6X4Ah zZ=Zr^6F+XN>c>*wbq#nm?Uxq|H}~cJSwC^eOH_yMG+g|gf%m9rmUEnw8&$uP_BA(w zXRnQ}7q1F8`W}3)Vf(HY*bk@sP1>f{jXa|X%=VLh;bwlTDNnu*UQGV{&FIK=GZJ;a z=3>6GBtM#UQP;l) zxy-N~s$WZa;11!&KD|Vkm*sL<*T?CK-hg>8 z6K>)s^_}SWY;?JtpX}0j$b#hY&1&C4_3JwDd^!hvPPnpbuT$^&13FD3gv-{^IDzqUZQ z@n?|6za89J813g1Thu=ezUN*DKfhqO+?T&h@5|O7{w-v6!YMD}XFwa?Q& zFWihLi_Q;sfu~ZO5B^T=*U&!K4_-iVUM1X&lb_SO;CmfU5OqYmMEPA9;buH3^tpdr ztMWLChYaur@@E;im-?lx!cDw2uhCV|6`y~_>{9&|*k{@23CDuhQa|~aaCsW?Kku)Y zXLTsfw+T1bt-&P~GIbwPE!)o}4A$JKSaRVPC6{2X{2J%{rh zcr5w(ls3Jt->2(Qj+NZM1;WiZTgd<0!9#T#w>FP?_ZWM558+my``_DoG1=wv{Wa=) zUjVPCJo5v%hw9ysA9XxUq;soq~wa)d}JGUc0W}1oxqz z(P(j;pM;xn#!ws%+o!yh;`UDP)I;_B$JV>Iz+Kk_nH~#njqMd&X zHnc}|s(vNy6ElUoafLdlQ6%qyhrO5j)nors`^eeR=PH*AcjJoc_&nJA@jDKKQSZEe zt9=WdPv(N>)4Hn!50QPFa5MglE!u%kK>{84kKzCQ8*jMeH_r(DUv1w~?%GQ~Q?LEW zFr34DEZp2zImO8_&Y>=^q&U0^{A+yfa|VX+v~V-dAf9`-`-KMBr%*g39HjbHcV93B#NsSz{8uO>+CM!Za?ssM$YZ@M6kiM<1&8jWmxF!Hdby3&2C%&w!^=Ki{{j>NnH8 z-vFLL_ge{`MEl=1@O@-IG*7O(zi)q7H`Vb`p1A`&nd-<} zE>Cb`>73_J*ym9lJh!{*ub_4JAb5c4#YW-oy#J!>T7E9U{X6_H)oG=^F~j9Dp1pcr zoq{--1A8CE!)M^VsekAhr`Pr3_ZPOJp(zn=;;Mzt;XeQ`pnc5|hpT-a#m{BnUfSb&bB) z_OWw>8=ZLeo3WR1^80=d^Qe6rjq_6Q8jAn9!p(Jko!W0t#rVI3{RQ~G@F4I$N2&e= zk8A&SCwLBcBh~$-;Ptd#z6Wom`8wrj)la3oJp;Ue*3nAg#t#vEK5q9f$MsO180u%P za=E-ugZjpW!i^uCKeVFF$9;VRofPUr2F9zsAMa7L`|*Xs&3px@-t7cWq4nGE7#)8Y zeWs0v8-yF3JR1Kp*w^5_lw}xa;<3g)!O5Zbs!esd{bveI4EJH{jJ&mk0FH@p!uEcD=Zk@KV}$BzpC_d~PsLxS5was%zVfy%|5= z|7P>dkiKePP3!a);pV>DZ_|Fv_Q`JSM3ey>fV z(Q(#V`xb4u2EY%K`s;Yk$Me;;hhGeyMfvt?@N!ze0}@roOZDPL@KQQgd_}k!r=PwT ze8x$tlSA=#4|plnwReRZoe;fGsowzAsh~b#s&Hf9Oy_dd;O#?n-JOAWJAR<*M92@< zx?E1V@I0YC?^-O})$gl1L*VCwlE8OrJl`OpVg4$FyX%_nw;8;U)_dZ~YM)2-I#0Nr zJ5|>ITLk+Y%40R)wbWO~oTB4&9?=N2&l#o(H{(pByf+KHh~{?-c;mY0JltcD>NHXw zz7l*N&F@0+IO@B0g6ENb|701ztRsFt>Kox^{Hf&UfrFLT(&q>_f-j}>ftSIHDDUkB z-$!vWe2D6=8moRd4U=;RxQFcD0v}HK@Gs$RoYUt=XAM>TCOS8`4?LCPXB~J6^_g8# zR40+<@gndT;m2Ji-&uY}W7zk~X{Z16*8 zXdOg5;4A`PLH*d*;Dxk~1`LBg={d<8g`2qYAE6z^b(qIi!^IC7$Yb_-hMR}0&OVx# z*T54gPyPxXBtM^dy6T7VyE8Wb&l7Iqxrp-c7vTGd_Zgw~H56Bqg}ZSzMEkB%dtb2k zk>8TfP#uTX#s9!#Xue(t?@ij?8j4yre6>Z+W%jF)Yk^07Wzsq9Vg|zlSU~YN&cTM+{7oJ zXMO6B~xVg`07f(Ktu@ zR434>9o-t-SA}r*z9_Hm1h1j^={H*K9a@i5!I#oHS}xq&m-l|X?yZ=YpJAWBI(ptm zoTuY-n_>I1QI>F`gxxmxWasCvzpT@rxynyEM_;l58?jBut zvRy9cW|W6R;A6Qig0G?0!FM{V#-e?1Fr+wwn@p|3R z5qjN4$lLkCjX&e4FEZ!FCJqDp^?cRF=U&)X(K+YvOI629=RbwuEwo3&izFhV5C_nqb{dB)o;DwauJHQhtzm1%r`Z1&v0MDiSss)dwyb+rz z_iOU)1ntaizxuG@;s^e{_}DA-y7d%4>ELY?|3UC<>VF!*>nKhVCaV4livMizl#g^> z+vj9L;0@GQd?Vb9-$VQT3$8T!a*l^}ZR7kQm&@~46je>AdjsJdcBCT#h~j>*#agW?iSzy!5(Sc?Df}61Zngbe?<`JWQX< ze+ynhdGh3IRKJP*b~AVfogcpDa``^y(VADS|9^&kCB^@UY}L;sox6pb`3=!?6l-DM zOyfCZlIoPveT@b85T6A;oc5<%guD3x-$U;Q{|~-a_46oB{4SU8D;*PkzpukSj^_P0 z;jaD??YHgs@~*#5^?lQI-|EG6mw>OJy7nEoL-T%ej_RaR-ndz~xo&g2t}MGxUv0SL z2Y&7-`Fhn^O8LYOo=@w&3cP~$%N^jwlvhViR{gdm(eZgdxDWljQ>c!3Pq-PsC#?Oa zJs15Q_I2c+kyBv5O8bp_u`zg5xLHSKh4uG-g8e=@=4Qm5#>b5Fs(nEbyD zyq(tX2{)*Ifa36a@NaHW|J-Tg0lbp@|2=poo%0Wxs`^E=Uj7GOKzZzS@G{DK`-Qvl zGea93`zgbyX{x`5*4Iq%6yh7edsCm&El+ixN>*jNF2;eU)4AUh;0<(NpMvL8o;hy1 z>L-w&uK};8`C1GfOL6iwcnhuT0XM3C`D4-XJRLlj^j`)~qPYDDJWTq-Zc_as%FlO# z=aGL_gO8zj{>SC=IVOG1H9Ftu%f8@mpBrgj#M^@|m-nWU-!_78xKQuc*6VIJYn%lB z7ab=TgJ?7b)JIPLQQU2jpHj2rZR?YZ1b;5j&-IS2aR2sip4;<>fn;3wUxJf8Zu z>B3!q_ELQuV>lleE`A8$cWJ+ePWRhXr;g%kJa`H98*{){Q2+e7aHF47qF0olS4XekrQjLV z$F>SL*R3hg0I{F%q~D?X?>wwJHcn=Pr_%cU7`%zj0pjmeomd)Y7I+Qy&lTVqq~8qQ zLU}&1P{uFoh@Tr-CEUbM49(-8;GLAWN8P3N5vmstfcvQKzc2hi{l?I{jX(eUcfN2l zo_O;ABj8oEFWBtr$bKBZ*KGTQGwxBHHMD=cN4S~CAU;pAdF)NtcTisa1H6Xzt)q%m zKb`W}1K>?GU+)V)(EV<6xvY!*dSW>kE=jvr^}Tr-S9V|gD0m0O$%n$-b@7HaK7Hy` zXzYEe^Ifh+ragaq6g-an{Go88<1f?v@G;IAj=5iT0#v`UT%O>he(!THX#4*KmeYCr z7s3zZhaaKeLV5DEfY_V;EPe;M5B#%QxQUaIZYcs%8|O~TD} z9eRGX$4u3Ur+R%Q_(+PAg~Hu=S*7{vG>rdu@S2B}+j$xDpxQSdtK8=E65-~4eRQ7u z0eC9%j~DuJ#cCg-eklXIlJ+%o!4oJSZWVr@`TEu6a;{FlFaOL#I{sjP{k(fQ#&gia zI-YtuAG-iNm;Cl9crC5p4~4t&&{N~we(z(+Bg%Py9bcm33FG}37h*h_!i_&WX&sdt zdzp9s{>4F$8v6vtkLML_oS*M_y`v`au^}`>4H_$pd;xQdh@VV%EbeV879#3X; zoNR}E8SPWNvs5RW{Fw`0OZ%^7;MK%`x#D2=dr#pBdM*dIIX}R@f%@dZrFz|cv@UJ| zFQI+V8{kW+Ui>cHtQY?N#c8uuKab+)4)BpQ{zRj^-a>>aVE^Us~I53SYx zuZ{DwgR0}jzIXw2%7vS8#!|o61bcojQ1X*%A4B=yFWihX9MS9AetQY*D=FT-1CLPu zaLOFj50c+*2Co^XaUR0>KLB4rdHcw@s#8k&c>;Jnt)qG1O>|!R1$Z*mAR z7{qvTgu8J_@5A{P_TIJ8>-6NORHuRB{AS@sCvdd(`F3Bh9QN(ss!j&3`y+S)Jr8s0 zJouCD>vr&J%42T{H`lHCN%O{eX!JY5`S(npoUiu&O8sQnejZvU+{APHFZwxx?L)ei ztG)LdjguSDC!`2BaactA#{%$nTBobP!xV>qg6DJpxd7LtbKqx$o9l)s-+l$&oA^mj zt9=^f?dige-@}@_X5oSI=3b<8P(7 zdO*1GkLN!9Ja;}4#5=HesDD0avFa4i{9XW_LiwQtyo2@^AAlFr{{6_1>St2Dn;_hb z(?3h^7srZDDeRkQoDuL8(vN>u^$Tg;Wr2sN4lV>wr~I%}xH}%~J8WL<_nh*Y^K>4! zW1R+sn|N-g`>F+xqkUiO619)e`WgqGNp zmz#c4SE9|U&9JYccuRaq$5}()w|xmbxI^>s?bgrWp03)5&qKhSutLX~PWkzI;l@7^ z%Bve-AEG|3`^%UYI{zOJ-c0s$tUdXs0lb>}isN2UeIN0w!8>SPo&hgWs(uIYiNeji2maLa2b%{F8t>pigz|-iQ=SNpZ_GR?F%TuZ_{w!U&#fbk&!i}FhpN)=(5O^)swHBAl z=a_U}anc*AlST0`9lU_@z{}wAl%MyyT=eOEQ>VSD`nePjcL+CmvKh}4ZpM8D40rQt z^nASmohFKh4(K>rbQbLSm~WL{w}|!&#o*=Sw~gSw#nJxkUadOWbj~myyoBn`li&$d z*FFQ!pwDr7zNPxLWIsu`@k8_7S~n*npRa=b7|Q>D!ruF|=70Nn#5r%PzMtYPApAga z8-jfd`R5z(8alrkxLWlaXV=!Q_2In2_6d3K>U^c(cOf4@Jg+lc?D@Rq?6qp|e?;@= z8ra_^+^p*e?F-(7edq+;XRScJ`w85$O!q-S>{Cvu(d&A~Yu>QyqCmLO&!IS91wNAc z!#}}8R9{BDr#d4kf6fHYsf+HrYQalrzGBy@PBYcJao{!A=zif$_~$0!Zhq*ib$=@O zM%b6W7rlNDTd(@1RAn6P~y$i>A2fUK}=4?=%Y|77Lz!Rz8c-V4^^UcD|{YLP+32ipsHY(@+@=n-AU_-=EbgBkw^HZgl)pH1GML zv(L4cd8g+kMl`5Be~w=++{}A9#d#BW9NpK6pBa1ky^pOv_loxOh3kd8^LU*0Ew^Ai zvt4^R@1lA6*w{;+;m>(}pJP1KA3iAD*!xFng16W0fPDq!w~<>_r<(Fx0KA0qc`bMr zt*=8HRVSO)@5SH=R8MDv`zYQ%7Vgehk)B%~rOU%PYMb5{e{bR{;l|G;KS%p{q02o^ z0daoFz*9e*Ol)l~3&T1PK}*V26L0q49l^h?!WLHpU;gq!=V!9Lygu^+?U zPxi+&!OwJGS;Eb{^K*bJ4L9rPdi7^_T?Wpt;QU^f%eSjPE4QmZy@<~;;cnd0`T5a1 zbUX>vH%%^U^Urh5g1-z23yG*$81D{8QzgC@CS}(r{ zH}~c3rhTS<3h6k5zES&Dis%1kdTU5V>^2Rjb zX8i3BY2LGa;8xfd(K_n&t?FEj_aB}JKTiVBpgI)-ub}aK1Ma1KKJYuEFW)<$_hw87 z&x?&dCw$4}@_Sfxp74`!{6Y5H19VGH#+?LBOkc-^1j42y`v83AMu0g6qBDX1JA3B z&Oc?~nG~N}g`4YUOx7LEXvEdoyM;@f`0At20Ui=={OPAWzX`m8^7-Ly#y-JGquTkD!H<8~?*rVe~r~WfXxY74MuJdv}^w)s<>3v`Opp#Ge zHuXpK1MfGN3O9a8qkZ4^;AK?r2K}Vt2`$mi;aSY%UEngT)vqB;?>9}k{E^Zul8b6?GSG_Le69LKW{9KVZn0^;FZ;b#01T1PX% zb0}YJfKCRU|F`w@;9qgSv@R|bZpPz#Q}dGjoT3EWOTYg+alh&`P+nai+~@=!)jInr z&MQ6vufga012JC-zp2h}@_#n?!2fA}cntQ>fVb1R@mJs_be?lkhw2BZ&gKa>feaGP6Ri~YPA3QAF%vUDmfqmd>$p5K-sC_f7$0Ffo zU8LZ>D|Y{03;RZ@7qNe;P71B}al+00I{)bWeu?{i3HCm!<3ECz)A_?`okl;w39t9L z3bwB<5N^ilbkoFa&&Lk=OUDzS_#7+Tj3))_`g)9K3GACFKYR~<7wWsc?kRukb$MSf zSGe*2d^|rk0QwE!YbZ_<{!#mOs@K`zNwlwA3?88Q`bN09uL#z!?Te;3T{RvkZkK^~ zlKv0ib=2PuK1g*MD1L4c?#}Oc&D%3@ztyl$e>b|$c7lh=559v{KTPLH#lp?}hI*>L zJy-n8a9r!(|9B5kolc7XT<}slXR8G7P4nIcKAif2p)snTO@6pd_<_bV7xpoj#cng;YL4(?l(S8d4SgGmBP(@)!==G`ZST_G{8Qa)_cO?suN4+($~0LzRyDYh-ZWw z{bu~WjD4Q=*dtUYhsJp|crDe_Mc}Pe7rp||raX4ikw#zMEApG(kr)1%CftlC z82>>>t9=mf)d6%AKpXtW4EY%D;m4Yz(dprmVwt&e%lJ3 zP5Go(yxy1B(KlJ0gd12O-1sw}`ho4>D=7c;Jx1rn!S@Pv6*$gq;2!iF|L=1O;qJPl zdgL4n9n^7aKS{W;Z>9ATGWIer-Xo&x$Pds7oT&$0@8Q0#I8Jqnsa`Aq?Tlb?_feink>|F}x(J1})2_kz%Y~bDl!W&J*}mlqm&-XS zjk8ZL9cL`%tLudu{lEnE+jUwtoHt<~qJ6>d!adIM|3}`tfLWGZ^?gMWY>0 zBTL5MpqP;({6QeGLS!ssk;uyU^YB>?<4AxAipg*7z0bYp>~rp|NB5w7pXZaht9PBV z&VH=D_S)<5U%mPc8(%DR`v0AxUDoSUXPcXdex^39u>8XR*0i6s_|Scc zrvD;qpB|X@Pg;EP^Rx?}T=^w^Kl*Lcd)^tbgcdL zHD99Xmli*K8|^ax_dl&?@AJ&P?BnM7z~YnWOEsMjT6UNxXjk&{o3#A=93wwJZl3>$ zweB(cf%@)mX}$fj`R<%{S+6S=|NNXhFLKY+d;LuF{L8*f(|OT*bpQW}QQ#h;UFf|3 zN4xUv&8GcjmfZVwL+9y_>6`UC4E>EitLePZ;)k=eOaDLcQQiLrfA3q(^DnmU1@DvR z>HizHbqAaK`)B_-P5+c7#~xPgFWz{q$y;;`pS+p&AwK^*hR(k-^%q`io_|g~-`~Gq zc1phc;*F2|snhDo`^@u&YJbtj>#h63-!koIEq(Ie&@SV$?`e&tG_`$*l{-k;SDdVp=l~+eU{$%DD8^=7wD7s zeq(R>h`!8E`zI>$V zZyCR5WafX%w11Cv@AzrjWgcw12NZ1my(mUda+4NDIHTl4(J zKh=ErMTX>qj(+|V|EMeXzR$G({CDd1mzn2(jdsN+#xC0M!xy=l&Ks<8{YBIMjMbl~ zO#AySx$%r?-?q-LukbYepRnjZX4?O|O}#Fla)^@318 z|Ma#V=@*(`ekJX)E_*M~{Ln~`pD^vu{e7)3X)OZyGDD}di{E~O_M!dtf0^gEEdAX3di~u~mb|)Y+TUi) z^FJ`{XD#{jDcWVdUSx2XzfNzbjp%;eZu^z~8toz<-e~dFZ<_Y!toi(s)B5?hSpCmU z`_mTx|DrKY!w^rt@CQF7XYf{etDUdNb|n{C!d@4rUu|e8xFV=R?;1J!je- zOCS4Q)BX`lZu}bUvhMf)ePkB@efC#q!SRCgy8Y=t(D85ohi=}uV%o15Ic(IKjSrai z`yws(zTVtlzUV>S&lg+#@Xez>=x=Iv`QYWi=o_V2gRF7x&g~9XPQ6Ogd7;(MEz|z_mi&At?Lz12iC(E@ zo}V$#zsus=mp!EEJC^>iZQ9>%@$I`z`~8;w^KsMu7RwG3KP>&}|F=oI$dgZ4`pFNQ z_K*F;u6+K@=6S3CUvf#0_rCY&bLXechRJCc`g@jq_$kx=ti^}FZQ9>v?ccAy41M_L z1N&M5f7A@+K-!t-7rj#p&L>U#hiRAZK4*wEQ@zqb8_WP~=|Bh)tYw3;Nrl#{LtNp;VJJ!1Y1KMT0Polrbe=jie z{QsKgUvI6~>8qN4V)5;Fn)dsx=YNIvAwK!2dH%M==U;wJ)8De%A2aQrwC3~g&^|=} z1FD_-&a+x0-8C1y`ybKtzu(ex-elTeY4!h?P5X-tzFcEhdBLNa&W9}daLKg4-I6mu zVA`)(=j;bf`^&6#dGTxXx;$0t{ru`kG$3J=lf0j(E?iWt?uV9 zTmHVYv@1RH1)9$rK76xz{uyh1e_fu3Pd@N!t^Yq|zWdqVsOkUw`?~x3Vbgxi+Sfl| z+TUUAqkn4JpZptLIxl|R@cO=-cG+LwW1a6))BX-iFM5w@zu(gLe$TXTSncUIY5G55 z$!?OT=}@;=l4Cd<$AnXlLLY}dcLW7_Te_%pQ2xZY@e_ho-kw||y(zT7bFPg{ER z&(JRGYy10lzS)e+vd{co)Bb+Tj{3W%J+a!;v8MB!buN4>?eg7sUFq6|eo5NlpS>^C z8!Sc16e33v1-_JI(XAE&tK)$n!$q;B4#Nv9Yn6Y5H%s^u2eR z_E%W@^mk4B6-$05xu)|rYu?^y+TUsM?Jt`43l@L=$AzZz7VCU`(6oQT+DG3wSymM;hemicA;;_6@S%rP3Mi4-ndKq zko(%EA#w2tn=k7AJcTUt@a(${toLt^)A!?VN1{XxM|MnnZ9U$-KhP&gX~z3H+C`2f)_ne$Ja3+9 z|Mj!x`4?OB@CT;-f~D_$-HxXJTI>10M7yll{hy~TU?2Un`YXR^+Fw-b_TSd*yYXjs z4IN9KXQurP*1q^j(|*>{lb@wszI)&AY0dmeGq_hwHT}=G?rT%i{w7P#yxX+jw&daO z(k}GhWz`Xw?`it)we*mmqh0vWIq2%Qe`KD&X06Ma$A!*IHa>9WwCZ_c`u~h-C-2yb z$Nut}{_eh|M?GfR-(ktspE2!ct^3`-qg}>z#o#*X-fnDs^<2|`g>?=-Zra~w=}SLr z+Ammg_>-pn^_ITz%6;8M@KtKPKb^d;*X%DRa z|4Q?`)&I}AX})XGe>Lq&9{!=`tGQX1ACY$EZO`CcH}m$-44uHzpTGE)rvG6}4v%RU zI!}L_mfMYf` zRnxv@@ztOH7Tup$TI;)M+P~kDS3hjp-}E=T{ru;qJ+Sus7r#-{f5tjrzS*?zTXcTh zv|q8Fe};C&C!2bG-);EkbH7#7zhL$M5z~IwlB+*r+Bd9m{g!Eev9<2^eVd;D>%4o`v|qFI`IrBfy8l0Dt=H7FKV!+;chfHOaK+&HH2$oAW1fGd zr4Ri1CpG;~TKjZv+D}=0_;aTH`z?9?|CsiPsgu~8v#( z`JZSPI?ugT>r0CVRcXqWH4#gez5`CX;BJ8`zx(|`jR)BbvJq6Pnv%IB<(`~ofcm`Yue{CeNMf_ zJpb~)qMv_>CAW8J7e0UTLs~Aq+pObnnCE}ZlEYv47ER~<)_MJU)Bd3!>zMy?MlvkrQY?8p78n~(DdJ8*-M`??O*!sn!fJs#>T%i?ax~4_0qR$`fvHmdVODL z7nYVrGp7n0ie!;Te{+^-phL?8jb&vd2P3ML0>yGzFO#3IT`T4MEe~Tq=@B2Yb z=d8t_g=v4z(p!GYv^(FSzpHPl8ynBkF7x>TE8gSm4{7?(TKx9iru{=!e}2`pzr)%` zfBJ_toy3wGo2LD3*17*fv@7{(#gqKs&GXj0MSo4x|J1{cGn@#)ct$p$1rv053|35>!$lIshsu|?vhW=}RMCiYGO>}^-$8`Yip zD7@iLoV?oq>f-vr$PG6hJacAT-7c!V{qcU5Z&yyQ#dZ5lUcV{mH$}as{(D~Bd&uv% z^ojRd!j19kE(OJOR{4ATGuL&?*>rC_*&Xj~XGL}Dp=+o1w`NsVj<=^pwmlkMQ~!EM z{vp4V7e}L_+U8fARegpZqZGh| zKQ0(>d^kZSZNASE&t}uvXmoD3n3mN!`G+Csdm+n_dsWCRMoDV*Fg{WbeXrF;Ck^t< zbBnSJn8zxxD5gD%W_h=Zx3QI2! znGmOp?Oyk3&-csGXntpx#osyDm#z7*{H1z5pFB~uW;sa0+AEy8@RH1{>~)L!n`nTu z+8gxhezxDH?|M;Hxj`C5MdcTX)%V!x%}aO2`PXv#Pj5}nn6>CHKvAT59+g#6WO)>1 zmRO1VJJ<{)pWd#Rtp}!Rdd$qtN27z?3G>#OzUB5wLa&VT+D+pyseCW$@@CxU&4F3# z4s=(fo1Q$`t4rQ8`z!UbxX!X7jGe?SQ)@RI?Tc!i#_+{{#?ZDVY~;meF`U=p3@?xK zDh#tKPx3VLtqD!~a(ZZteKB_Wsdd5RF$Uyd%>z$q{!Fo+z&`Unw zp5BrpE_eJY^r9k3+@vgZ|Mjc-&jhX;*E4oTyyZoCmKUy5yKxZviRPtM4;N*XC1qAc zZcwI7&$-olOR}+3&9*1Iqav9EVc>2lZ6@5%yS2D|F!kc}_9_*}b^D4*oc5HCB$m_L zXWO{W{LUO%xwA9fP4ld{u|Gqj@S^c}b}-)`SG(nSzBQfgj~BmV>_uJkOy*Z^SmcRc zs)ZJ6>0Y*r$erw7cip_YE((e?c**$GL7bmbe-zu(`N6E>=TaIlZ z@Z-bTo)QOI9L@Jh;Kedd%QZ~l64dzz!9n?b4EOtvLbvO#bGD&jR>&`}SdDfH;l+9CSu~HO%ji48#of8mzzs{(xd^E`^xU-0;@Dz| z=i>~HJa$*&F+XKgxRG`0qiWh(rD2A)-Y;`H8V#I{tCqXPL#0(v?AJ*z3O$Pd_7z}vM0~@*DH~~sqa;J=@)gB zIstS2{C_yv&u&y>&Sk!yg>IN;Rlo(Vatnur9ym1nm+QU_!0(@!LH~Lm^eqfw|MZRe zFGl?rqyCF=zhALs2XOiuSS|1JNFR;%rjxm7S69^E`tFCUGSAs}jfE`hY*Mq4@+@`3 z0GXdvMdaJMy4UZ_f(VNfxkVPnFebtyi9<^{Jcj+iOSmZbWnN=Q;AUcN=b(RM&`h9j zf&Dvwn0ii~Cw0x$+7AOu`e3E7_o^Yc>ds$QQI*tH9yn#{^zXm@Ti?LmZ`~u9IXBH> zw@wSEaJfkY)?v$ntmxs4eQ{^M;!<=b+uKLwdI)<^+uY$end?E&t+L2VoUD5~gneOd zhAxB;CfjAjO~ia*Q%p$@=tjdWX_QxvQ$=+VBtacm2idX2y1KyISJcqYVr(^DRHtQ~ zy4FP}>K~NHVtM90^h-CP|Gwj9s9pALvA>d9WG~EYT;3O2!J$?*zL%6v>BHOD3W_*! z^kKc~MiG^9=(-`QZeFIbqnRR93l!~5Zd5mST<`pRM>=p(3FxdW`346pm-i|N!^*E? zPcQl5uVs#tgebDu?YPED*EB11t|LkBn&I_jU(kOl=u6u$=vo*1_6E5Xw8cyAxU5l; zhoL7*yFT(37Sm{@LORQCX-#f3yJakHhRX+;F3o*EEIc<4VmEOk&2)PH7PqGxZuG$P zV7IK)5vpdt^*e5kXf-7-5JtrurEadR z7w*}7$PO3dOrLAHAYqR(W}4AxR>|i(PJ>o|)SYWbbSY`X@(S4@l0$9snKN3WSaqA* z%y!G^&O(GAx+aG{U=|INVU?CiQ6dY2K=wh~Q4(-NwGYSEm_PlCX83=_&Gs&qZWZBG z?OK$6nietR6wAW8;P~T|DQ!KZf07@8-#P2JO=f9c`&C-kL6le;Cl)80HH7T?2{J1J zamPisalDG7w2DG=X-yZ*<+Hy%w~=?UnXa)#)OE@YkW1CctL8gq2O z$M)TDs_l{e^9CPCPb={IT7f_CRR5CX_fIN+K%M9xaY6smm-PFZ^!t_g9eLtLeVtg= z)-a8_zL&EMhi)!hD34F~M5MLAP^?Y=FwdlJR#&l`dI@9huHk?=a$vMrV!6ed4x+8O zUJ&?BiO0q(><;!%|1QCX`(8EKEe%CzWksCEN$olX?pv#ieJ<-#RGX94Kfj$_Z=wo9 zZm1DXxhQgLv5a*|hW)$E07<;p)xL^VX!;qKg&)<4$Bw|=VO>t~a~^?lI;^TWDD<&i z26@HBgb^5v5-0hx#*2|H!fAY|4vMFPwF7WadLE}4q;sOc9V-L7ZDkyj1E5(+GF5k z$k@aLfc$Z|5b`7o$^r+IQ~POVtewy6hubcMGIwKc`hEuA)Vav&PAo!l>#@fV{5aF< zuIPrY*M1<{!&_LD;eJ(?cjDQ>?*3$_3a`n(TptJGq`rgclt<8+cO=A#XoBg^7+dl# za~=_y;$>0op}g1V1$xPj?=5zsxCorUuLwHx6VF&Oj!%c}Mre`m6c|}!-#3!&By`Z& z{HXGrD0h>@cp;BZhgBi?EsHok>IyHwN#_TJAx{GzR{;kzKK_%^i9+9%o@5~+pstNN zbNq3k&az5{C*WBa2QDwU83| z7I~Rdh_9wLZpahRsnaYky*ke_*Ubn3Jn4GXH6g5_IM$OCFS`}gwn8KxxRDWwc~El( zCLHv5V%(T+w734KD;t6}zf4yOj&zpglieHHY%krEpI*gJk(L|C2SRX&$E)Ks&734| zqDdO(do-Xyb;2OEY{C%Od_xSf<|Af^xICh)Onjz0_EXO?nIwJnuYL11=JSE3PVgA> z*$*8naKT}zTJRaj-pX`U@@vF{#qa4miz{E#3m!4O7#`xr} z|3-QNTa&WB`@5AyyX9gda`B;IA}byHT7sL$RuBdjwl#*KDSbd4b*<@43uG=%QO>u7 za41VxUd>h1Y;y|#VB5=OwD zdCPVB)+Tqr6Xpi}cm08;eiA{_-2!Zw-de5N0|RR)n{(CUEu9csM)R+M?VEaNJrW9; zgdEJ)71tdI>Rs{Cguu+lsHKF5&aa}Ko>|#f<=*YTA)#WjpIe=V`F)3g zyo^XOzs%f9WO>_f;KoOvQH*|L-IP^^wDqG&!ZAD%xvt@m-tAh4Mqw~tlxz2XJnEL}S zKXv(Ff6utX@J~qyD3P7IC)mXgwlQvQs=vi}s%MhfT-Z8cg?132k<_i7PI5{ZhdD<7 z5{<#m;aG9VFYi5hgoC$s96YwzK|Cv}V2F`LPK>hIb!@r($xU&l7!D>2xp)?7=Ak~9 z5&1LS6&Wz5D4DaQ)rzvnB)#MT{xpm25`T%7Um;HuoZgloC2X*_*4=I{N#D%244Y<@-vIX6IS7NWj8cxBJ$oNVMo@PVu5C-aGf#D$dWu2*EPUsaZ>F%Xq^ z2)D8i7dbP{=4){W%MmAG>XXwzo=X_Sk#!?J#utaS{PObL;>9AZ(NDM_V3mzR2V+S8 zROve~NOI{PD#5_vGZ2&J27OOT(*H#2cI4fEAP)Xa?7CPVOBK0pS)aXu5VS*B?$`oy zoyZq)kDwEly&Exk$SK&}5pG`NOz}AfJ(NM;4tenVr{KbkxGwBNhWW=4^3ZH^&e)c8 zQ+AcA94le0^T5(u&U(DJ9FeDc%ePbc;;lOWA9af-MKt?=W4dt!SmOxyBs zsBvR(!t-Z0wy#V}tYBoH5e^oS<<>pf2E3$_X*njrZwCkGWKPzqm{c!az4%~7rs3_p>`#tmq7IA3C*=;>u@#21;hbGZW`@s{K3VZbY0Vc&g-G46V)APgr;-TU7 z-X$!n-!{OC!9eVMFu+Oy>Wpo6AzHQHHo)59z&Owj`|l?GwItE3_Z*7eKwG~r(Ex8m z1EHAFz_yM2{(6uV*8gtU-`-K!pDW^*2Hx%SeKeHb5ccOP3j5>5-QW90GB92o+P&w< zB^hYzj~9p6z;pe+qyyqL9Z-YZ55@y!sO`FIa) zQPRyq(gksOxtZK!a1E}0G0bw3n0cjeu)8`@jfse`t4bRI>=}xS?JC-9C@zhW#2)WS`hDoAa<7QII`yNVPHS8QgNxbvayV6%#Bn{@ zu6DB>$;r=i$3x*Dd?0i3{BRP9%5h(0wv+9CGd_3e^aBr_I}0^wqJ0t_2pk~}QjvFOOnug|zw|bcZw)%}mCi*3^unJ3F&nvRQ zmpyS?;roGH^?fYcE@8}z;C=BO1vsIu_C!w}yIFwO86c0ujf>VsAx_4?3XEs-(Cpm@ znzr+R4pryjdRP5sETKxu8%AFab|fqUPkokPuM6=Fg3r?u#2v~@)=0M}`N8fjg8D** zW{{{q$F+*FVB9$g$8n8!IyE6jYT~-Y=681T={D&j;q}SR_QbEY>*#X+7@6wvT&JrG zzq#bk0qjv{PE4>#AX1R|(*5@bKv?S1w+9@ap)?=`$D9`ICXC;Szs| zw~SCk?Nd3tr{R2`g$qfwm~SP@k`Jw98dr+t(PQ{B--KP$2vY z8U_X?w~UMazSj-svx+)v7AI+>0} zYI0Ol4Mdj8d+$TxfXHQ1Ih2(u&?9S2V_u-lBm{*zxSDZlclvwpI}lIi<9;7}40Jg0 zQQpyeLmdkw(&KrVgs|Q|P?;=psklb0cTuH1`x4yLwywxtmq?Uz88D~Xbgv4wG$a#~_> zGL4FZ*?c-n#ho!z`2f39A2so)1VuAZTH3pza1FMnYsa6JZ+w9aMnnm!kYq@$Z1CFyWc-IuU%WIv{m?a*OI>1# zcCM=0&A5fKlU?m975-S?9skm~b7$Lh2vfwEo)u+G41N(59d21qE0|BNGdCoMHiHWi z{FGiw$W~nxeoNP05{i*N;0=xy`rw#oE;(bOjKi@ezA%VTh+7w<#e3FS8}8iTl;zDF z;ZN#7UBMx7DE4`CA#cAKoaZ_ak%YWEE_kQTQ5*9TnE+;GRxWpE`<--uc83^~Z2z|F zGUwM`JC;9XpKu(4+z2=#p{FD-_`@?shg&4#t%@WH!d!h93FtJzC7t!^ydfIf{%!py z-z3T`^w1(m-z#xPEcfQJ%hS2*=}Fb$5WM9QI-ap@LOcRspe_Y(`>jCCBRow0dRYU+ zfjU=mau3bQbRH3N#)XK-6OME;8~|{u2sucHdz75J^yt`FU5HHsNey{e5ZRjNOTA{% znE*G_Ty2{0^yY()jxS!icx`-obMy2!x}NAt$b)QePwgTBu^|K<*L{tB%Oo{*W^)ZO zv{sK$>Nv>g3vgxQ(F!ei;6uyz;2Lg7z<7AA%*)l+>I) zZ!S97T*FfG|2?9r*$6dmv;pZ5%-C%*NuI-6$Ule`=emm;DYzb<`{222o2M_Gz5MX_ zkxQo^J$>;Zxw^{w0>f9ONm>UU2TG6)v+aU>x}ZMv6ZF6^EOP|8QxgwKmg>OhB+xy% z#vk*&3XHw^K|Yoy^)GgWOPWUn3PVhclG8fjmWyz!%5J#+Yxq;#fajHJQSbbxDv!--@CiDIBY0=+=+;}AQ93Ov#cHmhn^CVd|qkLq?HU12Kxv~b~x zBml;bsN{i#jztYH>`iy+`P>b$i;VLMO;!Ms$Uxv0 zQF?wrW`UrLprtMkw%*%bNR;Kg8t+!O_X+JZL=_4kbP}?Vva|+&2(3Ib{$JT43Su!J zMXw5EB;?=76+`|#rXT2NhamxyYr+8$cwvq`lq`(p90_#X-B8BJN_M$yH;`UkgH3f$ z`Wy!}P_Jy~8s0)KdlNcdUEU$Yy;R!&Fs?G?OlN;Q$FemKR zbb3QrG$xUxAj~C5b7b~X_1EtP7cO5G(>NR$R+td;v~)>1S*mjl11s}zP?H+wdatVP z=wxQ}D>snyva>YKkfvGeEX_>j<;1uhO0mv`4?c2wQ_PoS6W3e;OYZV@+CKP(-ips$e&o`%bDQ!W z*&iI<0;k~v$+;Zo3UE(e$%&KZf({-k8L3U8kSza-R}N+WkX?j9k*wn^2b*fi{%wK^ zg$~(-iNuZ3JWf9}zH<7~#WQ0ymfkIk?UZs=12#D%5v0WnEt+1lt;|*eCKK2|x!Xb=h25$y9YUUimcSJP+yUlvGR!4Q zR%uZLerSQr+9>pg5{_d)sYsfsNT;k2atj7t5^e+wXCtY53GpF`!@e8pLn<<;(H31F zP(~6p%NP+|r&@JAL7EUMDoQ@eH(3$fiBFu?MMic-Vi!t3b_~2eYN#jZ4^So?wL~GO zdEjS}X5tgj0m&GscUBdk%$%Kh(*6K1h6@YpXe#HotB)5A(Hsa){3xc(&tCX18y zr*;Bd7-31=6Jn)eNt1OEo!=GpIsi_=Xp~Egvzw~c$!NYc+38?x zyC8Ps#{fPBILRtAVpetjZb^F)_)17z?uo!rdWPHY32C3efC3~69Df8LG&!XAgfuY$ z8KG@{8YEG{#=nPi9TJTY9=RGAwieeVfrjKMzUQp^!9 z`O%KP9cm24yX6qjBY-f+k5hW72gFEguBD)j(@$6t$=w8zqe)U1r18&;Mp_;r2M8iA z!8XNLW1%oTT3N+Yls$nMU)MBIJ($eweyq%T>;sqU7G*4G73xs;u~ijZq!Xqi zoItgg>ub07txFqUcqmpAbXYgmHdv`AHp5;j$I?XJ#eeF_A#CWks zBjv^hhIG3Ym}jo`C9cm_hw#OLDN3jv3X~J1ZOOBu*=&!wWV6VUt zyyw)vuF6`sp487w_KBUR?#KRir604pm!Nuh6q+C$BXhCW+1=~UTC0018Uy?nwV|G; z4i?-X3T)%(Gvw15>+k}qb#*ptKRr-%nMGz`H%GXevbcb7k<=Q^4m%`d3xM%eX4RU( zoTv+Ym^FS1!oLEem?{w~e1|&MTVU-aUe|?Q)}$QZvbc*JM-dJyQ-3;7>Fohj6(<)Z zxp38!g`o{N%X#$s37?$>EpKHrWWn>ojaF?2F%jf|$Y40d=fIih+H*R9{WTy-Ta5ZV z?<2F-xl6~GOmn0nj#3j3vYg_eKgI1{<58TB#Wgt^UF64RTdAdd;L753Q}F}`yK{ii zRLB7qR~(V*NB$5Fmp|3NYjSN#66?M!LbEG4JtEUd4J8!D!yJ&e)lOkxlAdh_?r?^d zR2L~0CbjkUtA~(WraW9r8r>VY)#nr<_b6TzQN{&Ga{Ppr{2IVJZ_l|o_*eS_sjT@Q zNd6rd!2myrWA+>#6=g{7{9d1HCqMfv9x^L|uaa{Rqdd`0nP>3AmV0+7Nv$92)9EMC z0-|y5ldP8G6H*z|_ne)E2ZOSoP$LcZD=0WsPv;ma$krOn3PEJn?T_))GE0M_K-{ay zCL+}lQ5K60oo`J7eeF41*7E>K|g6fCL>G)}_B-KYtUk?L^x0aQ$kD2lt)GCpSUFh9tB>gs+; zyv}BJOBSa6e}+UPQj%6wB0!i?iOANz2LNJp5Bqv{XA?>1Py?cVKoOxjip3uT2ViT>iDko7F|7Dq zV}e#xR8qGC(aH{if?mrr&He+4q%jl6GOAC+I3>s<2x6zO?jRh$ zJx$Y4QuFj^rK~jnK`@pPJ~d7;YGfi-$z-TI7Gd;5Z{VQlY&k7GMW}C1Z{7Qo&N}5j zU9#HJf!LFHm$^3r$(g%^05(1+VR$JxNcf?Bp;7X)W+#Z+Y3815GM6~2zj{o6)o~CA zk-lL>5s`CJAHoQ5xq7HUNo0b}@Qo{_yRiT}#$S9%;ELD4; z*59H-<}hjt^o$_4n!765e|W@9@cu#t8K{fZlGVacSF6VlDzQoEVFEE6`ed&qK~BZx zrX*)G;{)VW-@1mr2c|o@A?LW1=>P+XATB~;gSOe4xnD(2+gK%hh}is0MfsXVsOuD4 zr4PPNhRfKVxfM&P(7_4~Cw69eDzm6@i6tuZ1F5T>0h!yC`2&Zc<}bk~GxRPUY`0e< zm10CLnDs@$HMVhXE~c-Kq_|jGelV)pWcMM`w#)>gmrz?TC$S}uQ>tfKJ?slwMX*1C zuRf>_nl;V}0z+V97hMlk$kG7@kjWRv4<*E@=W}LyOO8JD9OP)VZi zD^Kd8b}0{FX_=WtxS#t@%kUp@BU$`}r+f@{IfZD&yQ&!+ z3;pUIE)@Q@QnO}MvR71Yk*;Ul)`%otmLzrpuleFt{&7zId}t@yW3#3l--^7hpHO-x zL9N%t6(N7guk=DlukLn|jT8{h$NAJA%etjePv7kW2=OeXki1LjZVm*{3oLOqptrYY z-sqyOLs2d^dXCJns(0qoVSIV(dzn=NRb!YQd|1(EglpQ5^ALh^IGlW)3Rtmrd zglET=eSP4@cBIcJzp_q{Hs6Uta&*Xq1hfNVzDd_v%-SIqOS3lW)5C&yxhLHiTQ&F~ z5=lvhy>(w7_|TCCL{g5_BInSZZ;cOsb<%!v5p$pJlK^1nL)Ar(NhU2A!&&q zOiL6Dd}}Rpuh6i~w?N`5Qu46;+~Xc*TiyoDzGe_z3$>cnmL6ctrb;nt4J;P9K*nDk zvsRg1gnOV~)PNlA=#ct0yl`WjpU!|9Y<;i{1U@}2i9#d6q_!OI10U2g**9u;LMP-d zVBhx4bdn25jcrn`Fv1WqX`5zYW?&u` zdtl(3s|IN+c5B9oCz}{RipAtbO?0MZWJ>zp%!Wf28gwVH154$4RZ(w3@}{V#MZ|Me zAjxd^IyGnp@A)zeKCk|&_QwXJq|gPJkMdc}u>_z}Ue>D$kbNy_HUN>nYJyvujGSw8 zl)DZ)FK(-bo4}K);3pj2$ZgWRy61J$KTFjt%RrTXVO3OCJC5trL71Py-F*;(``i*i zby}fKu}RrNp=$+)0eLVu)9t{W1s{(_OB|h}%yxofBZ-Nm@Thn|N~AUD{;hhg^lNvi z!*bWQ#9Q8uC6cYg$Pn_}-YC?^-`#Hy6gF5)_|nzGPmQPNfnFjscNR&@mrQ8X&4apq ztE&i_CMp*IrL@e-z}iz360zre6`QF}N$#1PWcyournyC|+0kJtPBNkxeNbD-_qK-K zuVXblbeU9%uHd6`Yt>Opi%0oEx^R`hc3UnkW}d|I0KHLiRWNbchCq_@?7=T+GL_(W z2%NQ?2F=vV{yK(}jUIS8#zQhjOF}p!5`9|}fYR={-GFXmU`dMU?mlHD1v4u`I{>64 z0q5K!E4sCQp*r#dIqTg3V@h^o%<@P`iM&T-G598IGs5nPv2KZ%)_a~u@}I&h;bRp) zO^Hm?_*vvufYTJgJ0vm@I=k$6>wO?!B(=ZddweS*Y?{60QbN6L4Qf4~Y*pEw`G61Z zI7!J=E-G_Cx>_ndS>4hTH@vL=mYb`}kc`0kAzPS_k@*&51reJTz&vdQ?eKTAlq(%0 zBGxAaKEEY|Qel1Igo`czb`piR=h@9F9^WQuHka(^LZInDW{J6gIAz;(xJ-?4eTqUd zkpQbonTKo_)o zd;qbF#LNI1(c9)8(1mYESHft(wTn6m`s}+0bTc1>j)c9&OpuwcMf^RWi}rZs=GxhpT7cqw@TuLR#9DgRM#koG z4gE<)2}JtvWvNLqErrcO9m+>l{=XUL}BmyLQIGhPqLi zbH*fsi*snrt7PHhwR4a(82>r+TVK@#67J;`Fa+fUl?vl4jt+n)sImd-$J&Rzgidip zmr>|Z`P_(cH5IW*Cve@G40Dv%>v)==Pcmf+q*URO=*Q`2xLsXn0#O44(Z}4-x}9qf z175ELxQJXI)GaS<422rnul>5lJV0C05q`Yr;`7KznDT%-0DaAzkk)s-c=27~l1*07 zM8t5^F8YAIH2`{$lz|LrO@q49?t{eBxCVEj(+3a>fC2;vB>+LGk)W+Us23CQIjO)z z-3R$}lYSo8pur`ANQy<7lHhuEmJ~u24DJSJB_@3Fx*+QA16HTFow@J;cmsB{0*naM zS`(Su8bGA=@ks09E|{_zWf+JEs^+44VlR-IauM}j3aWW)$9e1ZWVU;K8xY#L=WOm? ze~6#NC$s2HAW#&L;gq54RPYI32D_@~8D_9cf)$ z-2n78=S+i!(N~I!9RhgBt`Xh&+~cAcdDY|e8Faq@^ma0%IRQXr(S6p5rHXRPoW;M* zwFR?J`xA>x$WrSXgnlD+nP7XMo`Qmi36n3J=n3l5SaoMtVx;})mRMVS+^7y(XaaXD zpmzcAYa|#NK(Xifn?P=W%nVO~l1WuYt*$)J-vlfTR|Bd6nc+FWuxcTn?{AVaf#efA zdd=q3%4y=O18K3I%Zn*L-7>+S+>6z6EwRzsi@JE%UQ%|EY}bg}7a(1zK>@j8dU{jM zMoMx>B^60s66w=&*e}AOyJE2YWz9~;X?sR|x3X12)xekWvrupm03-Zh2?4cglAqTS zz&@8bC0e9l6PL$`E0Jqds^|5??b^cyiMia8kv^O^S)z})R0|0s*jo6!coX(HdW~QG zEEWqg$3`df6(TquqXcLy zT!$DN41~>k0yDY}vTDu!nw2D40pkSO=0JSM9JiWd7bpkw;^bBl zeR@WMCJX^YWc>7p0(3-4?UsVC#icMI$jut@J^WIRy@@~>Fy;kd)L`l@C*~f0sX|Y{ z3{TMo0EVK(Ud2>Ud&i=quv`?T_o!F^;wdm7nCuz9Lid(nirKD)l!m=-Wcb0x<8nSV z9yp5p%toR5GuqH{Ep%@0=Eb~FRX_VBGzO}iPy|ELcaM*y;etYj+p+|ph|D-Um=JjB zo+(o025I;HN@?)GH6#PR8{y1@C_o@|1ok4vsuc{S1O`HwnFQsNP)mv(b6rhPTNEcP zTs-(DdVMm|sq3a&BeHfug(Nf_$c0P%bb?+gnStpIw=W@>U^^vo&IH;$?RySR)>E?g z6g24F^)^cj%weFAW<^~$#=FJ5o;WZr0_-MFNkE~bxm4=tPQpOC+>v+zJ`hj`Fv!U= zts)Pwur6T$k!&luaxWf{-Ig9jWEEy1V3~5krLgmr2mDTE4R5vzJ`NA5xerMk)uf(i z$=+i00JIRf6$84Xk{4id0##Sn#!99-wd(SUX;~7AN$@0Km764$ z!_^Khz1!tuwu-=du>nOqiE+xcjNssCfJP0VLI&iUsnL28x*a2JTuc3Vj9wnuS=@ls(C>n( zzQ2`}6vY0*_>1_<^H(07E<6$2zt_mr+TD1!V1e9O} z@IO#)%bH!F?g2@b?$_zfU9$-U(>GFgn*k@rB99+7i1+X8RpW_rrg%9*m2f%k+2Gb0 zpV9G|8w)K)EFTOhlp8FoCuMH%qeVBWvYfcFMab{*`@;r71IFD!I<%h~gTx863?P~% zaFL@ji3Dx#q~iiMB_p^JvnaxvGwh^vD3<~LbVv|Yz`13xqfam{iYEc|Msz*qG;meT zx}OBEi`wM{C@jQ};{Izal3E<$=u#kCdiku>Kjj6}mfm)1pANEtNsXV4NyiVwWfp-a z_jo;V!u~4(unHd-Oi-qXI+OtHwr;~mHD*>vFyx7cCxC>Knh#}_^#a)GTuKPUri_Ic zrZ4VNcrz4)Tfv1z`5;CU&`~hCLANrD-}Eolp-$*PE{@?+A*ElRft2nkLjw^PRSk|h zw=SGAH6_0Y)hBSQ?Fy9{B;QFciHH-fG^Kihnp^>)QiM#gVTfaD%?mFGez;d}?}rM} zD!Ov{HRn_@svP@##=Q!#DG!|N_H1&)wL!9$sH^m_Vngyufh0;rTWWofG!)X_`$`Sx zj<#3W0qw!YwcN8^7a|&D--c?gBBH6`s zJ1KRZf*U?^?R+vmbK&&n_%#>LUc10R3NBtjo=~(G%_VbNs~uyH5!iLtGe3+WgJUb( z-rE9|fD{5ZzIx&E=C$$V^XIRgyEfi@lZhlM*sgd4zaO zpHe`P%L*-Lcm)~v))rGWp6?;ShkJ%UAr3)>^-)3{aQTi!vemT=FO-uJR~1sH1Y66Y zbV9g%Z>!>xDYr;5jSNj30b+7qBxUH~T`=`Vl~ik z1ucvWLwzE{5EB*wE*NoqO5hzj)ZJDmh(boE$|+7rY(Q;FTAW11uoNPYow4R{eo(a3 ztpdIIPC~aU_ws_c3uFjk`4JV5)llz(s_Z^4KVecPDFu%*>ga*jt*FM@7ofNKU@FDM zQb9NNjh(H7VtFj!jiKyM%}PswLvg4Sv;Fx#F-D_e17Y3N4e z@_FOz;5K@c25Kosctn%ohp>$8PKaWeWp}XhA@(O=0>Kj$uep9Nh7D^(DY#zwVH(I@M8A?XWtw$^62yK?g zj=*18>3VNEr$W<|8W%Wlrt?<0>$c3M3?SwPT&h8trM9&O7o~k8HXUqVRplN7i?yg0 z0QvOz?1`|sAU}(NLX1-T%}u) zbj2rT*IWGu@lh%7gwzC5DT`7j}Ocmn7|Y##f3zn zGTd0Lb5cgM`b%wIYI8Gw@&j4@+4TqIr`G!5DJ7JFv~$vZLMrJk&jR(OevIpp=Wf+3 zg4;weZ$xAzc58yvyI(w-NvAzFrf*r3zJ)Jh?NY>cj9HrC^s>e@K}}U_{RYBXna;7w zkU?-5i|NWQua^;gow6q$?i=)W)XQFKICu6FbI)@4^>)S%JkOu~(F;IO06Y+x9DojY zt{L!Dy3%laIQK5Uzjpe`a^=IaOR*7QX*##&4Ct3H9w-5>?dpp&0K7nZ3Rg+`n}kqwxp7$B%tVZ1~O;fI&x$Q>Tw#N`-fYx=7t z+3+Z(!_6)oexfD+%#cb_b0REa2>_A=7+RUu9*XW!*Ps#fK%#7_W4VjUs5GcHQi

    Vp-utdGG{lpqgdznnUdXa^^`9J%*04XS8L;FC-5{PBV>SLN4Nr($` zJb+~H_yn$Tl&#j2yp9SK_C@thG0qBA0zoThqe+Q!ryxQ%r_+7GTLUAuS=hi!ajFx; z9COPT=-|~~_E-O|Uo3v0o;qdRvE;dK>kGjSvFpqx@%~Yq61$NT6uUMq=2ps{g zukkfFR2V{DTD|FyMu|He*>uGuaKQOcqQ;C{gMu2vtDvwOQ-9N=A)u4iEdi^@Zaq;F z6H*ivC6_VHiQ0ze?QD~Q4Wy=6rM;1)&s4WZm=ViIeKZjI*-4a2>yB`M*dowH5gd)$ z#6n4fApjpQ5CI<@NOzbq?BjH_*-P{iasZ31ie935J*Q4ER%B8+ZLwGC~E??-7;I2MyMvE4CdPR=GZb*mmG z*UZT=*Hi8TICGQsyy{{6^n_(n=OSiB5|5aj*3R$V8P|xGVB^6vXE3%D)!zPCS^eCw z-<0&5(q2>8*DsRQeTq7Qc3^D~v{Haxq^yLPj7E>mNs1vxgZ1ZhL)Kn2lJ^_DjmL_;cm|!we*WG>b!~KWMW>FrlcF`m5@1^Km?)gbfk^gnycn zy7;-)e=J=8dn{?MyR=H+0n~tice&@*T;3XOL;x_FITx7yw`zFyJix zPog9GwO9m6c>^SzdiRQHR(GB=cyA6kM+!FD8@Q>KQc|W;ohj{`djug*(@W_@J*| z&Wo+x>5S3@*rCpRPkSv%Zmm{8MSUV2Q1|Pln|Xc z8cD^~c`=*pp;cX5{A|{+f*Ss9po`EpT}jhiu3>+!ILT5LRUA>Wu1Kj?4YUt^S@khjiTmS+q$E*> z(Hf2+(<=kRySuOhmu0m(r_=4`h>l48p(a5VN-bP@e^n2;CM@?tXQF})7^56-6{8}# zJ%8-xV>(hd*w~v*=li27sbPOtlsj#1Qc($2>Er=mlC zf7ttOa0mfq79;-8>T6g}s%=8xyWk1-Q@Tcy0@&l2CsB(GmMFkREH4XQEPtKb#_7Mi zAG*S|$=>u9kd}@McL1_VJvzz7!Mjdw0Ulec6Ws~(5BdFJBaIJv-#zU2&c+kfY)S#` zQMPlt+}b#eijqCbxt(HgnSFt%{U1xd70!^_) z7?8^I^NDJSGr;8l`2ZsV?+<1;suhi@+XuThZ#;I(Y=LreohrE_k5rGxw)LSu*6hl; z0i|}`y#$OclBs}ukt3G$IEz?c3o!kX!rfBoofsnxAk=`N5)DHz3>fxo;iRaMqP=Mg z`%O{5sq0@kfhvhEl2ZmfFNtd-h?MJjuO~^rDeX5o{U*4sN6hv5ZNWyK%}K5uh0)Gq z$=0^!WOuOD+t71c+&-9kajJDT*BxxtvDVF9^sty@3Svt5Pede&WE|NX(^sR+B5zBe zm`EW)3n?V0Oo)xPM~IpOGnZ7V3jvR{Oq~ODdQR_CSrsW#47>Ln#vk zMlVOBY!77RmV*<~3+i!!NI^pdRvzd1p_B*b;wn~y?dkz`)l~`>=-H6043e5$BGEk- zv4zDVVq?Gt+?|b1pRZN|6oWNQlcr8%4%8xr#0paFZ4gA16kE4eogR~!zn@|5+nRuG zv|td5z6qx^LZBAhi=skMkyuQ1^6rGheTEyj7IsInyRZajQUqWN@QQX`UdBq;|#}L@xmp0f#?%Wa$2pLB}4T z5`brk?RY^a01R)el0WD23n-ENit@}};9BUpBGAQ;*Y8h^Gi?t`xRL>?Q=TA)5Z+7r zyZlK^=k|0euuPywQ2w`yLCi;KGKd;SBk2+MMn>fTQEVZRm({t198(KbFVvBUlF~V$ zYOX*r9dN>`8>fo>nvb`udVhyI1f9l(M!Zbqd8JEX=}adf-z|N{v0G*{$ysnhHc$%u zE+BBEh#aT?no~LZqnhh5)eK;};}DQsO}#?&1Fw+)iy%{pYV%E&%Hk3NXje}}nN2+q zG}30;(MU;?9+!xseaP&OMhc|9yxQ<;UlPS(^j=ysheW#}y(W7p0Uv zz+O}pXXPi^8h?DlC{W}`rNVuKudRr!+w{Qs-tC$Syx->Y^{1|!Haq!F5ID-Z+Zl^sn>xc&#g$|H|XZnKgAlUdfk)p3YN*+|`);)fQRadFWs8z$x9l-B- zkSVM%&=&RE2J$qqPWGSk2He{NDuCWsfz%#5>i_?X$41h9ni4JBV0+X#J@IgaGgr zR87Rxt*q^VDbL;>UHv-4{xCYT4LGA=l^VvBY$Oo60<1iitO)ux*#UZ7EF?U0K@uZ~ z#9EN37MJ|gRnrHGtPGIku0`UG#HX8nVw|8{4d|gc8GUY(8Q3hiGr7p^FD{%Zh}a1QblpNg3v)|K4v6cy6ZRqGe1Cd zpy|Mkj*)V|K#=sr`d&-5nw6zp~ zVDD{56i}8?z4SG|+a15auoI+&R$-V$gm(|yRT6D6*!Jlo;tAo)-9wVCa8lTo(x5-K z?$iyqhd>IivFS=h3J~g2TkkxKV$;7@fjQP}XpSe3qVZsaQj5>dq8o_9==M=fD0YA= zf)UpqrF$aELAP zectVMSxthnzHK9zOt=R>P8Z!LK7ep|(vfqoaP4HSL+`#FfqHRAqhT#=+VBPF0bqup z?Gl&{i&*}`AtO@DDmxlA^E1nG0T!F#zS)!?U&W7RRRcl;K@|YY9@Yah)taLI{bXPt zo2Gumqxl9H0vUv=a81&S(470uRcUsdmvE=?MO74fNpRF1I=f^Jwb!N&(K)Vi^QvI7x^{7?M+aZV zMamU63z>43H?p<@DO~nkAN9+&thz9nsj_{o9YS<<1d38!M}()5(K~qLJ41?YKT{#> z+ib$V`zSmq7+8|jA<#P^AsRWL&UQZA3c*c1OzrX+jV??VMU??uq=+Cfd8h~gTv|8# zRTh{Qt%Ye-YwjL)V9)n}D@V$>b`<<73rvgNRp1jQx7Dr2?1U(j*iQ;7`9yS3HK4oI z54CC>?AOU?^ay`8C6b#1Fiwkv=s#RJh+b+0b_pLXx!#D7-qf1DbGQQd1?GTMYQ&Ch zePSg?_k??Eh91uDPi7^swPnOMXON*2rL~-u^#y#EJ`jm6>OzAJy5bUePS9P zyxAwN+uG&^y%|GbK%pV-DxM2Wx9NtO$+&sVGtx%cK3zwWy6R*+S0L?)!_9}l0it+H znA2nvbly+Q>tv}aFXnuY6PR;{aJM`|*P}Q=geI&7YPZMBSAD|W#pJAGyLcO;3YnIG zZBq6Kpy0Okr0Mwb?VuRXum)%Q8W)(?S@JrgSOe9h1Pjra0#@`J1wgs&6&%cbi`PMF z;vz$A1#pg(zS7chRo}sm;x;8g-N4v`yXFDHub6zr3z$rs?n)fu7~{hZ))1($Co`v} za3LfeRM>S?0-0>-DrJ@;LVyUQ1)0Yb_+9bk*vvAokxK=xA-R~KITwzBQd{v_!fVu< z&r}Ei7R#!n_$#?MQW9WY7gOHTmuo&4=ML8`667Kf2`P4P$cyC^(4S0Dhp29dW#0wO zsHP5I4(F?79Chqsguo58_MJgtx?!r&iS1{56zxr>x5~$6Cel*Hb+jKyo0@fHdhNpI zxzlII7thAyG1%yn{ct>f)wyq^i%FWmXdoLBD^S#u_tYj~eZyb(OXXgY)WAqn2vskG z8cPL68$v^8(>vp)f`ycm%EJo(9fdqdjav6vMOfRyR$)<6k_dY&L5n0d6D-dPtsX_V z=6BJW-z9pP8lyxIBr)YZbgX}05 z72CPOj9$q6&dD7F%UI8GS?OWztO;(F8@L~riQ2iZgvMMBJw;u?_F zW43(L(Jt4h^^(FWBmx_uTo}sZV(oARx%n3+m&jfBKF$ zn?-RTwbd+Jn?Z)voh564S{D<(#{Y2pkY1sBZPKi@HiO6_j8`d*4@o71eoD3eB}T8w zK2hEBFR^!_W1632I8C7&%D)oS4B{Bk?8JFChruvsDBn?+GZu(}j^cBIOu+gimSlHI z4s^CX#!`hJ6&}G9k`=5;P>_5{DOEMF6|`FKU$4wL3G^QKZK|SpiQ|KXbHw*`nwNZ^ zvVLrCavTc+&b0O?j2jsPRdFj2DiII3%pw*>rmXr%r6SE|^@($S;>COY&D%amO zZU!KDppPQ2T##`{$?MWQGyp-_Qxsc1qR~pt*hvZ#;AET8Z@{c2F_A% z;Na{x#X14~_=$12*x00m4+mUrsUD>#!x7r@#)}J2VRA6#G1>QW8!sBfcXsIb3j!qFDiT=acr3R z`2ESHLKYTE{4Mw|8kDQ!)1ezRK)wR06yYd6@w$^X0wzAUXc7=8f7Cu;kr#rW9N39% z%B|eGL3a?S6;!@~pO$+x!P)rrq$o~m8F!BBO#@VxD#9V5^<2?GQtod3lW2Sc{su>! zkX26QOsW*e;tuQR03EfcuOtWk{T~hJPCg%Q5&{zA?4P@#)U2b3kHj~~Jsk8NTC-|rdXths+`6}khk{l{_A5DW#KI7C!wvH=S}MNrwknH60*ola zfQAVyys>bs>Bd}{Le;BSKNF1dQi*^ox53_BoB>0HW{f)2jVjUy-;Mxa?T8g|492u7 z|D|k-$a4PC_dVO|YlJ;ME1+Pop$32qX9i<;(WgUQo{Fk+1GL?7Aw>Svim|vd<EiZu`@b4;SCbd=I<*;UV5P_^ek z9FacBZsbz2OH5_76P&{o^d;T~fl^{yCt0Su8HkKQAnMs;wZ7&qHCtcdn4DQLu= z@ofCtLqmQQP4!jDQ*4|~;OJ6ul8{X7v;jyH>o!Y2zS|uFQlpws4{y!yn~9Qs9DHI0 zDh+^h>lxM;-mJtnO7RKS5}X!7J@|8ZkJ8V~rw6k_a-Fq#n^+2E=05UiQsIEb4T1$6 zsN>X*7IB%gp_^RCC(&2{jvc)|z%_6xF>8jR`Rl>$X`U%048tf?195>^1=oyn6lj0e zCc-0U_j!0$mFK4GwNbah5<>%VJ7?vu{zP_6Qdl5V6gZvkj;8aJvQ+5jIHiz&pk`vg zN0kXeaZp+#7{IU?Abwg>Hg;95i)LO5N>E6xDz5azlv<9}Lp`?3F8AWl@sUVPGZcQp zLo+K2v$!M#wMxiN|-iN1iu|JLq|Q48|G*&Tbr5Z6x=f{SMJqLKaI;9CFDUKlfD|efM>=FX8n+$Uy)uxxDR{I?y9!Ahi5G2yv)OcTr(jn#2u-{#Eh3l(a7wpcIl%Dk| z)kK)N)C0Bx_y(|I+go8!t5wH{xG!2m1{@*Nhw9fywSko5$-kitK1OmQPB)7v>(hlJt`PT}%{ zD^@Me3BSi+gOSDIG}cau1q+dnW@}d6$(tO5nTM8BY;7np;ELo_G4AFaDJFH@)+c1^ z0|O9K9!KAKL9+P`C_(B%rAR_fYAyLrx)*9HHRd_tF%|auSi)*n?|lo3 ztgkzFULCCnP-0jVz0H7n#~vfqWCdTl^JYijbng@c;pv@MwKw|agt|TALAy|8dyndW z$gbkkz!7=OOH@}Nc~G%%-KYB=^tgWyiu>24xNm!mmE5$faJ|3x`Wuc(na`N7U!Q$KA>63xKH5Cmft_omq5IMh@( z$5LiQxRN?u)Qlm&9ku~V;P}+4>c*mPz674uF12Hch{g_cd}-}_$i8JJy-bE7EL`?u6ZzS7U%k$%tn-=>N zT9i`Pl4KZz>)-`ooE@7Sg&Ua@ z!g#@XoZ*=%2$Q0Q^YQ!V>;6&kae_ma4!UIm!U;vCxF0iiZPGc${Q1&BwHTB;6Tp=W zrX!3C0AS!96XOIq7C~V?Z30w71|~9~aARIOQ2|n9gOt-2QfsGBmC_w&=JG3x!e9aV z@^>8rbb|P6D=&#CM0uI;tX^TrQ5Y<8C=aat=(88agDo1%lH-jlfh) zp5d`&LMSDK7ZX`YNf11pNEm{?L873W$L?jMxkm;LsvxlyLNkICM=((hq*j?A_hYQL zp{Y!>&CuB_#5(z9fFm>|QSP|2ndp9+NI@0CKu<}nNi%peDsfp*qxZN}sa7s~+qU!u z0oo+4I-C|1^eMGR@#quaIhyQZ=_MR`hwi36Wn0Pi&1!Mc8SuEfp*!7EOb}BXotiM9 zPSqeA3T~u|P(12>@|=TRxw=*O?o@cK3XGz^M5cj}z{Yp+&QnJ2xO9zRU(N&Qv)5&B z0fSaiFNXhfz2gIz!vR0yud zkD%LRiz8X_<>R$>sKI>PZkvt4Y!6ZQf!QI*guFu%H%Ux8CiOs+8DX-V#1zUSff*A8 z+*glFM%=fM0o8!QE;+FKK;h#2IWCz!)ECH*j!J|hRe}iVjX?A}CYe|{le5D!u6;@( z5i(2xUO1`@2mQ=zPGutq5QFrY=y}kx$%rPDh}gg5Zl`o{zzZ#QP|78^AmD;vkmIg~ zqSYuyfRz=%*`=9FtPhUAwR7n?mk0!YXtE=gw}r|ZDr+D8a)8Gmt^rdqs0Vdrd1Of$ z?cMT>eWcn3aC5V&A3jj->O=3h>WX(}W%hJNl^1gS1Vy9dx}&$$;<7oE#x1bZR$tE0 zDH-AsJ3}oiAc`9cg1PgsRlxMez3E0c{B4|-RoPfw`*s_=23^i095$0e!0>-NDn&{U z^!;jWX$_30!q-{$lqDn74-cdpSA_2rmF=cE)akD%J}5VUmeU`|Me;-ln8$7cD2El1 zG617C)Jr)tzz@Nkut3?N3J0mpH5F82sfet%&|+DShFYTpvA|OZ4^M6?D;Luc7CF^X zh|cBCkvq0g=~#}4GpgqbD^Fj10m`hgAv#40PJU2mEoIT|)n$jep&kQsbh_h#kZT+< z`B>?wJ(Sp$c~;_J^v&)ozBK5FvR$o2r-h`Hfq&|UfXA^!9cmr>0x-X56pM)%K%9|X zdFb|Anx2$<);1S{r-*XQHI4i;akQV?ASrnXo}1iy?C}F!l{yLIq|t_4dPxt-LQ0%g zga%uJ?{FA?Y`jz*H#NBlGM+_#f$gYH7MPl>fnv!D_l3T|-ChD%uU8#y_lWT8!r2*{oe7ycx zs^`G6Qv7ACOYPoNp=&^=kt9X|Fv>JiX|Ykh?uH~udPx9aZW*J{0U&F1kh>z8u-P%w zBhT4T3%&PlNXFor5&MWHOx(6Fl^l9dyvLnOg4C+WCxhYtWADwH+c>gyZU2~k`ypx` z?v5;5ZJl=84ohvvcZH~tghc{007{~N{drbqR-uMW3bY?_>NO+z!A9NyRZqds8o%K3<3LebkfVoo8wOe!8pm_>6y-Vv1s@tFDrHCy zdNZ0+%YqzQ;zd6Xh1q1tjviCMr+QG6n*OgQU)PbCU+m7kq zX9TD>!8bCVwJfn~3SQ$=(SaxQm;{8v4c1`@C7cl!;Fqmc5-HGESop}wod~Rfxdmge-_touo5qw5>6v;^ykf?Yh(eH$xv&8%fA;Z3@q$eI~ zZpi~RVC*U2ndJZA3#tAtc+l<}5yf{z7_hO_)*xY1H$MM{h!>c1piUxXnih6@Y5|gM zvt6oaXw7dR_~vu$==i$+^TkRe|l2)I~?M;$*T88A=9~LCNp4z)z_u33l z?9E%zu}X8`u{UR+MhkxSxn%yabpEM)UeM3yU(5~SfZGU*hX+8@LEFqHND15zwG9g4+1S?6MtEV^rI%B zWcCsg>}G?vejU)cXgnyf8{tqmTtqBAU{H9};Bn%h&%a%I6m(||GNi#!;3Oe0Mtz#M;Cat>E1e{rv!NNoK92v@gj_J%z{n9DqwDG(!3{8o zk0s14@^|Mf8p{vdh7=rD25BLvXeW6TOGqz%sr*N8tT_a|2cC33!#tyazhl44l5#Z{ z`2bzueX~c;`_;q4zxcx(uR!bxUR+vAKtFd{!M*ov;b<7%w3@0)i(chO%^|B0h8ddI zsR+bLH4|l;XUY4)l^$g}cQ&8I4>I>`4hm`=#5bWiOeHNU3gi2>Bu9tWDa#7wbn^H> zcV2C8#w~PcH^2}V9^&J=IzctG?Sn|bk{|Jrng{iXcB-r*PAM8y$n%6NdXgH zUXV{gOHc4*Ql00wD2^tG%-{{)q1D1D{k(hEYh9a103~Az5e}k5bRL6W8IO|%1MXT( z>TIhGi)LTTuXpP%7k}D?InW=hr z=ME9{3t;l*H(0LD@|uXl#c?IKQqlw2Y(-OyztA5i?Ida`?eFSOJ*|23)XmdhM3I3s zgOGGUk*|i@gdu9R3?obFltzRV9VvPR$<(3}iDew`lv+};-#l`R^r{vzi2S$iFF!Re zHWYCGd|YuCm{2q{=rI>Y6arlGxaOf7(`!3U;P=PTYff!zvY~;VBKw8+TP38e`&7iS zV+HrCo$M?9B?*dcqiU_f+zES;Pf-8}S~u;F94s#%S9i66!6D#XW(`?|I-bnu zGnHfjecpI zK)_;xPqlCdPR*wpJDJRby>YCV*Z3hQ*d`^-ffJriEVQK#RZED{ZlAWZ{_IZ$GlQWZe5Idc%r2wEPpYo0x0nh$1SOYc1r zAczYTbo)y6W9Xb%?3CJEoApQKjqHBzJP|NyBuYy98<2;`(-|L!rt4|mMqjqFwsf)zA)3(Zb4(bH~DkK#5f4AwOp~DJrSWy6myRarGc$38skF)c@GMgJa3K_AVhLZhNKOyu zo16R0wjlJqI7f}H2nx#pbUcio>16LC5BHfYPhFkD5{#I8%Cewf1wl)Kv@L&5?#anW zG(3}i>|CQraVaQEu}#F#vsG&;hMb;s%YFwIusq7){2c6z=2j`SA?O8JCA}I_h#BAN zdBqT?!5Zuj^D`It=rIuG6o-|Z!Ne-$b7m{?%~b~Yx27`rU+0*zQm{`p`fux21J%pAzqE)D@CPpxy*E;kCOnY1(fIt={ z^6iUX%wL@!au0Y;S`Td-oVf-xX^|C4K!ifF7G(H_YDSH6hBjt`*pf7iEvyE~Jdwzr zJQ``6c8M9%QDkaxBCZn1#4E)^b8QR>yP7Zf3s~h2Okgs&QXP}j+jM8Ye)K;5NuEIJ!564 zM^McMXs@Tah5Y$|g3Ke1g@j0l<QlLV3`-P4Qff2aI z0I32lnk1u|1y^5d3IRfb8V-%JfZRvaUc#3A{FL?!}>(NynZS05FVgl-h} znJf+SR^woi2IYYo5V28)ErtjYoA-}0Kp09tfAflAH4Yf+S7g;_o~ zuaeLY$X5O`@P@$-B;npk>Kn>u(6G?o0+5U>)ijK@)j6a} zYUp(j3=y`c?U)xz8klLJe#@Qf&vl#uDl`1n^cf5vge{I4?f;Lv;)Y9;)JB)6U8>hq z+GMdfK^<`ztl<>tHhP(`FM2i(h+S>zf~1H^judP^1%$CDaAx>=fJ;x@Be`gO9wKBs zQ0gEt>z?%8_&hMCO{Zj^n^2y?V$pAhI5k2eg*+IK&f*jwIB)yq5Oae;MZPA9$#Ls# zPJMHZ29w>DObICi(HJlk66;+f81^ zLkjVcxWLg5{P2xWNs36y9h7hy)ODeu03!#zh?$G0zLxQ@6Te`8^E_Po&a9sLT2bW* zz4#gGZ_@M9<;CY;i}Vy{VhT_|F4W@*;82r>0b&btne#%;SE2Imnn__HrgNBTMdd@w z*QcfCXHE544`p&WaY<8s1IU5aPQc?(KI>3w_U$0l-!2>Yg_>p2Vm9eJX2h{9CGEjA zWTPYMX*U zLyO^{#+2!NX+%X`J*61YGFo9l($rjdcOl_C+Owot%(Z=ic+{A}HbzSt5@6B8g;~-p zJz1?PCbduiUwM_??)8i?)m*Yjc7h--Xl4MNF;xO&GnwriW)y81ByMz6C^PQXmmT+R z>|vNrC`E=1U8HF|~6KCj}YJ%bSM*jaRi$c9Df=Lp;dKS zRQd4_m?c_3gqCQ&!AF+YCO~O_jw+S~uSawq)tF^=B~~kl>0P2DLuvx(EMbq__i-@{ z8FaKW0t_9vhcwYUz02(^a^Opn!At220v=|2dSm>z#V$CfHPeIUg-}OHv$`$e5E}?lD=1&I>ybJEG&MdQ66@ETuDi7Hqd1%#r4U&w-pjuV`DX>cnAgf?I4hT+e6cd-gtdH7q@g0p>L~L;&iAlOPQm2?@mDjDrOvMrp)$(c?yGaILPDI5z2Kyll^W4YA^4@nci8 zKk?V)rqb-W;N4+FN3n+%ikMvM*kXWpdZ7z-^x&Rp*UiPEC{FYT{Q&*gWn51$)`H70 z19-)#c1HI3emC73WHiuR_sgKhZJi9Ug}wZFS3Mo#>#v+(8*RuCB2D0jw82fUeD1V7 z@5+a>_-fPD&lTGFr74$Mae~m@^xBq0d7xIAhL~kw~`m2HD&YX`a`%f;+FQ;b?&MQd(Tts7}wgz zvy>|z7T&qSEJ+LYTttCDTqu?~`;~YCDBP{?7iIj{hqiw74((Tmpl+TVH6x}rt=}4@ zL9eR+2e+p5a}-smM#Az`BLT0Fi?b6!>9F5FE!H>NVD*^ko+IxYBm`GWGCB8)^wS^7 z{&NwV(R93F{0HL&01Th{YdRnpgpHD2*B%gFOpW*pTrjk=0Fj}O&3^XW^@jHiL`RE! z|9P|fyxN&7oxL=UTpY|8!q3z%M4EhHo{FI%gXMtA;OvkAomOnU5Uzb%(Opt)Q9l23 z6&;?S58LA519APS*fJe(qVTMMJ42jRL(28A!R=5YjRmKoBu&S1iU^eH4IUpPu$?ur9e_oT9rYDVLDLTEv z(rswFKkgMuWp}%}=S4%^Ev_qLOXC1|CyHZ9(4{nG(q4OLQVkJV0QlJ|iqo_H3uh&8 zY_o@RMbt0!b0*)=jg!nwGduAka&ls6P|*NDBh1*$TB<3ogO4ZC$r2Ug7}9nS0ieVC z0zpye6rw9qZQz;Qe&9mJ(p2tR{Z{!^7Q^MlEyA5zW#~+U7Kz5gWwX1M{6<&!_;ecdc5Jc~d|s zfs{K<9^iaE+_@gX)MPkGnR8ani2I4t(k&J<$s^kO z5E&CP4QV}BLGK#U{26EBBv zh=u}^vTEYFza8`B*77}a8jw)b1vIHCVkgG>IM14^lalljWpYXoUg%3f1Fxtf+;N{% ze|P_+_-(P^0M1YYYC;ZUn$a!aO(Et|R@i%xKZv2!sgZD`aET;niX?aH>B)Y^*Uj0> zri7{n-WnQqa{M9JXid*9Uq5Nk>A{N2ETp)D8gf}_gLdrNe0^)(qx85RuuA0oy{dx# z{p7{P`ukKynBXYa@@ViffXCYpo3sKq*uI)SB?xvU~cDb)go+u->4e>l08+iCW53V(Lzv< z%3n>p$*F4!2lEEABa(PRXNqXLx<*yZgEoJyCt?3A5(jsGq3cDkZ$HQPt#%Q; zZ$#m6g^^P!n?2n2i|k`i-z87J_RQ!yIsS<}`Q{#~-fuTILJP1g9{0B! zn*W{_(M|Iwq^qBeeXSn1A7P9K7PhR5yXM29@HU&9FnQ89a7+e1{bpB)z@uFGZV`X* zS6H@Be&SZOlZNz2wh770+Kv-#)~D>4^Yg z#nJcG(?0Tj^|;;dtI6bkJD0PYHKJ$fpO3%;?lo^icJy5y@Ubt;ldNu$;@*B}?iR_1 zn?Heq>cN!9<#@~ePU8Gd?tF(!#CNNgx7DJ`KJWhc_(!EiJ^SWiyMcwYSlw^PU2FCY zF4*#FYG{KWe_x#K6`X{kr6k_mCOZvVQ^ z^sbY+-son-{4365v7lxC%)gO-1Flcr+uSc&|F1I3o;15l;Cdr=y^*-y$Xsvu&Nn>Q zJ095yA+uw%yRVnbo%G}5uDp3Llk~`&%#Fu#&%WDyeq4Y2@Q1!lWA_(z_ScT4IvtG| zTRVQynA!1*#*~j=G)8>@e?M&Qo@nHYA+uqNv7Et5 z0A=}{ohiyXfPwAnw$Ta(w?ruOkqd09hb75@{a?T)_~%XguzVQ&iB`+-L;USvs`6ZK z_^vl14A3!dD+a)x6K96n--sNqCyv)MYjRx{y(Q<4)v~;5|14z3_9S)UdINTV<(pq$ z{pOp))9ZuB*`kYYyYw^ic2HsOtez$^(5I9H@YURbNS8c{x_(yo3@-Uok*?bQhsx_US&R z--wiwJh&`TV6S0Ghv&Z$nH7LvZ~3!pM(7{pS-_-juq!0~kav;}elHI@lH(Xpei$?Q z2FYt;Zh1)X?oo^M=v_?fFw(tIiH4jH!(3>g*6r$MculON$7&A%OtE+H=g$v&Zba05 zmFzKf*~c4^EfArThm)Bu(2iau>243Ig{aES3_#q#gH#YUH7H1vfc%~UJ#p{>VQfyE zzX7PYS?901zk>L#Y4`W6zNN~47khRD*p)~hbKkPM0NG~(_olz6!^m=>k%DFW{OtHJ zeD769TD8j*+QI@ZIwGS5oqPf@PSQ?_!j=}9k!NAl7mTifNhJ9N#2lpU5XGT091aydMIjUl z7)%fGblMH+uYxU)DcaK$%^~#$>`f-J0q7m&5Pzf@oOWiBO8Z+7W2WSQ7%sFeFE>_^ zR|1m+>J1kdu(t_-;#zE*zS1nr(Y1h%f5}q%P5(KV`(V?#kx+|L{Kga!3-qm$lVp&?49~Wtu$8mq9WksCzAi1 zRw{WRxqsRwm{@(`akxmS*W40-Zi^jACO><1yLoN?VdxAf*)Dl# z*T*|7gscaRH^Tl8@es!5R5UPC-4@z3NaK^vjMLPOsfj>Bg4==<7nej4?6z3%4m&=5t0xdrWKXzc@9rkN__-}+L}ws;ESf9QX{+VU@%&~h6;sY7e~ z)O-dsp-eNk5wulJ8(LYgVMBVOT|hxr2CGf{yU+uUTJhl$r+!1Nsqt}0rVXovhBNew z8S8Pie}Ah$Aa@%q=VI|*Fbi^}dKy=qE>))mWlUG|S(fB4+s)0kxL4-m?V9?M+}ZFy zZmPW1kwI5a;Oa>+{`g8EaYH-0RFe9_?`%sSw4ON)q zT>upb2q`kkDzT zJ}+jsqh3+{?3qHt@Dk5oI5WzuqHqoAc5K#W-j938um`?%*!{=|QsWZS@hqE@^lE~f zC~&_UmY-1zk?WPNvGYiihTHu?8v{b@`f0H+B|&rzirtWE6lkvp$2dD8J&bS{cC(Ad z6^&_rxe+zzL_moeAXQ9Tn8{xR9Ug}-_h4&mEc!J2X!IZ~VpeO!I z@0|%)4^RwAE?S~Aln&;#So$L-@A4=aax8iqas+VEoP$>y=`3YAUf3N#SF@rqw+@kX zOA&EZw{*UGsc$qEl|#z(m0(svH9`pAYlupH)KM`gX2voD&>0dY=SY$BkwBE2y3D#H zfT(;g0k&TSxbOz>@hmqzI;1|A_m85poG=*B6hky!v$(o>^rg%-+_eR=L7)YZ#f}>7 zjOBe&Et0Gw@m1DABvO+OP~*{(nX2h9<4~!mqYM4Ke1DJ{ixpo~Bz+A$oFAwU>5bfM`h!mr zc?d3SvCusb(*J<+@PdjGxrL+-p!ADXjp?2OQ$ z$Pp4G;ltLV7v^OPg)~8ff;Jk;V75RXYG*(@$p7^im;VJt#A7IUQCQ2ufR_X&%HM{T zN|3$_3DcTMIx4e&vI&M7 zsB7ks%NnIvTLMJ_i_#elembVe(D zSc4*l6F)4;?!r@eSeFtVf>@n)1E~gT0a%OP;{Fy92DK%rpw&lPp-j0dicXc8p)XSK zq|6ba0+-Q?g-(kR{J6{jAw%U=V5SjLN1UBPq%zRw#MH5LxCo13UDYV%#E?S<9$GAu zE#=u9Af|+2Po(w>nMBO&SqxVc@cakX4{J)5dHF%)e5dwUo#G`uXr}-@WPSOIOtDJ- zj@S->0OVIp~`Tm zgd?_s8mqAy+#ahP-F9ZCyZd0%Ktz>#Dc}y)_3$nsiVuCphTyV z4MRI&UxdOSdJTK1SX8c-;tdfhmA-;<5fF=0TX1H!V9oF_--PQF1}9((Y|Ig%oWug^ z9@QN#|7y0Irj{G+$J*AVtEWUqy3va%aJeysxhhA;3Wg8h5lO!@2OfmPc#bfqq!7eH zL;H7(W>ckfLB=UU66~+>FhNbzu`c3t9Dw2$az|bmQ-buNGbyMXgeHZdlZ+NBL%ej< z>+sSAk0TcM-?D(!B3|(d2jpm^+u?GGd{p_;({dKh!u^hva5 zkVWySP#pXt>r+smjYR8ZW_55WYAs+2^yj|%HT%C87YR!)suGL>0LoO~Zc&tEqD zjw?$vRmZXw1)@Vum9#!W>*z^z1tQwv@L`!c^n6P>GY+2v-fFV2rtKKONgS7^gH7Ew zrOL;fn`WmGG(pWRKW!eD_e~+{gOIgEq9_OM4K2=07cT!6WD|uA4@xvht)-~Q9cY8= zKsM>ci#HO9?-B&>9w?vosU0TeFKR*x(-(Is9B8PI)kx=(Pv}uoj&i%W|B22I#HuI> z;)agT;Gd1Dpvn}Ch+>F_046bu6bOS0FMwyE%ABFx4*8kB0d@%acH%svf;J5_%;qsJyee0TFlVuNT(8LUQ7@BpAE{NH z>@#akg!`zV!H5fJ0pvn=V`yl^C|M|wSOQu@6`p#l>i_*HiwG7iI5Dt-P*al|G8Ya} zVnSJkzFnDZs6kL&8Ept;oMr=PDg9#YfRIYfT1`CudeUAD#!nKn>#|JB`ixS;Ck2PAauoE(iA2qfgRyG$U=BH#UkHYL-pECmlOvj zNX0_?Xtcuh6{^{CnN!+SAe2L-0NEJfbDbu}0C-GSteQj;e6jx#uiX=_D42r^LbY>t z1vY})1w|+v8wo}WjXH=EjE4&}4j+-ub|eeQU*;*K_{_Vn76ODddI^|Iwp>!!hHZ(y z)iFpn0i6rfB{1c#8a&hE-M;ISm7H}3j|x(Rtf-{*l3IHq24Otu-CJyF3)nXMJ?fah zc7OizSl+FwVf3Oqv zLI&KQUU~%_Wt)aOs)8oCV3V$=3|jL|+H%L{C6@ODS7`1P522__VqpNexCo~L^Z{;& zj7O0DKySUtN$G^gYXIy9wRLdU*iRrIq0Iqi&onP|P5?S!v9oDi6K}}p5rJDB)MOcE&Wd0Vi_7z za)U&m-nH~6&AUADSOFHeln{wpAJ&@!k`Nf3yZsl>(&A^15ey;GLm+JgOU3Q0`WFas z?l-vRl4B^5zlAP>_78%vQn5Q9aspxkhm+X%s4?9%%N^-`zT0}#J_U^o8V=`5*A@r! z0E_Ryj~ylexI-kGDVE?qg~T`Nv6*wK89K}v&7>5Jm9(aBhItGpo8Nr)b6= z-rgS(c^xf6mtfn~l!iRvX38dOHU+#KID2t+aF0nG<7Oyt@oR70l*yoir(MNk>qdEC zu)@xL24yQ79&BRpGR0`E*$y$`mntyA2xvg-PTZ2FT^1cIItni&pC#G{pv{sW^T%4) zABTGv;ghZDt*ek6cIpsU$s=DywiDcTk8O4&HV*U2qF39c<|R+GSkR?5?tmC)4lL-2 zLs{mEuw>wbv=AZscpoe*P|SxUwxic^9G*-J-fRz&q|sG%b4uPR>N5;|owe;G!)Zz0 zJ2RZK)+8n{6%Y(T1e^r~k8!@FOlrw5_mA|#mWr9&fnLo=CypzB9LI(4H-yd*k+NTO zwBe-C$0=98xqsL{^$AxLh4`AJ%3J6Hjga55`%zBEiV$t8K7e(KabM`Hq9?Y*gGX9a z-_Ox{Ihho~{y*TH?6|3@_df_W0U0hL5vZUGbk%)fvF_u53+wo>Qv=YU%Lnu&icg(S zL)z7fahhxz6Kf+420oj0O9CcFm&x3u@MzIkKR#Xhh65tSlp2*-~KOP}Wno>08KhuEPK2$I%4eH>eJ6_8#fZ{<=(qWChXOonZtjjaJ<(3;KiCloA!j-JMCm=N+L?g)~lHesJ z3tcKn-hce~^S7^lT>kv#&Aad4FWNo2wC>{Q=RV6zmh|EM=3~<%gV@L;zopF(hbqBC zwe7S{bRkfD#EOmrw!;E)196?{5 zfMN>d>tqj^O2NF^?ah^{^fQf0nM}qg?sKvZxPYF^mLgKNEcHM&Y>2!?9%>C)}Mvm+~91A-thC-DJU=D^Tc z#`J#*fV~u=0dgpKF7TNe$+QFsQRgW!q+RDkMXr03R4ck#uDD?!f@ zS0t;bF-?HF7sgVqMA}iK-4Dma$H!p}$)crkOUq9jcFqVTi417Hh>#{QypUDM59AB7 z(?H}nojF~3-=LTe_5IC9>9Ow1{Hz4Bn-Kd$H&4t{vAWHqNNDP&z7Hlo1}scAP}gN9 zQOXHl42&`S!BC3i;Ei?em1?4f7xf|CnF3N5xx+BTKn(>TrUWAaSm+s(5n!4Z05V5o z5bc+#g?JI*n8S7M&5)(%z_Q+HL;oj)&Bl$0FoH0frx`R+a7!KB2%KROMj@*U$1?F~ z-Wo-UXZ9~^7Xm9h;>2(OpUfqpZJnivR#FE68Pax_K+m>L8E6>>tIp-PJ!BZ!(Wb52J(L6~QkY_=Gg?<+}qx`nB_>PHp z+2W>21`aQ_Py!U8v>7~+uUs(=kpZPazCmgxYH3zgSCWe$#!?cJA&CY*6{(DlNaDSk zncfJ)5?MtR2bfchE{lZ>0Qk?xzAd1G(yI}go7{2oRQ@G>Mu*-3xxmPPdy_T` zY5?UZO*G}-iZ7(9&)h&h0k|ct-CZWmfiJ{vYV!1ZXkGqAVnsA&6w(hp`&}b-!3Gj2 zAg%&LO~}6M?p%}AI?<#y$VZ>o|E8Zg5ZE=4lcnaA+N%Cz%Hp1of{}+V;}o_rG3aNk zVN8OUaY95;jNA=Ff>~|=PgBN=(+MU2g&vV3yL_I-nK(pJje$$6X#)?U#HQOgNHic4 z3tbz`KeQ`I?o9)($tE4RWWzJSXh4Y98<2S&j*|*46pA(cC-4MPk?tL2D;%%iea=S+ zt8P42wTlnycyj2+FTt6RVk4z*NsVG^j52p_!3yR7FlWfVk1EbtP^ z7}NkB>70???hq(mNm>kgDm+btCG78&lJV3I8pEQTf@5LIh~Wfnh_{HT$m}*&tp&hH zBLIE8Fq%PRA_IqXJ26IL~c%}FF-D>x62MZqq8}b5nm^3Ptr`l^F zIj!;L$9DJy>yxsH!%qV{VJ__s82(Y*Z^<$AnHm0&n)|zby?NYYpA;z>*Dio~;mxLv z9Hqag?^>|qf%Hag$*Nz*h(q*`a|1tUO_79HZ!%!>9N2JG{nqGiNk35!iO0ZgWJrS3 zl|{QKJayY zc30uZ3o9>Y#;ZM|<{^8tf)ZN*D|ed`RZP{qsG1#0VS0iTTXBNM-D-q?(bDou`t|Em zq((_u64}t+n1hz6CT-a?YD|}bWx~&MTR>{+oZ@gyI>c-GI*TIhf@j?)`9+I6@H4Z#9Bp&`HCkrc z_!8AhehvQz#0x(e`^iQDi79jlV5#UGq$Q)#z$e>#hzwzls`0@#t3DugzB)nvjO z6HXB*4{4FA*~+7|@7!{vS6;eyR!V6$li)lf#u_o+^&8_PheNXS_)ox86Nx>xRPB+ZI=c)+~%A{-?kjcqZb`WrKMj6cC(U92oDVQ zF>@;CzGjNsmZe}BQB9gNHFrdnR>MbsQcyxIkBkT`Z@m`^7~R@YrpL|VhW_^j%zXDm z*&mI_p$C;xlLlI7 zMQWBjN-kWy36kb5F;}Oiur^;Lc^|p^{(GUbB#7T^-$oCQI}v^d_ES|f6QnQ`5R~*Dlp|_4 zUV`e$owPI3t47*OGEcPE2X^=EL=l7{RgT~7(Wa6BTOOjk1e@n4#(RCwwx!7WGeoe& zfsjRxN)r3%H z>@}itBq;!ylu)Cnm1^;za@M>CkoYMp|2u(_^t(Z1gfnUsVo0`oPrkNrkYU~UTI<6w zHfcWqoIid3;k_9=rXOuo;3iA%?AB`hn)=RMXIXs+Mhm zhtq&if;%-PA)Zj~)pgFVUWf)Vg65bHuoI%9+R%sTDbnWxPHZMfS~j2p{S?w@NtWsT z;PwN+-0%l}%1ruBT$B_pFSN>}ZbJ2&mgttIe5mFq^{VgKt(($LlzF7&c1|*0H zuxt)8*?lY+4(Fn_*0*KV)xJV;${!|6A=_ZwJ&_HPn*;XB*e>j;M=%Y;6yXzr1r_94f3t0+f*e{#i92eoi?g8Bi zeBl%W(;m0$m^)u=Bw~aQQWQDSIf8Yp&?6xZ!64qA@ITZn;u@I(G;wk`Bz5T4Pi{+q zYi6I;|D#krkRODrgFLpU_)9Y)Pcz3HS+uWi^WXphq2z_YOvz;$2++jlP4b`cK0>n? zAg@N*3ym;yM~SrW2XGd^8Awi7$P;Aqn{i!rg0v5hCG{WG*ecK;iIMA~NT6ZY2GBcz z38Nhp`q8BK>+tqs0eu#{e^44e6uKs^z9AM8HJSjG6dH_S2n!|+ZHNpz*1<^_i6rp4 zB;M<;oXOrhDsvQmW#92VeKDh z%X$WQ#D1*t&Da4X+8kLqvAbcHOX5&C7K=sk%yE@tnE(C;ct}YGq^ethA$j8!JzbN7 zw%WP<{4dKLfoniKoz@<5y0pS}aI~Qi-R14Mh~VMULm*g1cT!XM@5>$~8 zGNDMnQyyXZv4JlYs%&0Ke5MCtd^{jM70m_sA@qx!uBr6b{tUblg(^z86v+|IAUobU z%dYaxSKsR)1OT&x0uyN=n%JhBp=B@BwzVS;KfqxxWmIq?H%8)ru0D=g7(U#II=|IP z!p|Bhkh{+cQn&Q=Yxab%KK3|RNXFBb-R3P$iN<;j`cb7~lL?KS0Z?`w+W zD$)uKajMf`&Zt=R)a0fpY%v-G|70xCVeC_a%Z&O$lQpEy(Aer?(4#e9ZRdwcR0qu- z4C?Tiq1Z(-)u&eoY30#CTLMAjvyldasMk*2HO>vGJm~8ql+d7s5F<)jp>+4495%P; z0GphV%j0PlB#Tp2$0^(8llbgQB{LmKRDT47&kZVmRc9Im|F$+6I2y*v2K+n;7-U>^hJ=tY26KfGz-)9 zf7o9JX`dO)q7cOj6vfb~q?n1%C(%hpKX|jd7b8AWNu}8{B6tOI!uTYm zp1)Lv?yK8v_?f_Y2UN!VTZ|~n3#w#vzJmw}gXhGMv=71=*<_ePSgA}GV!t&d77hkI z_s>eOxzb0j*EQM>nL5e5^~tSC;%m^(VvaK<^u|I#r)ikGCB-yoclzI*db1C_?8+}W z;%1kZrS~@^<)Wg&_RI1E0Ra5eEcK&FxpT{d1l=Bt3}Mn1P!@R;M~)22v?^l;Tsh-} z!7{7IM)IWdO$~^OCbb{|?;}TWrnSuH-A8&E%=0srYqY~&J73W}Ukp%4Ws3G)QZw)Y z1z~4a9rUmh4`5Q3pu7X#vVeOqrWZHp8dQ)Qr!yxJJRzKx7}iV)&-5nB(n;Ezh0mhZ z_3h@f3_ArQCgVwYA+$u{%|;zbbaLT)>^6!}>cLPs=MX7_iQ)Pb@KfKC1rK;xCs`BI zV_wD(qeKJ=2FuysqML`y;Ec-zu|a>Q$2YxAJu^K2b8R3cTr;A7Uae;N`2Pt<0VG3N2Y7wZ79$A$9D==yvLx#Bo|h&tK30>w zWH@h*R?73?l3Wp8F?G}=#@}h%R3+Rq}Jcdw*2~S12`5eTtK6Wh??v9%#NIj zz$b7p_Exq7y{aZF^n?urAO__fm_KYFF4(jdHOC_wr_AlK3>1$|&<=ro2+$nPdb(+w znDLMc6je*iRx&ik3LT&AHji6a=_Hmc~CQU`&2ab!-#zns&YIM1OlQGBK$)uq9eT}4pgw(WE}-)&L2t=YU^j; zKDNKZV5D#KcbTMldq+nEbyZ4Ww<-8Q8ggrd6|=hOyZ=s>aOO94iT87=AKR=YN2KN| z?2h59qXby?)-+5{gfoE8zHS zo3ymxD^Q-t3#33f1@c=q68R1E+gup}zJRNH0rM-q9*VQkspKl6zO+k0*1&g2x)FN*tcT0 zsy+nXtJ}?M^ACBF@8pm|Zb=sAwu~r>V6q#(q(st8U5q)o!*G~QvP}|M4k}>TZJG?S z(y&U4ra{;8RP*W>?vdXYADX4qT{#jgz{CfYbU^{PHyS;9r;c_{>&g#aZB_P9ZF{=j zYdF**K;8hj8bn&XsxoSPFI(`;AUh~P$`@#G1c;ER=knE|CZMrtqw;FXFiex`IS#rH zDjq0UR#xbq8CvipQH!z_O{`~Al@1sjAuK{;gqel0^PAaj& z9o#-Xu?UGyDDuf!vm>B)H3~ss=A7+oC)~R)&@aRF2T4rn5NS$G9&T{Afw%-VU)BH# zP8yFM_9xo+Yt%hujFLcw8K~`oUnzF_*MQCa5Ne3B27ZwVHNNLxYU@#9h*8~OXC!|f zQAh{TMvI(lA)VD82**BLzL<1+S|Lm8d_f0*sGnNCr4}K(+Hih3wtoqm4!f-xjBcLH zppj%8C^U&e*XE)3a!f8_T;}gv8_YHQLos#9=*fRfi!|_?nD~gQL(-CA>zvDz42PC! zJw}_JK{fA+KAZ;dvZ{(|+94pJZzK*1vM@R#8M-4v>OX5WrTvBMA#`vkiAJ@l#yGF( zKdHKlQ*{jiMNC?U)EHYY$!mEqdVuxMAu^IAPzgsouC{**sZIAFnh-ektv<7kBWN)Y0rd8=%8y_G(hqmCWXPeN;K%{W zJ|?O62$P{w1k3J|aVEad!Ks7%ZVV8$%(b9Esb01-uaRsNHSU*6-Z(a3M)j1fMBb;nn5Z7U@Hr3OXAfA$czm zb$g1n%>Z60dDhekWU-|0CB$}%2-HbU!h-&6&xe4Vs*K57xM{TH0xVd+p@pSiPzX*H zW*uzdw}@eEpMHKYE)Bp$BD;zb49r-EC+mQ#AA7JW0p-y6tw|m*!I^)waFwJx&78M0 z4u3JNOK`SPR->?o_5_ul$zpf`A|}w-QsSYlj{lCh3~%t1&V z*B{nk^p~BZz;_`4O)At~5F>=<#C-R%WeuwhQek-;12TfF_x$}Q6M}w|RboCw^oG+j zjU)-O44rv%Y>WLW0J?JqhHcOkGtdI!_Tdr%lt4$5N5utQhwiivt2!B&2`Yg4A`>{k zP`9vHL|poY=1ueK)A+P&nan1n_{6=G61q z^gI!eJD#}1*mwQgKt@fLWB?50UInueakFS(0l7}Qtg0h=)>FWe?D}8U6-|3lKqDZg zwr%NR9z-Q>+8tulqzX!!2)NZqQecn;^_+M8l@> zzaxKb}BU_xEwfhe9iMBe|4qf2p=0zZq&h%9r4O#tDk<;kX&{OGqM-re~hP_rF*!` zIZx@}ov`wgG*UDVx43GML?XBgj-gvS4pgwdKmBu*2DGzGiirWjMtqqvvwaGkv8*W9 zQ5r`qm*P2->-H%;lJKOYq;7r^)U269D>GVVRg*`Fm@Yk zFidwNSte@p@xH0+r__`RX8G?Jt!(-yA^&39gSt`oa@o8?_ACnlQdj?Y73}?xC%f^kcXMja9dI!!^!dx zU>_`T+*#y`@Moq08KA5Mc1`AdaL9ABp=9C&A}8Se0C>nG%B9*fb##qEutd3I7kHFw z1m~)X&t{>4-vFFk`>2ws7*ui;q#dQ`SKto}->5nn*ZNM?0@B#Sz%c$2%$ ziFQ12BUJWH!eX3TAAzm>Yyh@0*$LPW9#?m@-pa&nWG;n4i-cMk(`^Wx!6fB+f5*~! zHG}DOAiT}TqP%NhdTBnJ;Ud{CtRFO8kTGSeG^SLVJJ4OB1sNsDgny|xXM8Va>q;Mr zJxQB&_KW_#^Fzsc4W%Gp|17cw8NCEbP$(qST>9$qAQ(Z!njyFlnqk61brmmL1p=oU z1n8a+inUCWK1^G?op+<~}tf8^ghVJPt0lmUQ4#6zLuetlq zWodK*RV^9)<)8Y&5o#>#M z_B}lUs%#c?SWV^508cXRj32|k^R!epSZf&&90st`1@N9m0dA`0f%iloSfQUyDVwRv6gOR`AI$TQYy*mQH)8W?PE}?PIDA2Vr7fx_J0!rjY z;Pftn7PiT*QO@Dh_a{HefHPY>#tkB!3&lW#^kjiYly>JsTH;9h)Z$wI2YPlf^ekyT z0FNFj$8h$gJ>Q{88(6&C@d{M2fZ-K*t*DI@ml}%)&zbCMOB%-`LG07H*QfDM5F1^I zSaHk0!S<;8RPJKv zb=mFh3pr~Mk!I?_iHMA3*ty?dJc&BN3_I3COTS&W*@_f5~c-&{?Z^@Y|ESz6~ zVaY|^&!;eMkert}!k{!6{hZ!kARkSpHOB4Y^OyEb-lAnI?PL*j%9S{lm@&-j){-yI=GI3fOH*>Z-D%6nX z*m}Y)hX4YMDXXleUz2=S?M;%umW<*sU@%U>WF7Qyb+bp)k>ioSrUL+8G`#H-Szj$; zoZdG(sT8FD(!URM-)!_%1E~;F;GoN&)ow%~N_buh+Ra(=CZq7u+C=ErK){Er8^Xfq z(&^}=pH`IGXXb>h6YkIE4jGZLEX<{CmrRySdi`4J)abdQ{MXl&9qdc}bzQlII?F%Y z+aQpe(M_T>Br3viRRTo*hVpccC6MdCiE=ufAuuAjq(CBgK| zCXV10fI7Yos*>K;#xzFsg9*N4_LPU~M+ZF8g+ne|;-2A~W^q}(rgsm;x{Jrn8bjX^ zKynn9Z5<#)+9iyRRz9r>pbFFEM>Qo>WJu7SA3TV2)5jo+p+StHeG&C2lL@DtEI7I0>-d-YL=n3y!7ZNlaURioxSAQQWQi) zuY>=&P@C#;MIye$OyuWJn|Cy=X7a)kF*dn!_@CisE15dbtn`U)hYXG$w__0t7@kLj zIpP1lQ96uJCxj6lTriVVP%IA~pnl*%J}yj6ax*z}k3@W=p}5unx;*x)O8fvaYA;$) zXP$y=3^_VOf$OK;3{99}c`};i;#ev{rIXy5F3qJud@)L4Nrsh~4xMyXB57)_qOT&& z5~_KOMj|b@r1Q%NMccpWs#|HJhhB=d8(L@#9{0a%nh@}BLsdtL6)jC-rZrcul*fHb zmucOIxbjl{0}VWgilK=@Kan8@3f5V4kB%Yu1XD^8NeB@SDUJg|p|?&G=quI(f0Bnx z4HrGVu3Hmk3H)5pVsJ7j3V$}ITC>mNY;*GMT z9j7U4Xv1W1a&52rB?(a2(6UP&Tk5-`YRWUq25S@g3 z2J>_*rO#7dF%5eGtutta!Yl-{w;5GO2B5!&3%Ik&ioR`h%}bJh0G2y?XxD@5PeDh? zY!;r*1q|n@qmrPOyh|zmc;a<){{V<^38BSmcY8eFZSt=?O;prdaSGXLkRmY2Xu`5au_m-%4G_OzI5npUzXLZ*7W6kZ}EcSvfwsZvdD(ZUO9D(5doT*Kr6 zeG7oP4QogkQyf{dKpmtt))G5_wN-}+OE550I^@7KJP`&bG|VPGMP4# zwH=Zbr5-OEq;%56fMX+6LxeBKfZD%$ii{v$vJce7*okw))A7}>f*c`KA8nHW!6iAY zeYVRcH(0KkmfX03^}UTcT6tx{dPm{}99*b*q}0tdr1Uat{IMT>2D42k^3A%~KW>|7 zzq)U7l`E6Kc#uL+5OXux&^_f?FM)vf+!_?a+`Ju?(MM=U2g#&7dchZ zqLqZ{B(d-^`Kn`ad`Mg2m+FXcARG=`6Vm9%93&Goe+{>Y!UWn!Nh`!RC0U+s19$X= z4L}-hD98a$Qek!qdZ^$Li$Pos=lH3FNGymCkUOC0ku)$Z&2s_2zCDC!Pqe2|85K#s z<^AKGAAT&zJ_1x(mOvpxc?lClou7?B6iN%B?KK;M0p>=cQKM(lBbIQ6Ato1YYf-C+p?}i+%i18OcM{OiyaK?_kAKwvc!xR;>J(ek zB@S6s%$5L9hK{+YH`IAXFEv`tFy2C0NGG}f45~F+fme`zmc zOk5kfVTgn7C=2<}31Yxiip^z1K-8vTiaW-c1 zX|gfX$)7YqQ#Wv9(aUb))QdKSGKFfbu7FVqadJJ(W6tLbv0w|%l*D)qMNZLmWjbgs zQ_0GJ@A9KQ!uw60aK71+tf5>W@k?2N+AQ%Buo?ejzdvrcCLV0#VgR+vA7^F+d;G|Gc(D+0}<6u)q?FxR@wJVHp?^RyITR~+K z<5U16d&V+BUlqKlkJLv>XSZP=wmP%hjLE32Z|b)$k=qcN9$nhJhIE_dYY{X(rjF*0wrFSdIzO4gwo`u!o0eI7I+1oG!Cz)%W-L{#QM zOGGo!ykmQ;f|d?PzJR!5UJ$#pl!-zn%ghpf4fhP=1|8>Y%n9%Uq(JG%Ai3N3N}fy) zSfKvnwWML*n{`#}Wqoing)}j$lnRYG0d(Mcg&qTUAM5oLldXHr8?L#y|+Dlf0gQ0HH#gxtu3pA0t~=?zatfJuEkkCGYv$09_B(PX4N& z*2>bDtkFTl8&miDYJdAPWnx9JJFt6Mi7*>`9QbzVTY8rLlVGd4NaFbUDXTo#x~*H=@?tWJ@{?R#t}dt1JS=|sbD-QMP?(}Z6b14OA!ivsj4zFdad*d?Jdg#QFiE-|8oTV8J7})2`jtkJsoK?w0pFWXX9*#slex))&(G8u}c7s%jqU)o>~p zhL{fWu!0D#g-Cu>&$bj*&+4$Mar0>R$x>iklyObs$J2z+_B{FS!wT#Fj-OJiII#MU z=qYvS@89L$7=aC7(29La}%9$A)*WgboQ^b?)S3^7KEThy{Ze&R88 zCwFWB{mJoAXLi+`{e_uYnKKP~9ndNWejo)c)HO&!C2y5`nrGnrXusJk+vd|D^M)2` z)X=C#DxmQ4Y?cytiDc*}JAqK*5GdM0g?GmTIQRo*OeR~}UGRntnd~4y~q}Ltdy^F<(jBg*F2A%+P>zL!)1Ie z{RwMdKsW4iN!O06+1bUg{td|g24XIf2?2>N@?i8MX>Z3N*Qi(JAoj?MyPFN79JlvA zeKvP@4KC2_Mxj6`;KQ1a9Yy82oF<%wOn>Svo$!w*tDQZ8ZZH+>AHrK6{$u%Cw|I9x zui3Fe_?ME(N5NicxpbA8lm3FGxIT7#Rp9b!*F`N9UT8U_S+t=>%VuT<^i~N*j`{Xja0M zHv&nV3sEH53HGCx)kz~g6*jcTkdP@l#PwxS zScrrgxMxUPm~;hIqC+P8g2mJTglu4fDhN~v7_=I* z?x6v@(@B$%9(zcjQ!rTol%UWXFR!^d**&b#iXovxGT@CuV3>!Kfc(caW@H}`nSvCj z3$X1PuP^&_GW<_8x%>jnS7O|0&%hjd>kN-nX%$i1-=xG^n|pI;aGoN<_-ZS_-s<05 zG3Z>TyRvO14)$IN$P|fzG-uo6xeepy|Qo4x4sfq~>8AkWz-R)+(ry5&*z+JB-!1mE?q4_at=x&EA`Z?XtV9APt7J1;! z9zx&K{Ej7@xoo;{m5w2Il?3%vu_Dt&tqe*NsWFg$G{EM5y1&dbIvK(G&IIJp*LqJR zp{N~%)O25n@%)x2x4T`n`=8g}u`auyk1&eQnuTe8&6FjCbrgUBNPvO{hpMx(j%j<@ z{)C3A^de?p5NQ@}hjj^IkDdqY7FYJQYTs=3^tJcSY+JI3i5M^m(4~Ry)~mpg@xSbv zL;P}~cL`X_Nk_bJ#BqYgtEfv>nQ*I9e^C3~`13&~KvEMe{*y=Y8~?rQ9^(O)QF{kuGxG!TCEW=;fAJ-?+i0Yz>?Hh=70 zd_{$7S3GzzKzYP&TqIy=DG}oCz*uSUTVLG^4^X>w%9*!35jycLW*5h^-v#@L>xHUZn!U(pmH3QGdkN(6Ler?)8 z?#X>vt@yfF{CCptYJ>_G9IsC&RfX3-m?aqZYvX7~g+ygiM@-AHa$ax-QuxGZy=^lf zUmlPRb3Hf}W3)ponOC^|o(`#33Q^Ly3)>7J*qTzA#4KNZ*+D4er!|d+B`qzela2?} zB3fmp*f`;3z{(_PAJ;2NiNlJb*!a%QgB##}eX`eno6zE>w@|B&>UaPDPp|&<_O%Y= zrsEmJkCY9hVh+tESib#A>NkpdlZPTk#4pGNH6wRK;)~YYfoseL;ro2Y$-2zf*%h z$V*q-rw7tf>O(&@pZ>+icsvI5Le-G;2iYlDp`(^QzN3-7RF-1JSQtdV6{x=KdlZ*; zHzY#uVO*$CfCr|EC(rTiYZy=kLIPG8f~I7WL%WI-6GsYIWz|qxrg@K5U?Lm` z-s&>vE~EMfGc;|1zyRQo880!&8D?RvT27)ZqHu(Zg$5ETl-4Vu7~3eatNv4+9`$0; z3sU2r4+W|FkMf5c_uanUJnnx40iY(xVTGpTA7B}Ts*OJMq;EZT0Qg=u`%!@vg5^Fd z!O;V-bmADa7Jw|4<^)1{_@4NG_WDLNpL?Di~Yz=;*?Y-}>$pE=kRimx7QvLh!3>h!!J%kDk~V-+WA9SEpc zwms5_tNO=geY3xH4N+4*D&(rcjFw>zB0C7$CdAkyk10=}gGCFc?JkYR?rm?Il(AE% z={SQe`!bT`of;-qD{k)|mBw-mD`^9Af!%=ILRbStlibT_bvsbXg3aGyxd`o;X=EtPCms_{?bnZ}pLN z%}5&ZoN>xxif(&vfNq=Z+u>6ie@RsaKdyEwb`$c%`VZL+f=s=tdH9w)2vmW_qM^0i zJm?ns5L;B`6-`^xy_Gx%hE*USh`Ixc^~ff)z5$#Bnxskc1l1$#q2L|-d|4NF%?FCl zs+WVUOZ^_+SC^2$`=rNXPi6mAU3clIlLs<;p8>U^+7+}_m9*fMfM0TNXBtyvbKMK; zyko#5<35DgF^w_yJ@TdNUA0|3?0ru?YxQ@o>3X+Hn4qacVpn__T*wfCU2`8H*;O>y zQ4}a>+G1mYqy$N$)~Du?6=k#VJ9|E7-97Ind^T72U7U9elwjP4U?BPwX)<@^W%5`i zx}jxL^zB15cEw&1l4nA!8#Fe)nLaVeT<}#M(0^2zC=NouuXYk`x{O&Ghd?uLK-sn7 zMk9-h&FgU|xo#4_6nG$KW|Gl9)R)E)tV&WCr;rq(kq=;xoHzHC$#hnGETxU1&p%9Y z6M<3{VTr7tK&Z(j<>eij+`APaiNv!tx#%i($$bTOfH3oaJ#`MD!-n=jz%9?ZlqfY6D6zy`~u`99B0{=MW) zF}Sr4Z*tQT0*MT-?gdfNxdFG`HzK*09bKWZp0FeNZZmri059g>2nU`PJJp=Wbq@=}s(~o8CkT2om!-X`2(0tF;x8Rfb2QP;h~helrE{LD_qlgTGtkvWoknx_NS!y> zv{he!h$GKST?K&y?h0Fa%Ixzf&ZDYV6R9(SCB;!J%x&19Lh1lvM#jYp8hQ>0AIX<< z1T;A4UjYMz?#UuHV@XR2O_4m4IDn%b(RtG9XHGlfpyOL)tRbti36O$PHs<%arBS}U z_BO@Hcsjfmo?n?PVNroUqGgW#AI;h$JHnZdFF)dPpLYoMgCo%c8$_(b*WQ&LZ99Xl zz`7?1S&eolD0VRd^c5t2171tY%J9{ky}`DKFAleH#6!q2?GmO529^8ZxSql*ZXtTfxt3XGU(4ZVCzyj$M#?&_e)zJ$tW$ zam_s%=Ph}=nvLewUQt7UMb-%ag1yqRQHDCEaLMDs^`_IxI1>Ar^ZZUaks z_3-CsCgxu$_xe}{bl9~|kA$)N5Hj%(wX<>7 z71R?=uZrMjVq3xD1fA)t!-J|KCVAV<2yuB zE#k9vl~fR786o2FHaLMl4t59YHfRXW%_hj|7Ip{pm;)q9MC#+b)sY=pWUo zBk#xe)e@?a4bmox&44=J@L%35{Vx*aK}2IJ^#Ft#Nm4yXL&n2)^$~Uy9un102z?T6 zl3pZ5R;CA$bUXvV=z>2N!b%Y6Swl}^n`R`}!-a2_8*7wkj5IK4jEqVaS>AI~yxH|j z79{4?ZYAKltB(=pSKI6$jgMH4e!mkQnRy=4QU;aoW1UMcHew1OB5Ehd>$! z+zK71@CZuZG36>KFQhjwrHeUg7skOwY7bQ+tXGPNviKaNDx?a3?k@G?=F>b_drYE1 zs8(b^^;mO+=v9oY&KMGEp(B$8HsU^0v7hOr!D7=*Oy!v@Pa&*JVOLVH!5zj7s1gF^@d04tT5Z0I`BQN6U5di6-nDzkY)a(j(iFnDWb=(Nv0g zWu1cn@^cEg=f=-R%eCE19AgL(5dfXLTYZ#}GopZqF+fKG9?L8|+X;rpX0Eh60;eOj-Dl2 zA|E#O6C{_}YF#Zi6)Sq%&^@t3;DgBklMN;nHe)i4l$&);s@s)bz8yp%`8cg0K7j&3 zS`zvs+q*gFMp$JnS@{%J>Js^tyrLBr$td#lA^e=chN+ku*Gg~(5XBI*;l5B$APeT5 zyXXNaTswdKW9|=Y{#y4erQrvDckyI1^26LE+%FJ!1BX15qd!gWkXrR_2@>CNOIv@{+s& z77-a;vVUCx(MIrbrqQ9b&;7u8TDf6Z9lFfJ&}2?>dwx`ce1P8J6y@x4#oo&<3*mf& z%ntqY0Xg!sA(g^0dh|}z=7E&ydR67W$j`Uyc9RJ(Tj&5eGY&r?PYu0lP30IW$8#4= zc+65Ugp$J!?pA9N2P|>w&U<75Z5QqvJ?|K(A6$C~x&w}c zax!ytQ0sJf4_K=Aw-B@sy&UIvjycISQY!(x(o8C}1oBBseTovxG$pLv1?^0o;)#WE z(Dc**oB=1RP&0y;?TLgYuS?>~^`3=QwnA&~u92B2Jz_wN52TzraQ_dvtY-5+gIxAm z&kB$V&r2r_u6!7BDD&Unz(|XuFHMP1R$^G{wnM|%7-`Ql7MQ229n^L zqnb_*B+b!iYv7842&qK>s-{g0TIzh!wPv_TiV_VCqTB346F^mZaKNpZm3;163Y4(F}jFlhh5Q9#CVjmsQ{y&)!L37dml^Cqs5by-qqNC;PZe#>NKT zTmE}3e3#3AH2Yth8_bn5!6wc>gzz% z@!HD>U!sNQ`gD&^P5tUy@s6y5`{tfCHii|P_pr%_o?00vR~L}vYws>PHuZ6v`W%O) zTrLHVamie@upkwql7^z$K)Mz2whSq3WNP}dwxw72yg_4y9CvQ}%cTu!>R%a$X~2ly~(xOFv;)4d7C zX4-laxQZF-Wvizb=2>Y!p$}=HbbN|B?n%>*)Wn zcV=yF8|R)sAI8^wurHUgmc&o&SYye_%-rz7QcyEylN~OWlutjuw*auoCQwykQMsC& zW2q%|gFvB{clj@4g_R^lmOGYw{Hp(DgnYk%ccDl$d=P=s^L1spYo%Kr8Htjv$`Dos z!yV(zq`Mpc4Hc2(rHTlt;3F6_c@Jn9g$gnQ>JxBmi$OM^=dhmbB7<}@!|}dqweXeN z3B&s$o$bGWsC6)8Ls_38fIP2D{Cps2J!TojzyLNmqD71XbE9sS&Hktz*!$UN-%Exy zHMyDSO+P}t7`KYHMnoE6y^8$+|2-t9P`nebiPMshk_wIh6h$FI<98F6+RXK|TzYc0)IbdKoLo@t6YLKfk42uEMOU>z(=& z`y*&%s~ShK{m^sZewr@ByDUNpJ9bAoQM0uj0l>K_@&weFfn4$nPTFPL@bDQR#e$~z z2p{9MT@S)g?%oUg41-^4S9)iukks7eujJPlxvicfu5sPWrxIE;M#K#kTT(}Krkx?y zWeC3y;IG4z*b!w1!%t_?bO@MQajli~T|i-laB654pN^W&gQ5UaxUsg0VT1P$k27xgC~ zpvpNv=#DQA+JyHt=>mC?MqMwx5>!)u&~3Jn*rEHRTSqAZF@e8wNeZ;51XGzMZ)! zX1KeTq0Asg+E3ThB?)E5tH19N>H1_#xP#5}E%4Bo1P3W`1Q2FIP|_La^UMSly;}V_ zWy`&^#4_O~zm`8-0zf+YP8hxml@|D$$b&mhW)!C8XMo!^QY-P+nr+a*^sg5M{@fxC zdhg+&edAs1!R~zituQ+zVN9ggl)UGcQp_P)hw70T*>yqFF&!F$x&RZ4VJ29$oraBI zvLr}PH}ADcAGXjb`$K54I9GTP`3}9dF3cAv6LCzN>4R#?P-$&D!+TIPoF5d&sahC{ zS68bJ$W`+PDs~vu79W%p9*D;F>+R=dB}L!{U@(snq9dqMRe-&By9xFQ{|REPmD|@` zY{Dcn7&>^Oqe(O>F1%r(zg*TZdvFqEFbG7*qeQ)rjdjB(a3_hsCUw-@6 zMgigd{H?jICy;u+m$<{0OG0=Ugw;J>q7}pY&Gvv9!C?Ju5>eV<) zZF%LGnNH@FZUab?N}jd6)9-17YvbuvWnY2@FyL`QLcNZj5`F&1fVmnDnxz_7cx-3DQr|20flI=9;ZSngec zfEeieQUH#6M-|jIeQyJoCCeqO``j3#P3?1zuOz#}`Dd(8yWIyhOWSBz4<9P(mI1Y1 z0&KH)iRbT;ZB_!MbB*0pJNbmsFWWyw1OFEa`d@~EKDP>R zwj~QwEp6qoLz-0>Ob1}ElLQq}K97H;8%X09%O+v|jCxH|?rv@`3&M`=ypfW92X!t) z!xsHz#LdMq2c;r91dwFgMLBFplaO#ZZzK{IO$n{cG%rapN%md!RQN%X0^3y)#3lO) zni%Wo;S{pU>5UILC8y^$P}2LDm7j9E1a6A{8=i^8%UBPFXXhpN%L2z-y7@xTB$wt= z5d&~e=|hPNu;Vi#7UDZjXhj>wT2ClDhawVz?p`&B(ke3885;fpQX3_mtkxaHe1{5m zXi@mq85NlF@K>}$P`49o?XWSBphi`NzAe&Skn5a-_uRj)1!dOvMUqYV2MK{m_e~W3 z)aCBY{J3m6l_y=yd?+@jx*N`O>b05xJB0U=|?+j{QPVA_N4sgQAq{dgWyCea*Rl;T%p7s_?Ld#Z)9?;<5fRRbrOexUK(%`e=_&J04H~3_oas%SQ>OhvTx#aCvOe z>B8wTNwA)GoS5*Wy$?I^K=b3}_TFL>mDKSPrqIdl5+M+``6oHOdC`#XId`XqwZ!=l zNkpa}U!~On?k>PU%cqhzi!c99bX(Kw3z5%BGF_x zkp*?xCMu1?Hb^SWD?x`2I~e*NwCv$0g8zb#R}?^U`&V!6Y*6p+A9iNmA=LfCKP&B4 z3dg~)ucDnE9v;*IXERYSrYOESh&#{Qe_uTK%PYa$kj~tuWzf_PZyx-80Cp_&2QYT> zId9iWWX94^R!!O*mg?V(SB)tSEk_t+G4?h|&mqhE)ar8aY2dZ)v}3^Dh-I<%4mc-2 z>bEx8;w*3@Qse8Oyjv(g6tIUC-F*a7So^j(s!C>r&j_92Yh9g84=5b`8+JzLx;tHh&2j z2Mxu~ch%=5X#BAJt@`{ArR{e=LV9~8Yakc$5{`Df4zO47U_n7+hKv12|3(LH6vY=H zz4){8#S5F(v$=ozu9Jn$$p#S&HRLEIo&6?APg|08-U3B6KB6zJyj*YTyFIA2xOkxk z0G1D2VNw7@Jz)?WcD?={XEwd>+M+5&&SUN-$8@IoO0CL z-EHh0V=dTiigOgQ`r&)4-X*f4C)I+6j4~)6UFnQ8WJ(yeP`5?T$!sX2I$i@)3FDeb zgsB{@wlR#6IH=jQ2@9l;{}~U;Tp9T6Z>;;eE z`0yxrKq8pGi%}Vv!**I3*ln;#Ck)Ax+ch{U4QHj}H83Bae^|$BP;v6T267?umtfkL zn6R#vB#4iRd^KoookHu=zshO;wGXn_+oL8EX8R-lU|(1rHMYSDUu%SZai7Pgybq16 zi+VV&XVzA(=7oY|3~elJ{@w7H!TTq2S%gBm&7r!qaR~$Fpj<{@65maV^9H%$9PN6$48!^rKo6v({ z<>QYq7N7bOYDe?8aoYMdD`u#?g=PQxmY)=eZ*gv=+{jenmE-v+WnOW_R?g)&nCSii zeC8igP|r4GLypt)4nhqfS}XIf#PL32|8kwpa4_pD4LVmjGXZ{1Y)DVf+j@qiCJa^F z!uV|Kf&yyfjN+lX;yY4NZsH%yA@Dt&nZrcVCS)+6C`u)gWklu(Wiahj0nR+g#wgN? zFds%@3SsUxXOc0D^gt3(Vex$-#saU~lTZrry$dud=P$vmxIQAT&6pzsWU)sQVItWe zYhrJ@8|Yw`0mudCv((>Tm@U?D;<*hfvc-lWak~Z-8vm^gg6sUNalMbk5N*3%14UT> z@yPs1HKl)b9%O^zQJC$0{VSH*SN5{-mF?8ymbzCg6e{?&VuOTQpC~lO$N<2Ugw2ZL zp7W+oG-KFAxSQeN(ZvXA)!Q$Mn%a-sFO%E_ed?T3X{1<}?FrMhUI0yEA#N86(w7e z+YC4xEF|Rigj}zuEQXE@IrQ|R!!k0fst*5yqCvj06((pn`qv~d#L+DbUF=IO%!eq=a+Q+ud$E$^*692r8(MQwL*MM0aTKBfmO- z({AIBREqy$hA*u5eX!yCUIT^JJ6z)q)g`p8eV?W9cMp#40qBAp;rl4~t$AOAQ^xjc ztu?XXop{v5fYw$Z8OqrLs$g`vKzw8t%K9ca5@gAuj`asuvyXWEeX$nWkwlkQPukVinjT#Ahqa$2GM z*K3Ykg_9ZH2kUB=ebB#!;bFVnRV}Q7NIXH%z7_#&iuiGom!)&B2FaKCk=HNJzIcZ# zOs!u1?f`uB9;;EW6Ll)I|8PueaVkn%Eeso`4boc69;dTjNgTgco8{wb-)poCMyz31 zW)Voh8lCJA>nzt-o}0p%)xJ6$zFtLd{2=F ztM;_g5T0)J>3YAgC}UNzcsh!TD+*L`FlGzZ1)H06x!u-l>VJw7Xc^YL+ilkgo8!C?WaM^?fNA)+s&V(&pk9vGFhRCTCVnXb0CoYDjBW(m&l4> zjkjq7Fsi|@1cOri8C@qnfZF*rE?eEH;YIg@epmK-EA6g?Gfnb+0K}xss_tT-ae8av zX9ida4kd!N9P{vvAiny@`V94Qe)_%Oeb9v>`(q)acvgqfhT__T6Z!7AKQtgW9zl>v z6K<_ORn1q?iR=I7daP#-*p|hZXLW#QCL(g~j#ZgycF7p@>K>N>IE_BlLtxVOxC#Q$ zbi!3ACP!`|W}Pt3_5^EqwLS?JeY5%b;kXjPip*a_#>&=I*d8woeGE+nkl3UXbfSVb z$CTR{B^aChhTI-A_XpjE)Srwab%XO$prGo31wkb-qS@jsCL){O{JrQQvF@M4YoFXd z-3Aq&ns*WsC04M9m9#f9$!;g@0jx2+Tes1$q900RYB7I{vxXujwhmzn?x&3#@R>wJ z#5hCsDMtGioN`88EXRKxK96gylb^E83Tuo38`jXlV?VfImPabDQ#3vb1-MC7&UunQ z(Sq~OdxoMWYKye3qe^SSwqC8*peJB{Gxt*vic$Hm3Zx1}#R2nP*LVfWl3@bMVKRi& zBZ}vQ)A=Cb%XM5}38cZlKtD}8X$T;;>l{}_nLo~rEyMgeibBVqeIXN!|6=h|5BR@+ z%H3!Zg9h|9 z=l2<2^K~y)WEA6S^Of7KFk(&0l$f+F#GuIaw*4uhx#h0Ss!(D0u3GJctwF?-1GQP= zzAmpJXSWuB0NUmBZpPisTD2PU7d&aRqU1zKXnQaFzn-D{x7TdWq5oo{7zhk!(5$cO|_k~bf*XWR|yyFzalO1()3?30~E|_KU zs6`$Ic)-ES#%Du7;Audw*A@7NO62^LFkAl{%G~8kW$t>lsditN2$c8o++cxgSL zEphA$+_74BIP+su&-=C`KgFyk@8SY$Q8*E)l*X2y9wDgoI$+EG-E}m6aeL}g^80}+;Hr^j|KcYOI6{u*As+cZY0z>tQ!T?5>ZaSonZ zVKzc5P;emrStvC0B*4YKzpN13uB6TNtyxt$;$e+Ws&cqJ9aQuAr*pdm`Hy$=Rfv8j zCaR&+50K)p-6hbMqmsgpCg$yd2LJDmZ~y-0?VI<%{`B{c%b(u7{rktCKK>szedaf~ z{I)J5+W1}P9(fqS+PAH>1e?#eY$>dQ2$m_~x;BiVzT;~P{K4nou+3594Jn6$?HIQe z8wUduP;ncV$%GiahU?ir8e2%y9$|(V8Ct$7_(qcwfT==yAIZie9!6wZ0XwNQNCtmhvs~ zd7w%&oLaE%ttpMv&MpTqM-4BByGeTvwk~216}x}VM3E^dmcoJfMK<2`LF$U^IWjjAds0-^;M0wMHvSlnu>QCh2Kzs z5F^w1*~$$LPUmz523_@sYX6`}<_4#|CFK;5aJ|(YUtbTnCBv0qNMRn3cSY48MXSr~ zr(hwu#?1^Eyq*?ES6kELBx%&|5A+t!5h0OgkUo1l1O;e<3^Xa#rYvByNwX8j>{$=F zXPa@EO4T)mfea=l+Ut=sY8D4Vlj4#g0MI1JkNiL$> zI;ZVxTt}xFja0!)B$(`2;P+t2!(9um%# zNhuz3Pzz7H)^y%&IL0$rSp7+!G~_7_JWa6iah*D6Yj7J3yR;rl)cfEWR7I^&7*AoY z7KxD7GbDmbB&abn8crQ?6G{l35?K*9^M06C@{-hmIs2Y#-4pVcu1(2}yQcZikjk9j*w{%(s#?g`Wv1XYP z?YL^~@d=hszGH*8gLhv9{Ih@U+rITb8;+NrJC7O|BjJ?tb?BxxQdJu6^~GKPMx#o}A$F7{wx z_A6YZ(wgjHM7mhBl`$@y%vQLy|3b-bsMz(@IRaj`T6%PGqPpZn8Mdy$)T**%Rp1zL zep3n@ZW~-=H=2&K4pSfGVwp0sgH@`Cs-#XUoJ$i`1tU>`{QzS97*)!jYw@?D!lo zEezX;OwDs2k81ZxcXmE4wUVSl@Ja-QMXE;t?eDjvt#N--32Dxv5Y%n+80JRQG?JLP7Je)QYUR#e9tFyZxQ&LOkD#oJ0oa)f6k_>!i$?uAgL$qA%b z&3o)ym6sSHEs}NRn0J+io^J5f{x{X>AXNa9s1lBdN&O;;8))V*QYe1}#F91E>P+2l zsNf-FHh;v+7OvC5X_{D=t1kyM#V%l*56Iy*=%%5M*F{0s^nzgp3e<iUT zOaxk#<6qLmePT?c*!C z71a@9EeVRHIcv2-O|q^Qqq<;BSp-QAT0dNZ6@F4~vu?sPj0{=4;~t9s>-7mfhM?V(Rv~^&6;Yy|x>GvADXk{8VXigMw_;v{Qc>DQnX{BFa(VMN?=}Fr zVY0eiL3R}1yP(``*unezuvGy}MF6)a;Q*a~5Sa_I{l+Mq7T10y8d4z0)MsZMy~mIw zk9qH6@xw8%f6%{(_VIBCx*`Xyt$*ng66O6~iQ(90GA{+rK zdN>?y!!k_oNj9QvseK6&Z@=gBZFhDwcGSv&+w$w6zkIRvpa0bLsaQO&HlveG)?kR; zMzjDBQb%UV^<1=7`@Z|p9;Q3>@8e2bCXbsnTsPKhLDeQm6^Q9nXadfqhA=S6nFtBv z5;N~MZHvOTb^sg*I)%aS!kXS#4doU3tN@=;`6gW-7I2wh#)+hBq}54yw!oDy3irvd zkGeev5u{=LIbH*%^86Ye6{5760~CcFfM^O++iR-Ar3(3A!k6QANWirzFg%ps_XFss zDS!+D77)2jR7}T=%6bS=BAUNf*5(Vy4q#}&1d!U5}=P62$*w8J_y|lAzVk`3tS`j#N_iK+tc^d z6)8}48uur79EC!ZIu=lV**f#^IqEGhF(s@P&Eq9OwU}gP{0>qnjD|liH}Kndk!g&i zvMO;KlVmR*{Kmd_=5js;*y&XW+n05O1alC(_qovQou9~V3%4}IVQ!a*OzMpIsz8uI~qg)-XjXxfBrUfG{fnQujrFN>}cm@@AYqRVaRgPu3UcFZI7Z;TE!hC zG5*6Gu)$E?d56LEd;SjGUI^s0`AhH+I;>u8q1qr6n}OS6XXKV~9M7v%HI+(=js(T^ zmXp%ZK6blfBqQeU*zpo~D8iQ(YtvIKi?#h!cgNJTB$lJ`33R;5@~%Uor+?td!l2s| zC#FHub9IQkC%UWBUD6eS#R9o;X|JNaDoL*FsYzUAB{CT(tH2^0!|ACwM-H3s7z>wl zpPN6{IC^tiS&#_%tZ3jG(wT5Rv#EF**0kGDmsXaFeTOr44;aY%q24k3p{o@s6$VL- z)vL~>_1t}Kg7;r7`vO-QN7T292re9G)#kr-iVit~BnNHY)ol>c6K<)gh}j||@*|8r zY895Su6v>*LsTNOJm?FwE`{U|Soc*2T?2`NA1)l*zqM2=tQer`Ihi=whkNIrBBbGY z+!hSd{I-{C9arw$GC!=BAd&Z8FF=6|!Is-_z!oqB&~h|Hnt?Oao1Q2-0m%G@niA}0 z)m6v!K__m@71nFiPeo5vH8?dV9j+Sgi3{rWz9WwazW3WhbHn>SXr0YJ3IjiYpeA}J zNUv=6Yl0>^1*_e=ok4Ep1>qb$b9f>Vqyp8nWj^)~?6cKa`EZ+QB0D$#!1@}*z;R84 zCAt=nS#o?=O2G%=a*pW&NYOE21Zfx0%S}L_0ziT|6phtYEBXLqH_KgEM+5SN?Z`i!Rz#X6h6>#UW61s!)H{-TILX;-FuYnnp?=@JchRy9X zC#c1h?Fzw~^|m@h@1Dxdb|(hE|B>1l^rD)oA~h$RQ|LVPD}EOS zrxm}8LX=TNW>8=kOJr1cyA_3dnHQ=pX-GE}ZBuq{=Q@vnnI|8~8?(3<>xP3Aydh8G zwHT0VNQkDb!g4xqkQ{EDWt$+i`pzXmBw4OuUlhZGPc4e`l|6P`v|r!{RqZ$cb^~}J zin=N+kas~^Gw-VNJ%LhywyW-A&67gb8G7b-0ZjZ=^_<-f?MlImth7Vr;8u-MR|Vry zY$*_u$=xBIcTiqN_S!PS*2zU~V>pQ&PY{wR-}}JY%J&j9m;A3mpo@U`#%BC8Vy3a>BG)@e!w@B{5Iao9==Xfw@XNLoOC!rCZ79ssYs|#(m`5nyd65xUi8L#X|-iTSrEb<417;cN| z4x`jkrXAz{q^{CL)Oct$Af;5cP|vfd?u4>OYo~m!*v=xiY_$c1lDwykEGF-vjxFiK z4H(HJU{`=dmC=|3V(Yw&geva)Jm|U1UxJzQT`?!gfc7B&!Ba=}#T2FVxKB^L&d^dz zy$&vm9VS7N7Udauoi=hG-#dtrnv`K37dMClfjWUkbR@D4g>AnE2GLJx$M3^ZI|iVWm7lAuK`_h8Q?$~%O;fqy-V z+M;1nI1Yz@!-weGdq^ou`6pH;{};E>pr7YGqN0)MJHyZ%_q_xmqoH8Rraq|L^|_Dy zN-e1&VE%#-)nd7Pq;0sm4w(rWMIyI8YL?Gf8R(D$OS?va*Qe#~tTR*kr+!GZd5@Go zP!|nM@4y5PXxlQfYm5#v?{U$p=d0_@_SZ4=#B;VV}O%N1`SHB}{O*=1=1)**xJ<=j>+a_tg!QnRa-?1W^ z2Hs<6>W=Hv($0S#UZe-ik(Qj{u;f)r#Xk)22^B{~r1`>Vi@XIqg<3py(+}FmAqD%- z--*RKETX;WcTzb~Z9+M`rpMh5UJ2hfj}c2wJ~>s82eZ0Nq)zwjvX;S8j#}zESw%@l zdhoE}AU&suexz~Rjno06DRfj|un4OuN|5RdOIPkdTo@_v0kDR#z6&5XTr+zd8zgQ=;aE+@a?k&z|iz)Narwl z3yLIX&_egFL~N3fb{niHHla^tu=;+B0CMpmd5P+pjHMJVGdS5%>ZRw=)MI}<>yTY7 zI%+Ji$BU#?%%!?$o1(x+8rhA-xFaC-5>bt3Fo4FEDg3Ikl-}@wK)pn}xQHcO>r}Nt zL$N7_+)@?P{dCh3PS_{)g?U`X@Ai*j+HKeC?dPR>+OJp_nj(gKds5e+gV->m*qPEP z&oVzF9beQv!umTTz*KX+AH`^MsfQzuD(Y}7GP-pYY7lVSkS{H8!N@xmCeK?))LaUOZM`M%F0Zl?dD5uxYv+6t_E(2j2DkQ#cNUe<3F^RiqfpyoWqm zciH_%XWc|0yppNk;~|&_VLfV|dz=(<>iE8Kh$Mzt!~4n})noIpiz#Zx$Y$rmA0V*5x)f2it(-!P_8YmpJk*5xuAPAhX zbVzD=$8=a^8;&}j>xP`Fi%6+4m`K~akwzX#2OEo+IDWc8uFQjIqrB3it@e_ zF7bbqFfkP<@;Q_AWtAtj;)BcB*P`5eGq%!F%zM{(4Vz zG6VmO1bGtQ_ll{P|2}LZIX%Bv1E%=_5EB5by;^q{nC1%Gq=X_zSE{@Ug!1Y*>ofm| zH_ZGIpPY2wGcGe(1F~{-oiuEyy5JFkaNj-=k?;7idJ4ne7}xEiW`Rr5Ecx5p|MMZo z=|mm0$1$jjmI^?XXBfRfqjVi!Bbk(2vU)O7eL63S>B^xGkNw|lw3}imRFd_MVKQUYFZ@~ zQ(#05qE7DhMHA-$zRh~u+;q%DR^?l3@BqHru)XtIWYxzsN0Q@a^(E@|g&d0O)keUn zkic+g0P@t}0E0OH*_xR~LJtBLfRUFN&1g9CKUDKlyqpo|;!(#wPLNn2=^2IHC?i28 z0m@hSXY?<~OM%>DskC0z&0wkYSgke_qiNSy9FE&5eZ|vOz?3Sw<3{g)*}KiJn?~XL z%VRCkh!SPFL2B;LLj}-xv42=SKFiJVP_0rR7%_VbnkERdQN;uQVEkZFHWOzjjssX^ zjt3AGEW^>NLBdbfX4SY~&QPj!+bVc1-T{MAo5bxlNO-+(gZJWn4V<@puTiGnp&)6j zVV%2;DArou_W?!5|2_i$DhwqD!@6-Bk2_Fg&|>$VVL9G1F3{=F@+5Bl_6Pg03b=LR;vu}90+)Cb~ zH*`3-|GMEMlI@$YuoAw;|2nGUga_-(aN;a5DDoPWM+Al_^HfFH7uZg{6wm<@vY_tu zgdUL^kGso0sdim|T|J39$KOQ_pg#o_R#`x;aPAWQ_-;Hf$n36kyJd*amFslxw^yu| zkNhZCJP(F@SYF>DzUsho7Ey+(>E%(6Q-M1VNGSfMS#TnTq&fzF;jBd0BU5=$l__C& zk~()lV44{|)@?cGrgKXs&EVPlumvcxtM;qrkIDAe{^P?=P0XLkUOX`Xq!z^H6ZEo@ z(D{Mssm>3x+w+3M^WS@{NTZnAXGaM*=#X!X12XJ3ZX4&^$wK zol%)UeNDhXNOFizm}OJt~ttveiWfPPUM=O^5z2(kV&qT%yJN%y5rxbHii@?sf&vG(%)ABlYb- zpcrwC2yp;K^_pYLJ)Z?sW_j~g9Py}GayyQgg0n4@gt3pK0C;0`IYWgK4Yprljbwfp zHvlKX#YnQ6;@7&p7w*El#!A6yemGByKvHU5iMWU)=2L21x%H9X2NJL|Rj8oKiCPyN zgaL<*)htlnl==J`BCCWDI2toGo7e@alQk zF-q&5K=>x;y-G_BLJh48w9}A1=ExsKbO`A%QA?n9z;C1&Aa>9fHOOMHPC>Invm<~! z9-Bkjt<+jBi`f>g5)EBcu7m)~i(3Ddv+8s2U3oj_F z&qZrTD0JIpEC0ZItWeKt;16?q;J%yjJhxWzD22^Gj^mKrp-yZW)SCpIqNs&q9V(#8 zNRzq`Nr*#=@0f7xdXH=7AFQJ_=zZjl>+bd=H@?GzAok|_PT-mPUV`HB{3ULSrhqZD z1Q`^qvDj-HcU%%N_x!!+m1{-z4?C&{vLDY|+g(_ zyFwJdRiA%3Vxts>#|_PpKbCut-Ry-7WK>0DE7beZwdk92WgqBT)2NpKso5WRKSEgL z+zS&eztNo3E(FKZhG-g6384%_3VV675&&M8cc{1QE5Zq-J6R$TvguZz&Z{qwNjSX` z(a_$+e2J0kPf)3MoC$Itbfk`-9uXB;_VRqsy@fd&8~jn=(;yiSC!~fbIULoqy@fPv zKx2Wz>GBL`-3IVVgWg&lKrcn^Ef@_-L|zmN&ypRe%T?0285ZFzyJ^#jnSNo2(pX+b|M-3b`miM%U4Vkv{(v zr(jvqgoznB3brq)cOI%Qi-opuLwodZt4*sXKFdudG0xagSy5huUUUlfL;-^46atA% z4odjW0?1@uhGUC+{{AS$fio4gh+g0g+=d+yc3ikZ5EAQ)w{MGxzRbTkw=tST#%a_@v`?@GM(1fjy{bZ-7y|0_FrIO0-)$tXZblzMOkV4-o5TZ&Vl8*11?Mc9#j zy0h-sUJXHr(3kYgprT>%M^zf$vR(sfj-5_8=6>yazP*C(7S}qet{IKcKSc zzo+rlq=-8GUy;ZrUVwsJ7rk?auUz{Gya&%#)_AdWSfxP#cJASclGbbsPtO?wLbFNP zh`qSor3}D=Ay1So^As6b;_xR!n9Q#Y4|H5Flb6fzN;YKYJ8T z+vQg&q)i})tm_nYKFfGnFF_UF{~G>#7QvnE)mtA0fR^FKxotVbY4an>yPsql>ws3D z(K@7c<3b~|h+|dJM3mj~qU()g#)7c!P+wR%V;0-i35?e|R(SV1FDWE#jSnQBXwx9b zdIMm~v7}*o2l51>>c&U8cHN1|G7_?WsZs-$s}$ik9Vf9*cLrM1 zqnQ6xw@GE{pSfLuvb^OccqP~f;@sS|jd(V8@SW*-W9v*emh%3nP>2u@s2zCocpp$S zf#>ep>;|`F*eO^WMR8{Kq1pE+`M=%m2EFBJ)0cOD1d-g8Zp{H!8npWzK=joksIa$Rz$m*NCmnXQfX_g- zXAQ!o&O5V|jD4pKeht2tC`^bB_Lkvbq!UTnO*gaT3*Fz`g~gA@PM?=M*+>2<`$gHU zkNXFb_)h-uFUM-vCM`nAQrOK)IdY z9Ot%5Nv+Ho$qjik_^C3GVF{|59k!qEL%=k&ds*{^t72qxdl-@LEB;x^GBQxltCI(qg6m{b|yvW^CNkSAHmIgtFHmt`DDky2~qE7*G9mO%I zS-I;1Ai?pSymxSWq2O(p|1xr#X^>+Pfyu;LP;_DXbN`3Y-X{zIBegw)ju%jK#CJ6& z5;Ov7`;LdabqN?H#Pzn+l~stZNQKKrp*mIJ5{77DMP#nZiUVRXo{f}yrKbWN4o*PK z`H{G46vkGTlC@PkLLqMN)#7I8J2gm-@31EsiZyO=f(g>$b_Haf4N%tG9WgI09Ar$ffxvI+)IaaK?7vpOoo6G3OiK>7Y*rVH<-&kl%La?nx zjKNoeV143j`WZ$37F@7*<_CoL>)S6c&)rRfCQi`FD*!sSY1TN0z9Bx=^LOdC7O0MR zUn9FiBiZT_VV%P`0C_(NH7@TBpH$fQrHIh3_caoeh@ji#K&i#{EY^Ktgx*i>3vPG8 zW@6i&tdm1zpnXS_l9ul!NcC+4YW36|H`*yrUB>~1?dAO>G`Qxkv0Q2y7!6X_br;9- zUS?Gnf^aPAjT~4h+(Oz8h_)l2238+Wgs7q8J3QKyXpiIY;FxH5G&cX96Rb-di^XaK z#frKTD%3y8m*)rm<+t?zEM2N6f&YJ5RtIv13ba&IQ#n&{-qg)_%-I*#5G7A7EX0!< z;QzNEi{Nt@R*K|Ap#`$`XSF^`PxBx8_w(WCMD>+a)&JKN{{k-d?tHf!rsg}+(>yCy5a6M*4!kQz{7t}SD7%B z3hQ1}l#kMarNUY@u}Y~GS5c=(!?*!y@aBW@ds@}ooh%9zY-t(PjfnLU{*9O&D=BH% zlRQXCiS@{{9yTHEr}+)UaTCfdrHNjpfCMAe<}jr+Re#ntF@eTY^!Rl~k`7Rl10ky_ z3cr!_q5&S@`wWO{%wIxwlI&$YE88P%R_(G6{cp7UkBv;6jCOkkO9b&XxYTry9nX^p zp^EuiaC{S)Wd-H^(mo);Qngt1aPI&*`aiAM2SuBuYJZw&Nf_jPzz1en97C1QaGkB4 z;V-x|ct3D%4T9~Mvmqs&0-ed54=9SZYWXjGq+`C!-hO!f>it{ZbWA_6ruyEsIZ(FL z`MIOif6W1L^qwtIZfqbEJk-@*(Up!~)2OW)`Xe9IAtZ%vwhV~Y@M9Qgrxmm#5;_s$ zmhBGe$xKi^#|dAWnu>1Mh-f}r=3xdCtqwZes^v5X!PlV{U*oSFNs~qeBW@8K6(}ld zlK3jpF3z!#a;C4LiadW8a`^SU&Ytf0BKWvMU)>zHPFI!n`?Eg{|jE;h)}P zRy{ueZm%*PGq~H!!hm;t?}GL1e+{E*lS~IoWZV1CWngk6XRU}4(pyyxor#Z1_&PEV*>jSu#PE;BQomK*37WM;5B3W7`6s0rw z4IwrO>buPV3g(vAXEoIugQ`hWy{F-@)WmF_d3CrcaY;=XsoRsv{xbila&RTj+8iPn zT<%tcVCrz#qB1dv1^-9wwj#0de}~^iH~6>l+urY1e^v)IMBOLJm*Hm?i{Xd#yc!i{ zEq@$m4;N$BpbH=p(-j^V_(I4r!ZS#~o%KUrY68k~qnYmnSS9$4 zoB+Lz$*X%n$cgeYYS*L2`|snb*Okd3s8<9x3Hq_f{5S`fumbK-OYx8G0Baj|6~-#- zk?k))yCZpDk~qQdUhD#Z)@bui8VX~&-T{-0yMSVakop~GW#Mm905;P&vHJ~ZTJPx` zhxP)_`Qh9H5kW7qUZBX-Ug`)#ivAO)gd^P^{0?3!REG=??sgkd=HK$h#BqN79dE;q zz_W%F5JJ3%1FZ(bc_54CBC2|#uJh`tmqH(zAm)>@tkEp}W6jnkTNuna@RBh+2~+}F z=Y#-Qq3?hrK5UDgtk|M4YPlU-L|fiG+=HIM>>hw80x#Zg*) z?wFs5!Mp=Cs0{=QPQ3ko)oEd@Ol37CH?WdLhp+9hV_VbT@pPL?f8CyuZkG4_WzY97 z2JoKEW8EYD@G*W`tyS^5|9zJaf5B7{+&-3;l|qOf1=bN1W8bU%X9}Dz!*<6^xdBUp zOiin5jCm6ncexs=X!gg+EU{(L&ssEz4xe{Y4c|Y3pFC*D>tDYD_mrutH{Z1I|@u-YvUrVKDO=wYsX+H>gz+HcXad5fo-uE+lqINGn2ZFV}! zM14U@8C*`aAvM}>%iPtjdV9AhVjx|{h=%iG*CIRn= zd%5!=(11(7+3t3KDC(|~lr0wcvpiL+i*<69VO?fQH2wj@=TSpsUQuRtj?Imf7Pt2n z;f+4O5ZI+IVTidtpwvFhWVrfqJFeEO%MuUVCF=HC$(~gX>ba@1m@Z1;jw*p4Y`mEZ zd1S4R+J}3mT(<9{U7(!g6dto#V6d`(3?4-Z;1RZ@3g7scbE3E1J|!a<%}>eLA49Dd z%Cw+HObQ1oDI#Gd>o}zx5hQ5fM;Jf#>Z{K3QAWip$M=cbpK%DYey8sTYRIV8)z_`` zk$={|8#|7wKI-1+FoZ3xH7Ul-EuG|slB(X*=L;2S>{O_D%YlP?LbV<%7X3Y+-tyIY zI)BG56^oZ2@S=3lR>&*mbpA)L;pQ<0uEf4De(@?D)cf_&W8mfux%ODOuMUUZvPFJ+xBYrk?H+wZ!<1NdUqk^fOD?a?RFPVC@&uA5 zAK)}$g45<O-3g4$4T_> z?=>h68qPMiB>~jW`##{d7{-G&VUxwk8W3g&1sQ(-Fd~Rjg&_y_9MlfttgFTXy;U@2 zCSwfp$XYv~Jo6yH(TUC7>+>8wnnVZf(=&yFw6gspVD1oTet z%;pYeLLUP&KVH8m#*Y1DLt z@^ul6=b3e988fh{oyBdQWAy1AHf1KrgyU^MEAXA8X=#{V%#Ez?1d>$4YueI*JhbxL zheJzk`e$5H&foj#yG|NZsg|H31`l8|S0Y&pV+SaZ^A2lthIbn#WI%mKNwRhCYviV( zc6<~|SeW+ao~QTl{ILr6_M{&qtiiAxd2;a_--j{)O3c3^#AjuZh47liF>h zV|%Th;&-M3u(<&nC;+|ySJ|csldMK1kbxNKGSK60buNLpZm5FkC$S<=#%$zviRB@m+dGI}!R4-1 z^WsnNl>lS}fyn44Nks!6@wUF}d^saAm=9wOP=Mp~yUfJo33*t$!-~lf+sYydoDL`nQ?eF6cqlxm>7C6~oE^#tMZ~{9F^y}%*=u>+C&9hy zJU;J%KpJFCmMt|^$$Wd%HA9M4Wdi0jZO~o9It1*Sp5fL~?kJTzRm$zxNL{5^W+4Xx z{}h@rD`9HmkRX9*7H zR_9lRzC-~?qD7IpW01NwsXC-sq2<i zZ=@WPtlPJ2%&+FhLT`cKqS8Is8kHhXtG+~u{=<^W6x2liV!2kEWmm04L$i$pWLdW4 z8CX^3J(p9CZ3ym%mR89D5B9A84YyOuXX)!#um37UcZ~beyrTe}X1I8!BN@yp|1*~B zZZx zCp+3pXy?NpZMRtb)N@{cR+~?U2iXT1tP<87hVYn_tEd76Jit6r5HD%$!;pH95AsD7w28A>*h2z(@=o=x0RdEzaW*yXRCwW!77@J-c z1MoqKA@dgy^icH<3)d&X0n0zg3{0&v-p%(_R6=XBI<60*sU#aC33MHx$Vmns)rC8* z$*5AuLx2*Ouo$WV+@DHlKrcC*XFTUC39PyXvz^3A6-6C>-{%?!MAHH_zM+YGj3YS? zh9+(u6&Qcvca2nP*ocds+tNZ*#WE4CVF==<-YYx`{Pk);(fK}#RI7cjfw{8xHK;4t z_6O^0xdZtr_3vmyPnsW4Sy(#y7z?$s46d9J3Qe^A0>g*gFQJ$oR&9%H0K5CB4rm<= zL0B5^BN0EQXtj;O^B`9Dg|fl{`JqqCia?hV-$}GB$F--65RmAqyrG^xgmG*PG5bOR z+Eyrv`-1)9-MacDC1?JQTdz`!-sg4#0?o9P1?f4IeByBCKzgjV(!0s|ac zP|L7YLqrb4zwuzZJt;98OZG6!9=j@Z7u7oMF_`*U24Ax;h)|32DniwxAYE78R$VN5 zTOVD7c-2-<2TT>&m`~ru7cW}0?2$v*jNCbLQ%&8`yGk-p{{4)&JsAyYA}Y59rLv54}JkkB6B*o`XC%(1g5Bkq%yQM9jb&`XwUU{31P<+RP9?lFq8q;t*1LRKrPLTX>b zp=&KXj$89&;nD5f4%5JJaC5%{eHzZ%dbL4-4<6*c*{z<)?mnKrKCil+(?&tB2$347 z11(Lqv$LO&3^c`6Yfaw&3A-Q>QeY@z^3am(w!!m?=8$tkjRV*49C|E*C@m-oK+S0j z{9j9&OjJ~1EbzOl$P*9;R*>oZ7*P^P` zVobltphVh;#}|wQ^?t`Az}joHuJAkPcas=-r#qAiZ1dInC}hOmMPS4k{hx(Gie=NZ zKMS6AzSp=1FDtWH)Mi5?bd4Y>(7Wvykz~gFtZ#NmjBwWI(9y)pQiyB={SMkg2tWzd zDH0E1($VoO#%SW^vI6}`?>9<9Z>VLuoh)F~EH5-hwTq%@Lt&I~D#5OeGruX3scdRa zfMzjH34xhV%SARHOFR@@2)bM?#K@uyqao*;MVzoB_(oHkU#GMQP1!m^Aax8mwP~7M zp-|?UO2ce2}(mq zFzlXd%k&7PJIHCtH!}anHep;Kavwx0K+%{+VhDCFZV4eX^nj{1kH%0GQV*ih6!_%E z&~D~7UF*|80t}O}BVxZIj{@G)MXuZU)ZJblD3U_XDQV(Ja}~S8y>2c z-4n!0UUpA(xULngmb$Txrq$5fmgzy_BUc|1!wAWUDpDzO0F;WmvnEH*E1*F{m`C6# zem{=!4&k|F8QYftrm()(un8vI!Y&LiopoW4rcKr*S%{`4rlDhXoh^TQ@>?HVoZ@{S zyzpmc%3kAp8W9tA_gA-^ovLYW5myaxtH#q zClT0G-^XMT*;Ww^d0kxunSn70;LI8_L5)dETw%>a<~ZEM6#JTSIt4Y!?0Kfovf&`B zx7+pEDc07+Nh)lK6{u?A70^F04Om>2fuP|qo&(;EqcE1TNZz-!hI8`#y2nCa_3XXq zDi3MX5kLaJETN*4JsrDW@b}>uE%EtTYFr5MR9mS=MYM>+mO6r1N4tf-6tlhG5MTw% zHE5oijr+#zXNpdHdPU68qC0LHkrc|_ZGPP}3Rf0}a=GQpAC7rVKFKeCYWneF|FC-G z&#nArD*z6(9K*_9;%m!`wcZD`2j5GWaOQ3Un%U2ujPyd4Q5^#}19TSRYM86C>FEBetf&^T zzo%?!GUaf45Hfq)XyP4DCN%I&>XyGSE9%r*tSE z_F8UzrzS_sSTet`e9rtnj;LnRJt+i=NQCAPbV*v1VRu0u!^LmMlD-v#GYT(zU~poS z)hDwr3#v^=##LKwF1R?J@cA-Ogm_GfW!RaXE@6l%JDiJ^8%`= ztFXk2FQ#LP@?huQb4RgYevi=N8AOD)N@s9R&R^Vd53^pviYXr{D^r;A`K?1FlQF(f z%eIFKEzvjXWyFcmv|bNTMBMG%*#iEww9%4e3QK&7d&Cf7HZ&a;oR$wCB2@QMOAx>^ z#vVBaCIzsR7|8hyAXf673BYB2FTv4eNKIt~dnl$1$)&XPSuOg7lxbHBytXA&B`hhIR7l_)K|s6K5twBYyh1ns1UVdb9)r99=~YqWNGw__eA@8$5Ehv zlN);d!;l3LDQkW45514a>){FXx5x!_2D?~b&q#0KJ-_ZM0(;baM<<7gcR9G9JSPPZ zTlUADWC=q;Ah)7_uz!GYZh%L@mqhf zmM!}IIobMb-|1(V{%PHu|3&@&B=e~d-`pild*&3}k07q&L;-gO1bPy_v1Kg708C~q zZX-YxY)BLxuR#yhcV+`yGn8z36_R^u6Ahjbv#n zN^y)1Z$~N8kMs`Msa+bL-0=-S0`h+YcW6W4-syWEaIg%s={#t{D(Yo}RDvOW(6Yef z5JJ=e57HpOAfZF2d_07bTZvv#euoEyU+X(ak+mjl-Gb@A8*0;x^EE~A*$I&!)@}8Z zRY1SX=_W_D!$W4V_~ocWIsHbi()=lV!|SwNAJn6##Po%FGiic2?ItbzYTPIIszSU1 z5f1>I0fryWS*K|`JfD1$bG)2==fT8_81X7%ANuu9QTh;}t1m)kf6K1}`e(7&sL#vC zYV%bGnUb6wQ>ygCwU4n>>=Pt%?zM1h^D{ub5V&?u9uPL|@n9v_EeNwFS## z*!OD__Q@?wz-7_*E}$6rUIIZSLj}g|Ne~hAeiR%3w&;;#13hy0iQ)@(&&#^^VWMEN z-D~@m3QMYI!IbOdQqy|gT=6F(!Tyy9azOvWvS5t)t@8jcM(;O(_^$6YI9LsdgFY!I zJ4{hL3R%-=(nPdBscZGsDeZE9}yF2*lk{ycL33w zyuIA+0`U*;)S3dQWk4aCp%4Zyv7pNplfiZ1M=>!Af)@FQCR~hw+kmVtDg)7Sh8ZKf zx8uegQl7Eggmq$M{|?n^-NFd!A~c_n6T(iDhA_@^9UWunLCE2aSaMX(A`nqv&aoCOHIGZ9kZ$OT zR5@^66g!|T7Il+3f@g5N7o?&iCCYXFd`Ua!MPn+sMl|M}XH-CPub_Y=@BfyJ9 z7W7}jE`HLURZA=yX+n2fa`2M=s;E6=bzQ3GHnjCkL)^5zrnn|N#I`r4zgW{-BeAe0mpvsBogrV z&1dAVmcLc2y?XnlQBMK|d?7$+ovWpPBt>ZKKhKO_QjSX(T(0lZg?R0K4bI>B+mN~X z?Ok{xuMUV&*Hnm41o2oix4vBfQQl{GY%Mg~>0rYVK1&C)J_uwM?>Uxu7u_MN-eGpw zB5nI%0HvOvVUCL>$qX|?CxpX3INFh>T7Myo^=}C2HLFK0ctk6##nq?;Z`~$T+=n#K z3IHS)?H^(m0%#qGi2r#HL~f-!TJM7l%ztjBriL>wWORa10JWC?+HX-*xZnq0H8J~2 z#tS@8oe>m6{!3JwMeHR#o(DmWuejVv4+eYR7;Y^n%dWu*+BK=COgH}~xcf^jk7;Fe z_4su7$~|;tSJYKmW0GA3-AQ4`KBIC)l>o0Rd`hmcRPi+pIU!m1fl^w zIcN?<_Ixhvw!A8epha>586fv01o8d(cjdT!6r+yn3|KGkA)~s5Azcm#9lEP=HcNG% zUW*Ggy|&P6VkwP%qEFHTeSX>;wu0lMh+cpy-D)%~ija(^=+Jf2(albFQFf^0FyvEE zNyq1ghCDxZGRcD80%W!hDbUs)^m<);ymIW3;d^l{{qN9wfR-Y==;GPP}VTwcX^CBD7ys8T+TJr)L$x{`h|B$#Yy6S@Sy`RzohiCv|>Ys zbv*?Q(Ocm z%T8f5)89VyHhz`~TqXc3!W;xcsL`_0XcpBb$tnjG#}`?pKB|9zdQ!W;sxO!6WSGf9 zA0-yctY|oAKyODiUcIiTGah$_EuSGeTVF9!!owe#pdB#)tPA12BN$LHLHX`mINKNg zMyOzQEi#ccrBgX42c*YTejqp3(*&Q-iz_j@vs0z->QBZ#SrI~L7e!tY|5`aOHvB{k zYuxeRNR3Pcvchqe6hq5uU%rvp?Pu5tS-0A(v`a^d&bw?>Ii#HyWen#DU=eJ8rhQ)H zB+j9@1E_wWXEHIFB4Mp)2V}z0DbUDDN7&93>Cl{B< zj91_Sr)anddW8l+1t<#sYa2BsT)AO)KtVXkVX?qeLh262fNMh=&8YbY(c9aLOf5=l z4muG>2hjYe+Lc7A?dlUXD_&OsuPPxq@;VKnkK;?hnQQ)8+^)gk`Cfve z^86(j(J?yEA~by8z+qJu0h|)nSTYF@(w$vf6)cV zt^a+P`o($~5@jS{4v6&xdC*J#?81O}y;uC%Wjpn_{Zl}&==L>TQg=w<(Wt6m`*8&c z6=SveGYm;ocWQHB(Mt6=i3N9{61b3Yhl88`=I_aGoN#XI5Ltr{u27{!Z>%0;BkLB5 zSi<~LbDP?jf_qi6?gn-Ph`@Ffd53`nR1+Q_VDwqm0pym1nm8fDGSJr~75%X_Mz_v3pF zRIcVPA%{bXm=x-=l1obGbWa{}{-@wo|EIsHue#AnlCe|!{qoNhL-YjalG9j*39~g# zzUD9%cMIo84%y53`*WK?IOKU>f@IbA8mLapUqW`&Z*PQ;NM?}jIj+PlJyLiX$IX)5_H}63{xW0E}_w{Qc4~}ygpSFlb4|L5)sCZt`O7{ znZXOEEioa3v`3MJP?U-_wt4c!h>T?&;Fl29LDp2DXQ*Y4%(J`%yN`-4z!d}uvBHft ztN+;#EoQfgIa={Gd-h*A>Xik;1G}WE2Im2Sz!|ESm=?a| zs}Xtr#prT|fXuBDdR91zwIwn3r)F9bH|%i44d7?mxRMkz5f3M~smYIdAFo6}cK}A; z15fNPq=TI2{Ndv^q#+W~j`$-3J&J@7n+#=zon-i)1RcW#EOG)rybiU|5ExOP!#D9}1I8eM^vJDj=OsHL8TE_H?)?PIg%2lxYVf zh~`?T+#@s0&V0u(GiC8^vjJ6f%U#%ORzs17`2DJ8CGYXlQy7=)_^^nl*X-}lo%PZ6YItJb*q-Bf46*>C$y}sA5DGTeK(P~R2n8w}? z)eXMTZW+6H3da4F3hI1%(eX&N~m zp}DmX1vvzJ0?@%-QXxu?{2(D$AU3BlZV_p{7%?6ITY(^l=t$DX4zXp>ouc8rpWDbK z?3XPsF-?F#i7XjD=nyUj@!^|Lk4PgT8bHau&QU0EuH_-GHUBCd*A6<`-q!%k?tP8O zv=1;XC)GmP=N1b#y6e8ZK`j(t7F7a_LfBjZOCR)e#+)iiu5v1kn3xtIVH!kK3V@VU zTq&Xw*ABTGCQS4dFmo&kf%zH=bw8)A>JZ}#@lc20R{UoM=Zx=LjTi&(YsA)$PhwN% z9gbfgVP14sEKg$1JcdJRD)De!tcZVFZo-~GlDp4eV>Xl!Z9FLxRDx(`*5jv$DrsIe zp=zttT|5fq`}t3I90kgszSk)H%?S(tgy#;j@Z0OK>CPEvUGS4>%F#Mlw$sK<`MUYtaUFQrTuQ-j3W%*y{8(& zJKop8cWeF{%if<64G;xH70I@Nl;Rj)Ly$3D{HBJ0=%+SGNyvHMu%3QM zozIVz+jOSx;U5>l$MwDsXnWq*Ajb5)Mq$FBu)0s(iV3|JiL9qPCq0fy5Dr}us;uj( zHqJ)PjH%fA{F9<-OZy%oMevekAiuGwYFdy#qCnS=0jVbedA18-NE`HjIAVP>k@&WWZ16V9t9Ap|H*^t)coAkf$C6!63ymyIs9SO#u)SRl0~N) zVbicJy1Fa{$179hmh`+O6N>qN`g2W*1ix#wCPD>!{t4Vh5*H2soq`&LzY0lTah!x0ivCZg5_e;l=Li2R6XIQ!VeRyS}vgKyZm zrx3bsLxC>){InSN)BLzuHQQE&(eTBxr5O;0pC3?YUGAUo+s@Y8?H@-Gz0WaZi*Uya zD_H-Hd!IK-tm9$bxBL}1c%im+V!aC*KZZeddoRdcc&`+ZLNLDE@9HZX1`ieP@h78tkF|o`pA#q3y?dv|54JIe+I{~#2{||8cg!f!t&xD5ls1M`tEsVS}qm8y%H17NhPpC)tA^4Io?%bn_Y z{vrk5g6C0({6&~F&T&86tN$??TV0y0OPf}^_tIv|^?sLl9nQZ?$LYYq?R||qXbd3N z;(HsQ_brzojIS`{hGPPDNkQy_>H=6ii@P?H?$lx!3R*vqg=FK*ad{W-PuIwX#+KzC ztdk3h;QS?Io9a1?m(tw2{Q&`WvzH#-VByY}+ucv+9g)i)s`j{a{fQ=q7Lor)|AjOy z!$AM-5?MBhpYiF55qfEo5EGRmq^HMirqC(t5^o1C)6>PO;8wYJBB7`ma3er&-@kQ1_1P|@Ky6FBH zU&J?HO~U|Dp8;#ifHv&gIJeR4D?uvnkyf3wejfnCyrOGx{K=9y33Opv0 zy69QK1r**(f!)ikV2J1!i`Ouq-)-0J+ud%fHCnlLm!}O0UQ>cj%&S_BMG_Dw=$#;6 zC2ex?<|-rkRBr+zez8T`1k`zf4MZ4b^#cRs^x863p7NGV9*$KCMIGp6S0>$wrEc9= ztZy1NW*9(VZ1Ae7n^F}e>H}!cW!MKJN{{*Z@SYLQCS^qGj8h5sMQ{eLj3n4Z=DAW1 z){PHa0diIQRr80Kk|>nk>DG{$QETkHD0jvpLIvKn)1C^K>eO_fhU;N zLZu>Cy7}7sgNyp;uVTlfcQG+&5_cw9B`TnZNV%{hyw3x$pUll`G*+0tURV3Q9{t}S zuqjAI^5a1js1_uAQc*l;)F@P8ose|wyf;DMr{32{Oc;T2FG8k<8bYc49ezU7E`O@N zuD6vuKT2O%p{6aatw{}kRu5lq)t0gAftJcX=-h={Ny*$pucp-Se%!pJN7a6ppn}Kadrm1_gb3 z+}5od5`G4TtaSfXYzEHc%Y}%`qojR0G0O8x^zm(^xVoY8ibt?2P^i>NirXZy3(DG` zI2+&7?X7WCBMhVF_9#)}&*#Jg+JD)ZlHlc_jQAII`04$(3L=KY8J63#QcuQys|WQY zqT_G54eO*KdGRhWb281}28-%C`pDPfrdF+spZnkUVM6GCVw3C5s%vtDRw870aT#s{ zXF?K~U32B)20{%LM|cP|vJG(y7#M`6UJ6z*sZsZ5hBx%8u7SLY$~7qr0{mg9;3JnQy3Q#E7bk6JT&;z& z46K{(YXX%obZ(C!nq|2QhXK6sc<40ZPfrNQ{M6F=L zsqdl+L`i0lF(T8?%B~69252PW2ChAB0%F7SadXd=qZ$Cx@v-=E^(l_NBte1A5Vgk7 zbdgCcndFg>%K4AzN4I_^8y@;e~G{8{o8tPRVbS21!KqE?E^&{P&3GmiDa2~IIkn%6(Pl4Mwy1`PMNNx zp(CmYrFbYbOggSZtgV$AUg}a}0IChLPDWW*+1R;t*Q>T2O^>V>8pbfDP|Ud1Ws`@H zNg1+`Jw4CfFAO+h%hUj);3 z>(xfe2-{kflo9w%=sghD7-+;E(A%x)EoKOfXYS?a*i?pd8*BJb^IMKgW+`1wsCq=S zOX#TfMJbsqg~ENZZSeyVB+iTSFAAqG%fIIg!WAMYg&UN!?%l><5Kw(Sa+BGiTIEtpiBCH8x{-9JgiSeDpJh^FzU7 zToe(*SbPD*!&sNnkjIgB<5w+n(Cscz z4>fGpZr5Pp-eEMnFOgfltF48Uk&HJP$?3C;2++fC>)2AY|8f<*gkkqFDe1|m|ljd;Wi%r z^wNlC;rxg)L9h3&xZk@#5G3S6H6^w%SMit&S&v(E$_!&S?#o%<`VM3DE#!P0e6z24l=%73CU|LW=KBEK}R(=hq7S}!SnqiG?yI36`49uHgGt5jZA=?G!{ zc3r!cA_RRhaDO7KyCsQF`3|rv~k|j%WW&?t^W>9J4q?m>pveC^ZiGgF2V>R@eoF^ zGgxEb9c@=NNkd1V3lPpt6uB{WAyrm`FdR1#D0hgN@tWu*r&8B)cNr9^4BJ@PVD?DR z_+A2y8~?cuNy7I&D2sbvA~EgEj>{JBDewEBDd2q#;HDG3Uxn>4DqaMGwq-DU<4WUxOUM97#^duZ9QE`KTLL zYc0NtAqoLLz_nO<1>X`<`d5KqQu_}9jUMlH12J*_8e_n;SL^OFPGUus&?{CtgiQB` zuWOZlkY5Mkvl>+~%s<*rwF&mQ?x~+K8qrg<5o9T}kXVq2CE((!Ohqsu!bKTl>3A{h z@xrwZrEv-{TY~kHZi?eN!939rLP$)c7dtKElLJZ^Y6}#)DaYo_1f_~wB#fc9A%-6Z z?mjNG#|`h6I~c%j)-KvrJMO9`Jx~xNdmn4h_`gC*s}TIh*iJRh2$x7mMM?F0cZ9)0J+y zZnu)IUtLZnKt5c9IY1K|@VCVK4dROd+J~~|_Vv5d&MVhr(-jT_zgS)>Xj6u)_CEWP2V^2vH zF&Mft7!Z-sA(dS??%q_k4NKQ;2LU~6c@Ask38&ThOUUH&E#bsOkNZ``vrZOb(8U;=NX1iHQY)P#HDz2#>XZ{WAVn2Q0?V$nOj z_03ZjZ_JW!~)eY7Jupmq}C=oipxBLz<3<1XjJnnlB!!FXL(l zLPnTCm9;_Xq^{i6ck6wpk$8d50}}?Ap$k3a$5HKW(fKzTth)XSjm!xy^r}=v#K*m<|To%?;Ml zH8n>zoVuu*5?j!w<_4QnwUOkUu6zU&IH2f=`ZDDOS;n`Nfr(q_ih#z-VvN^?1^Bdm zNq2F3Lgd-KUpJ+0|8ov3o@J!1)1Q3QyKE0E(L2>Lxyg^I|KstXzAO(rh>0(IC8xa| z$DQw9^h$1aMj>!CjFjwmp`|Ns;l=hD;C6$g4YCdbs5)U>&zo?&Pm_Mw$OP69WHBQJ z8iyRabEo7Ec*`&`EvobPYf}zP3EqK~WL=BmHxc_#tMq`~`s)T#@bO)#urquwLF;$^ z5;DZ!-eE0j&d)Ze00K8uOPrf)AYtck#cdm=Dq`6Fc$~OrE`GeuMS<4A zspU#K>@bQshgtyZK-TJSsKO>D^qJfV$o*0?ti{JAyzo^o{_^v$Kfd~T`To`4e|o)q z{p;_4|H!Sh(ET8vQdDGgX%BwC1>dUq339$2+#p$6<7eGvEe_pG*|ZGCZU)UwtcY=K#XK#d z#Tl1@;}g^UHiQJ+ZVz?MchzTMV1(sw)#m}f{c&Vz%ePWzm;Sm_jzqFh{uMO%zT zPbw9tF1J{KqbCB;4tvfVLKjHputOE8KE+KQ4+3SwVcf|bZ?a{NBdP2Re5MvR_7s~3 z{LCA0=I-!*J4DhR_uPXHWY~V(wlHRmVV3J_SX&H3cVM!`AnWAY_jG7IIqoa)ZD?ua zk#iWpelb6F^uyRCSccTWLxSZFb{4418y11%tHoAtel&P7L&29cR>Z-Y-RkKO1s_je z|F-!w2%kjBPLby>QEGgUUp8WkI^yEtZRHjGDjXX-aB0q1G;xPC-rjd5;$A>Afo@kB z>0n$oC>jLLM;)Yk!y`Dpr6jQxiLG0S(O1~*Ho*26CY&4}n$m@EMgQW{-_$4drJ%)g zIQBXgX;-u*b@C4R%DO|D$@SoZST{cpT<_lBn=njF+#N=s7#J@X6v)M*CpGF)=Bt+B zpm_yN>Z6=8*I}Rjww^o5zYp$pbU`HaD}xG;6zGaLizl7?B!n8|JASbVg0ozH{N?rX z?cd)lmzw(+ohw0|TV91Z7((QJSM5?1O}q8>Gtc$^*n6|?Hjb=Kw||VUv2q?RZCS2T zmtEG9-*UenIJ$QBSH+S`&^t=Ws#DoKxT|P_I`(sl12sC zz8v6gmV8|m;w?s@@hD4I`P>m ze%pu{4n`GlbC+U{^V6|xIehr#^P!<6y4c^X?)iN$f7lC}4#id!9H^-Gz=aT)nle=I zK1sZxFvYdI04|h_c69E^1p04&QuEyYx`TgiE=q;xr_F^@;ic|i-a)oe%af9!ykuRq z1Bj@$DM9deh7WelloSutIA86dOm}yrFZ-oY-6Ih(Xcgd|2nCBu-+%_8P0RY;KB!HR zUE;?)rv_%a^Ih!M23W4}XfqApzd-z1`pENLq8C8?MK*j7)0P6!k&K8)h}3u*tkox~ zi`^$?NI@2bU@vPve?=;~|AKq#K28l^UiELckcZ<$)JxiLB4Dy4Uvk%XLMN%wFC8ju zJgHKiRy1XU>e^ItWZREPo5kWWX)|fG$qt}JD)}mb=ZP7q15koYKDJGf8H$Fc1izMo z7aUi6`D}{0ZSdrczW>HAniZ-59hnm%w!OExDFChcHNm6gMyO-#Mb}vZj%G>YXV%2Yx{B< z=1ny15XU^*=Ir?<_+*C;NlfxPyp3?W_zQ^A19`BlLBB2q#2?xl5bc5=!&c7mdl75V zz^@7Mzg7|8e?Oe;u=aaV5Lv7ex0#)N!XD)x=}OkcMH%8=%|` z2HlruSaQwx5c{^HNxO3v0e+}cnD=o@i7U&(YokcoSmw@t^|8@W@^d0CEZ*jO(Qh!R z?#wsAK>W}oC#p6V91l>5WkOXQnPf&l?0Dsb)QLR^J@*gLe5+UH>u$_lAW{wn4Gkn% z>j=GiXK&KTa+{L(cAyMqxIpIs{&P6NHTOQ-G@70SaGKyfr)I^nLPo~>{die>Tp2pP38ni-o5JIO@H|I z*n;UikDyFIdcs)$ynly)7Xj(h_}SI+6t@<5LmB0-p+H0uk>sXBzL&Y^JA_H*D2c`w zsZ7kP@3y>!*2J&>XmF+a2TEFT$<=VJhQmFMC(B{A+Y2cHX*IF6j(e(}82?R?JaaN@ zb|3dCzoe)@WTW^4e(}RV7_I?=%|Jnmo*xyxDY*2@yKb?#>p-sIR4-p%aS=W5UHwC* zi{C5Ew7Jz&pOL;YRu6mrkjEk~RB%l!Vo-=>>R-^raB6;=^4sa++P369+emEmTDnYU zKW5D4@{hab;SQlP{A&Tw_K$v4Z9yUc-P57t>eZK%T%I$j!A(9m%Le{FxD6z~!$+sG zY{-72g9w%7Rb+Gw7`)wX*XMKBOj`r?9*t#~w_^#ug8+eAL>HlCm~@FZd?&F=VrdzS?p`~~HdN>VtCIT~JnJf%aWiIDh$@8&nL1sMO*4?pSIgw@a-*9XCZvj+|dX9dDj*v}1BHhAalkRu6R zW#LUEQFvw_WUuRjS_~OR6+_#Q{#BqZ6=Kb8g|07oDZr)WVzRF$^ms188f9+FRP7IDDw) z8}%Ff1m(xjHXvUI&maWU=O2U7F|{Ew$$5OGx-d~LAF)286QIWZ=!t{EHd422rksZC zpK;wzu*3+-l3F-fBCm(!3Nfbd$y$bIWfE+#=HJ_I2xG2+p>5Q*w72JD5bT6LMgnpw zv<;-V=9{=z_q*{@|6}y#NyySL=iCl zv6HdTefGpHGRsJ@*sd%dD;#_`hZWwGWBudAg*E~3>1upVis06bs{QuJc5SZRQzO)R zw%fy-u}N8x~*GD^&jshRdw zN@XtvzOA5b;!s-0S(72sF_e7-;$jSm;0}NR2lPdLM*AaTdaaWJBg*VyB`jKs`C^K? zS?%wxZ&Vh8CeYZGc1mdC2)`EZtQUSAt`~IPnt``iHkZ>e_ud4T| zVecfD9$ok#q8lPN68yaC4CZg#|bNk;-}+)IdC_Hbi_3o+oc(DmLKCDw-JN+f&O z72cpQmJ-E#?JSWPheHj%Ufyp(T8iH!plq`9NTsw0QlXFD)bHzIy z_>FPrF(Jeg_mH1ay!fb5A5vqR{*~MTVNhZLq5oP=yRM#?+gpWli(eSvc~X7AOunADm# zYwAr*U3mH}ldFX|I*^X{-)N!q&(B>Rb`&nTG^&}gx<0QuYJRiHWj_%vK_{3BV}>+y zhhA9a9aD0NnSWBVVc~!d4T@EUJU~#vf83$*sr#jEBD*uArsL92{M|t1sTiS>$7I?k7b#hq3=#++Vb3f!-(aM<1xBA z>-!GRUEZ=$tZAaXHtPXE;9(>(Lz9@k2nwTdPKugjdJ3z6Tc2-U49492W61tw6h_YP z85ij1cg;>|qwpti>GNXSlMSjTy9dE7>mlxB4em#d5vSlNu=S&Wq1G@fgySqo+UhUEc?INE;TYKX-Ph6AylX|u4^EaCZ z_F3_;XP-?G2East%3PjiWl9cbxm>SWU^@FFpuE*VS64?P!gDax3wW6PN}c{sxmn6R zr0V&dTr_#83a2vk3gQL@SGaM;OfJs8=25+r%Sa=1&}{$kX_Z9pkL`cJ$Q!5-smM2* zVXOa&c96ILzku4o(Je-lUi zLcOzZcHgc`S~n9b<HE(R^gM7s;B`~_!uqQ)j={xq#w~z!Ycxy z$C6N3mxlDe%C!zw{kGYxI*Cc}1>EnOk2-;#sw{RFgB-;I1A#FJVZ9w*ku`bXd@> z58o|FTLeEx8P1#J4rzH87W<7nM4XU_;O2f%Fck!;%o0aGgVbR~)l7XyT@Fw1`A*=& z3q$ESRTsaiezEvv`_(8Dz540r+vP=b`d&fwLI2ck3nZ|jZik1>gbJ*Yxh@ktP@eKNU9bwrIf{F3s({<%ciZ^Yec;(RnHJa0#nGRw(93#1^VWyj93uy!>~IZWaok z069e|uncHG`{yET=MGPTY=kz&uu!WW301q*XW+BvT`~h3yCzf_gaCM84H3{|%k6Q> zBUMOX0FjG(3~^Q8dFzrxYqC%AOT5(#iL@jsM9pmZk>z$8h_a_;{DKGAXv4` zFyEeZvn*ZHDj9dvfN8}p9^4z%R9AYw{yrP>{A0+p`q3GI_{xW+r_50H!rlZJ8DZS# zS#Ti24bHM)!DSg1`oo;k#M5PY6;6+*Co(UK#i*1!p>TXeS8zo{MyW}26>%ZY>*>_I zT~Jn6h=W^IEcO%EanRfj_H zZGdZB$O%5tBXeG+mwJ^F{*ZCk{PC-}IHT0@Ka|a$CO%4jDtlKGcan4>q%9itT z`gj3Ke`lKyE1bAs1IGwNvP&DF-wOIUdTsvhX9&b@1yLP(VPGlLM z8&ir@o7_xL-;K~|5LaHVm27h7OLM&A6ho>|^z$_y~*Zg1M@w0)o3XBMa%PwjAiMoA@$M5%=?#re#xZrdT zUQ^T^oJWkym5}1J<%AeFMu9uCjcj+h);_5>>I)g{&0d23tc_5a!?C~}u6G6qre$#2apJkRaT|0rTvD`C4z`16E*2=5fv^)k)7zEGH{pVbnlTdLtBJ)tb? zg23%tYISx=g>Qg$Mjyj8tp^gezTHDMA$V*7YKCrgpmCkk)D^`{>D+)YCZ=2v`YK6j zL+Q%ibf*5ZLfVapK)$@^%jS3R{pVASzgsNiZ+|%s?6q_uJk4!*avt(hmu;li<^W{-Z{-fO?CM_SAN21Ak~+&q-^+8jm_uCGJ&DGsFoC-{ zq;Ri+3<+xi{$`y1tiP@_C7gTxhLcDBeNo~OovV~82}Z6p_j-AdQ7lPNdDoYSQ3!gm zFiOzeSdfBVEJiKp#o|H>`n+SWFF8N=yx6dj$WFm&#j!y2z1} zIaD}}lQ7_=MwPDauGw8b)JzGm=>h5{80_|J>22q&(iNAEOU<|edR54-BnP>E?UBJ5 z;X7Ov4UR`|fU(+iL=ntY?WHVvtD#JgmLB?{ON|zMX*}z1pp@RJ2ZfXaAv`mh5ifPM+mdi3}iGVtq9K6wI3+9>+hGD~-y$hhEx| zp(Qnvd8gXQ`df~B9sSfrl(s48uqH3DronwM$B++pR*pbm299`=FhDXD&JSLNfZaLf zI4KOi&79k2A(JCtERa^(W9j(UVW@tWZ@rgR!DUZQ<{TPAm9*aE+?Xuj{CN4rc*wO_ z#@w?F7)7Da@e=nYN-Uv|L7{oR3E4Siyaj!QhQm|vm6-~iTCW9ZA$0CPjt8TnC-E4P z0ZAhXK@NGQ8Ht*y9t7|-uB(U=3D zlS`Gpbb(sZ>@j3`sD+A(kd7;$K!HgiyE`;cAmSlAQ8I2>o-#m^bbEB(O(HE#su9S> zPw{TM6;>_Y94*IyN}EEJNLig-(PYC(Za%k;Towz&O3;pwC~$m4Jar+BA?OEKIH^u( z?dKbQp!^cN$zyF~8704w25LG#(0)xMb?{S=MY5bVvRjq9s$tFq9V(v4h%<4)$rCV+ zjG>@}=S&M+<1!MNEeWqgv3`B8*0^zob`&}S;rseac=QzE^M(^Pc>cy9*24QVw&V`| zCNO4Jp^s78=C9vV!2S$<3ibobBxM=J(Z0I_J-GX%)|trT)h8|~NBW-h+@wp-N=Z<) zEAyd2f(A~6zYjc&w(wyk#qH>g9QVtfc!6M_00N`)mJ&Vy0s_KF^>pUgopBWbc7W-I z4K@=$=i*}uF>ckO@e!V{S|mtb$7?uqzSLiWV}i<7*Oqy4Df9=gs9b|C1yo)AZocm8 zj@$s2ZaNLp)ws-a+e?cEUTQnWfwDUn=;(6Er+WJJfkMM_BOY=?gAs!MauCQ)9gylbnWi&AQH^un0Ecw8c+ zo+N)w>HPh~#5NZYKm8h@YB;k9P_GBoo%$E9Q(F<32c7C6l1@C_Nit5Z%V3ok3v?>U z*?iAa=0ldGSjsjfR(4#>y$?j2OU%`rx(#N|x7|Sl_feAp(x+5YQ4>Jd(Ig8qLwd91 zvYun4F{y=K=O0ff3WC4WPI!VsOsT*L299e_h6h~Ku&t2lq=vy;pKi3p?c2i*4CGJ0 zza35HUX5Shz5QwWFo{@12aLiidMOar07#h~CEyBVRbur!t%PJTzq85k$7b+uXJDTI z?620-xh~r*Ugb$6+{vWZM%;;F-$b-8Rvq&R;ZQv~H`3S9&j%2h?GY?}_Hf+a$u3m^ z^emI1s!`bu0{h3y8>AT<`#Fk683YV zyp{BcDT8C$q6%(;>QC@h1*VK8w59`pBr;1gWq_irWN~n2mJJZjST&dlk-+tx0)>tC zsMqLu{;7oXLmqP<$0F~g*DAk>_TZ7%>Hr{tM^Skr68)$a)kvl`-dTZ!6UIIppOYMg zvegR5tYYz0oyJTqb(Tv<51zfmWzcf>&U%1&D#O#HPFqziri}>o8%V1h)5P#qMLyA20F5iTCF$q)BA7FUZ>sP>Tpj8{t4u7Q z0JI8ag!!j#aola!YXc+P=PlNQs@Q8W z^(#At@lta3^NWT42aCmqlK*1yPktTU2TdvN!?y=Twdf!G_b>i)HgMmNa-yjFJ6rvq zyEkXpCjZ**|~EyuWCJsom;IeMB@@5{E1 zI8lJocYrovK#`S57ZX62%}qpZ;RquggrIa?mENK!^vwLU^<2bBWVuWFwE?{#xC)Uu zu!YZXVTXX-W+eiz1Jnl`Bp++kxG1G){4qa`TZOOADJ8AY{-!c*-)c@t3>Y_0t9u&5 zW=T59a^~Jsku*+A5X&5)gbw3-C$g$CsEZsKayc)n$D9dAXJX((C(Ptza;!5h!kk?0 zntmm;Nj&kW3oCJ{sJMi9hmOQ+!DkNHnE4T4hscCuu4!)=pduZKW~MQ)fcvIRP{qt* ze{2QmjZ-Oa6H|{uFH5h9aMnjP1#* zBKzAB2Q>{he@Y1x-tzhU3Snx@KLrH8duUD1*_ogR&$r94n0UJoX8-0Ra>%y`m{(q9 zW5{g&k>JJUA77<$$DabFb&^atYNCMrXGxsy3h51Ulwss*r?3ps=XhiK*vY zIg@Nn$kKshI{*59dl4SrmT~lK!$zj}Yy#1$`ByoulapLu$==m;*!wMoZb+i`i-bZ0 zuz1SD_(fr(T1=AqSdx*i0dC&F7a~?F8!*KU8H!de;E@PN%*NFVv{5_nLQeSmIFh%}?~G)qAzU^3(#Wxe>`AOt-xLFsCv+HmPhjj{ zeQz<@)h$NKWB12{Ii1(k&V{%mJMj5VEa8C|JH~C2P#9}CxyF0UtVpQy%00$(0XJ^y zVU`fbZ>eUs3!q;UJceu2iLw-OUss}`#9gf|8l0_KgkV$rj74x`N+BZ2$dwR%bE-1r zUqL^6#vL!fhD4#tx@Sq2I>psJ!^!Atig0(jQHKg&<_5{Z`#7QG_x0EDciCR)>s*(z zG1VeVmH4oC4jM9J?741aY-zUt92ad8{+a4BrYaz-&4meKxaJ-4=oB98C-Q$n>YGQWk2?#%qd`!zv!%rd#@fM+Bd z@m8t9J|EDyW5o3jyG8DjKN@`*!q6bL?s(9paks2yUpeMRSaEYeOjxgBbRCsLf zapQwUsrDQq66|te!iEB97u8fa|K?a#n37dJ0;;c9W>9+Z6cCs z$!eI%=|Trg$%&ij0J@<#7m+<MYXk9d%Z%}B15@PC$G{dOvC{}p3W~LNHjJyF<87TIUxepBUtk9yPzrq!1oVQJFO1aSHj=`* z6FK?rQ*q=L+k@E_XMzjumc0T>0Gu^W4!duUzXKo!xH0Wo6)BWBdjDJ$_0Z5^s9bOw z!AV@3v&Y3wNu^F#1tt+fjxyldWYkD|K5 zF8q5;QP5sDM61F$fsFg?N_<`c;c>6kmapf#?d6Y{zZR5Ih6J^`f1v)Pv!*iiS)U_b z-s8Mi)yc`&!+lOn@XuT4gkP^GFJb&;RTz}rBD#h57~%1z_cS~nu_hn|q;Jslf-iaA znTCNcoKUETy9Q@C6wQPwdf4(OZ^rL*by{pL>C`+T6OIg6-emybO79bmM4jsZcOGd- zmj-WRg^i?6r#^*y=>(-fybRxTyMf>sz1{A|1m>9fK~^q-8d{-n3d}ltVn*iSV~Ue< ztp<@XXu*N?#dOoj5?lq1CJA|t96V=o!q~C1?vLw3oE|q{cFn^hFSkXqsjmkr;M~}% zlNyV&f3YqM4m%QLEJBYOYDX66kPMPx!sO8$==-cyUTlp-x)#*Z+_zWH35qwJP%-FXZbw_Wz+dLVaTN_ z3x@WaR;;*3ZXnrWCjmZKC${tV;#g80w#)68jn*B&pdNV$kjPD)wbUWJ*Ro^p|B-3# zYvUiWE9Dp+${Ol%pBqZ^Gj=v{cEiRstI!~V<>TEO$XU&giXK=eVroha+{(wvQZ}eb zxfqCD!AEUc@NqdFsf&dXmsl+Rd^n89=|yaE{?D#mx*jb@>K+VYL4r_LD*B}U)8RX( zWo&@*IOPmmD7F#~;r%CuY-}5N2=%ccmuKU9TNFf}oK8hDZ~>9K3L$Il?;C`&munE+ zr~XSY(25tZ(2QQ94V(73-);rh$TBbd+Q5ay(gsUIhnaF)&W~cPoTNes7-3ZXQvaDo z1T)3(T*Ne-dLH-XJW``D#j}X00NIOnK;cyi2#t5`z?ph;&auR*+OPXVip1nPA8G4# zBWm57@rcG$PfDs1Y|&a`1XtqH^DNy#T5+JO9>##I~R+Fpku>z_G1jk ze!dO*u`pW?2da^#=9^K!8toeao}BNnr=QaKW(my3oHICO+1tRLlNttDKPYgS-k1zX zd6tLt9JkEoA?DczN>cNk<=F;kir_Y)a0OVDCoESp23}$)@!Ju-AaFJ-Ih=sb4lTk+ zARSQ2i@YNPV%X4khBISXcYb{@B444;fjxA16b+0q^f|ajgwI8I9`nz^9JoZPr09Od ziOv84YZS5X0{93wG-gIb*c?@L)ga%M$0uC2bN@kg&H4nnN#l(XpHO39yPa=2CgG&Z z+MtT0x-Hv|$rAEh=&!b^=#Lk8-=bS{O6iLGgx<^auN!_e>$9Qn0f=`)MI7y)h=P}E zd50zY)#Hj19N3tGv$$)ZtunK22g^^#r^< zuCzq_;N?>CLhz#DNXLkWO@LxB^H8?oM-emC9o3_Xx zm4Qr(r-WgI{ti|55<-R0-N7mOa=&rdn}2G*7biXqPyUhe41W$=y^B?R8i5(X<4Xu6 z8>vo@Z}w}V(Z%BLtKDzF#V0l4vIiyvTMhhrN3m&Q6+B=0ia8kEjW+Te9Z;K%`g||D z$g;gZG`oXNvpo;Fbe&{t@}X)_fsiXYDEfeF43Ib2X&E{X@KPZ?>OZ@rv!bqbF8W6%u&!(kA^+oyf=(0#B(&E2rwE=1p<_b|%MulN zPO~EX-bYP%{#96JLd)GFHjIwn6dZC>3sUqNzUc1S*g1fj_MB0Je9abql~PA7SOTcP#FNv^L%`fM}iMP_Rl zun{kapu3FzQNsyqdV|#9H!nba&3Bt$6C9Mmn?EHW%X2WHsz@{3butJtIF`bqmdnj- za|px=6j(Wv2uKxRLNw7P?2Ys0Kpbz`1^l`$OH2Ga!nF0x=19x@vtw@7ezzFtYWC8MD$6O zk%J{OmFC4rsTf>F=2MC0`9|i1C9XL@0fxt-f{os9(IGp8Bp8_;{A&1%qAeyEFY_FX z8-P?;PBj&7qoJV8Jy*5daya({3Mg6x{fI??@RoSA8huk?h}cwyX~v-H#+)ElPT^TV^54{ zQTKx>U1h3>Fg`c)>XzvYeNmIE>ot2c7Xht(T;pE4UVdIROLVlB-Q98XNgs+;i<_Rv zz@<@#`igg9B(a4pep`Z7ERJ_5ki|NzRSkRurfa(usV^|>CF03gNah0|a_<@x3J{^E zDH)OZCZx;Hc^fy%)sF};ERRkIu#4=by<{zNxq>;_3NTec&x!=okBm;*%7yT>0xoWm zF%+2g_)+i>$4;{P71BRZ+U1cJqDv+uk@Fy7u3I*6zY!-OaSnqknf5-{YcHfu~JPM24FOXZv!|4v}ppGfwTw};^%{L)C;+efLn*aC!$ht<6^|<~XlaB&A zPz;U{+ZNSTt@jp?;JP~he4cX_XOG}Etd%Uk=SW^eD>(R7#CRsOJAljvKL-q#-~^7< zw#{!;P`nK94pde`yA=L#@JuJ5bUcRBb81R>KHqan6d>lGf-OZ$+CX?IC1P1_B__;c zmGi%n`YvL`f=2foJR9bMkNTl_zVl3v>hTcmgdCz2s>j~@TU^-6meYAU!!g=CGK*5V zGo>w;{+Q7E1PFF+|EP^xW*whDQ8vyYkso*4qfw9in|yZ>PwLe6mDr$mgEO7!@epU6)o&&e*G2ufZrLWoExxSb> zmAQJNj*M=K_7%t}X$%i_yZX2U;yh?63=|iK3}i-AQmM%Oxe71f-3i{wwSha;=EmTB zMs4nqVN*$WlYrS*NT>d`Za(hwBPnaSq)f<7TN4JjASJ-7Q7|UUk1UAyY{FK+`r)TU zQhGa&Bs(<${+Izmx`RqAs-*biz+9bV)MKg|gkCB5efb{e-%Lmy;mK)9rEIUcscM|W z=S@bB^#(C=wP|+W^f^2EtF5#Oui%e)aP;*=G8x+*=%Y<##F|axG+eM#^QHP_^)XGp z;y!hMTw_N01&4||r~4F<_-R9)s|xN8|*QeTy?vhsz3TXdqUQN@H_V!(swLKfjD2 z9LD*ln8I_BilcJ))Tv@D*=X>`i2S$^57KClOZgz^mOw+X$3P<wA&j%yl|c&ew7C&f2s^wH=XBe-lM1QcnD|UNha8G z;bM)ACK0;4bcay#9U2%FwKVxc0qcTMd#XW+GZN$x@kQdxyUj=alk|G^QDI$WI64(# z3oUBh7)U}fO1)!t)?esbV>=nzL>8X?1wdw*MCTXP5w=sjZFX37mLQgvq;Djq!>$Ql zXg$OcAztqfnLr(Xn`$g^kuD)J|M-!B8Tx9seft3S$39uk* zvWYP5oSbMvTOacONCgf(9b;J8DKr5FJU9{6>eT2Oev0Um+jydOyIqgrd<~DTQ7CM| z6BlRj)A90b=Z)Hidtnf3Mi%sAik{?LecB(aaU}%yL(-NNvPs98E1By4wd#g z_S^kpguUiR#;*+|#4TrvOu_F5h+r>_%6J}A<5svjPFsqT0x_Mj^ArfIydom}7_enQ zx)hbYo{y;!GETdsq98RvuxD`}&e;xP#&XZ{>(tbyy5!e{H7DxV1Y)4UQ7lbZrWn(s zoQ`^^i)aBX7AQb{MH-Rc{s!FRSDcHlV*u^IEwLhoeEcdaQ)7qa{)yWl2NBGdIM3nW z_(lRY=C1Cpx`Y^>Z4+;bZEr}PuNefNN`s%mq+i@-RZIK(;ba#?IS{fGsEQQ$> z`i>k<22jwOZsyQ@{Glb461WLCU?~YvEM}`iYAwqL6l$iFva^7dj(zz20v6W!~EO}g!h`n;X2K@6T%BVA9E{cO&f^iKh6FOD(fYXzm$7%;@SKG|~r4J|FU zCd~^16Y&oubgs9io7a;jM~Q4ejjje`2s_tzQ%W)$Czpk6T&qrQJoO_#;scJZKg(N| zq5`)2EU7~(DivsF)%NIRl-(3&Ists+D9qsZ=E>)b!0+EjJ|{SfdQSfV*d-oL{vDOR z0Lsa_Yw9WM3?HVa2nZiY#msMDeha6VFwD1-4a^!qSdZXuSrY9Lfh=}C{hdAqK&QaX z)Z4p01pX~kiDP+v+}|PPGU&hl+p*c*SOS*Q8Ezsp4WN){sHdv-uTkS>8`>)v(^%S| zTjrC!+NJME(g@I0-1UgT-;t6{g_$d(TD!4Ey` z^F85;lrJz2B>j~SByDkBE4?#dkj3q*;yPd|NAO?uy8!|2|xfeJBq0e+p-qS%Re;lA#1kQ=%Lkzew8$Vw#D3)0msWobE*lXJ@248JehAhZbd7WWqx0IXJY zCS;;xO%8cnxAT1gAvaYjp0Gg%V8C5#R_Uk>eEvLR(ECWC6N$^~*jKg#Z$(+;m)Wim zvnV32>%f!FrzZYFPb)#DlzW4maob*Es=>edY5MN0N+iJyJy_F&KCBh6Z5_Y3{F;3z*gN}jRs+WYzEupA0XEXzW-9|u!hK7_N(7x^a3$B9 z>a1!~nzji(F)%Nh1dDOA|JS9y*`1HixOpS=Jt>)JLoq~6w!1gypLh9>v;*Ad6-06o z1^<`%MmEkg(tm0WSHVs$TMeyQZXZCz>@}7K(F^cQ_e>1c3=8Sw5Vshm5ur1*9O1_%lk3Od_sv67#iGD4s|E*v924kq44*Zc?tbc zG^*yi*|R$er%$qbZ%5oY^f}_l>AB;6ju+q};rnKJ7pBLl)JaC-D#((2|Gt5Fs+OOW zRAY=M?fEW2iXTQIahP^l=G#9X4sS3lM6*+uNYVT~eiYkC*&ry;01O-LH`14 zc52ZXe0R(UaBj#`#WfGHl<__2SB%|DZh1J%;A;iVWD1On3f;RJhwZi@KE~-CB$=ua zS*S3rsTyEp;eEk%e*Q(SHa;zc7(HHD9%T?4qIhUBMEEr-8JV|AA31YNJnJ_YXtP;f z!mkbVDCYaYuL(xS5{mk^VVj$b#}8GAIWwPUMsg#ovmuA;TxR~fp~{wY@aqJ0PC~~5 zS+US209OY;28-S`Gu<|#4{|70hvpObe=VKRa+50HF?9T& zAcNU0pZ=po3!Yphvjp4&{+^AXPoc0$#smN-Dw<5zwI{p9I3asf5*h zV+vt$bzKOnPjxW)OI-$=%uVq9YgJk)IN=DA_!ls-w*L-pqbqyP5GjyCk{84+r1`XNm*y&l*zW}5lDW%G1xm3=gwxbkw#7xMowJtD++Q`p`uC} zB<@*+7*Io@rB+DEM#$k@^`eMaXIw0DqET7_pb2G;QyfC+62$ zckgOYZ{i&*GDG!1t_b~4pxEC0b+D@Qv(9f1C6^f51fn{@kHIy`axk(Hc@*kFIY@0A zniZP9><4f=I@C$(c2H8^^4=54=2;F{d6xRIXe4^@Vt4*pOm%<9boqQPn{|A1$Xn1@ zafY!owe+e|M)u-IW`Hha^~~$)RdE?OA*rae9bhxC=RR4K0C{^E$I@3 z{Um^!d)p_jdu>v6oE8bDyGfFXg$#Xp3W+pP&e$ZJPWQ8Ef14;57t-6Oz8tt&#Mtp- zz*M&81bGfl2x-^610Pe7bwLKicTAG<1?)H=x6N;(^w$psHQs=2aFxZuE^YG^z3#rB z7I-Q-G1V$?vuTUmL{;}~39O?~qPN<1i+D=$a_`N+l;g&h2?<>C@Mey8b=Cv46-WZS zK1@dC;*8A@I7(9ZIhK(s*^{sa8GZ+124&TH9_r@3z~+Ys5yk58p;Z z=+lPyeb=4o<46uZHu>bPGYmy5)1vRX7SPU=m2plb&~=WPVLPq%7{`z26OnSTkt&a9l0Y|h89dfHB1IbnggYp!6p;ou&N z+VA7<$V3S9pA>u}dR5q_`-UP^i(K7+7BcF?F+hWQ$VJVlfITWYw<_y|KssIWDb^!s zD1HqB62U(p^L4d*fvO0z$Fj%z4JTol!?}83u=%l75<_bDJ-o!( zN1_v&jtpOpCb?LtL4+{qgdbZYj_y?RVAK)in9r$U7P$FZ2YLsCdG) zI3wjLxA*KonR8+OE&V1=8IDj*!XXm)3|qD$zc+aa#c35V~d;X+SrjsTM_K;v*n`ZHFOU3_-Cy z8PZ|&mE)b1R4Ib93- zVvyx~rDRlscTN~dmY4C{vk-Th4uLsEPxtI_l|IJ8+)!lKwGB-l8`b0&3oR!v=({h! zfi~53=1QwpaHXfW$>Wq=M}=IZjS)Kc?QLp8^P{diDy<-(VMr4VNL;5;3|=9XB4E*x ze?bg-F=_bVNe>;LZ7N488IffYOTOd*RMjn6K8XoTrC*1;XCh+yMkX|s9vIkp59%Mh z&;p7xjrKg3504}C=LW7XsLA3tJ#EEK@uX?7JzqQtg$+lqyQkI*Wa%lC%s+-+^5-Z} zXrSFEqu&K%BZFgtN3CHD@s&U-L|o4$R!WlOCD z83T?-?hq+BTLm%$Jy#JR_67`6%y)FAdzHuGOozldEy&9{G{VOdIY1+vI(%?vSYa-H zi$v7&T+cBiUE5YQ8ju5OkX6(o&8Pr74Hzt76MRx>q9B8G1lTn46Udv0uYhM6g`{bC zZ-AS3y@`voCntJv8^m^@Z4g$>H!&R@`F_0uIfE#l`kK`GHzMK)bc#P%Za=Htz=5$G znw7W~LJ>j?X6X7HyiF?Jhkg?T8zIZH__h(A@j8z*016Q8(m9 zQ|B!f``;NODR zOB}vzk#%-GhEvHZo_h58QdTjtU!kM&0xA34MriU|uux@!-vj`kYfzkPg+!(6Ih+cW zQ!qL!)g@QAtb+>PBV)* zRzux2C6LY*&$hZ_V<-E8pGVqvD1-OiNok2gmare(0T?-q&^V8y$J+$aTY>Hgcz}c| z-EQVAXwg_kthjG69gFZm(btint9J=Ryfr8Ul;(%5?n&ry;vll+d(d!K4_!RAAc9j< z>XsuvO1se3Ef+X?s}q%;sH^+BQANR34YpW4B|2-)67<3nB9wwmWvqdyas1Hig#Wr+ zZx2|Qe_3j8y^3taA7Zjs>zekSfYJA>+^EfLkXXzBM30&5J zw*5;y@t)dJpu>8Gwk_I@%qgBftod#|vLJV5Iy zO&;kq>#R7p$B$Sn{+TScfA5EX<;2$f_Yr z0TC-AxpYEhyE9PZ?)v-;6y{Tw)9N&WlvC0PE`oq@(vH|@|v^8s8tsA)@? zLARTH5LwR2GP7>hAGf>J;qD%wm+<2;pjmBYM^Px3uvT7P zz%^Oy+=3}eEGC=>r2@R1x$)LgsF2%lZTMK=%RXY-NZ|}adCXe-<)QhADm!5CkNH#qcS(QZl4a>drutxwzlIWMO2a){}ofG|y z?DOMZU&1;DcnuK-X}K=1roA3o98wNM+uSGMeWL^!d2ZHJmR%VS=P*|e}ntq|!&+DBDCr?Ka(};NuIZb_V)4iJvmllA_2PPyvp5j63K|`ny(t>|s?5AAp`cMM z^G_er=aKbO^|4H}kvZJbs>Ju89tP0e6!iU-F%w$})Ng0NchYjI__cwV%>1zVHIa~T zoNq&{hPU12tds-KFtGJ>P@B)N=64_We;RiA1Fa{rb*(=7f#8b8pDU_``unh12K=Y$$3!>tK*f85+R&)TX< zNn5sRI{8#~FRu@qF%po3jyB*WpL6EHJL#(5R9I(bVf}{EP^9okgrbQEfLZip3pt_i zEdeo%OB=k7%A3g%u91aOo~1whCT{uypm_96=J!Aumgi_!5D`d%A%{bbNo9wozTXQW zS8qAnJliO3@fmLvOR{N75{h;h3NvSa5*Nsp-z`T;o4z>!%l+{8cdvi`b@}VhAAT;E za!1s@2S|ykiYy8kl2SHplkvGo%{l!cMy(%M8QAmTXNsPPO4OJzdHot2c>eVZ%S+e3=YEfHv}OXk zeZDW2%dZa~1^c0Ixy#*SY>+N8t%G3BiGm;5qP>?-slHz&c-Fc-YgE=%{||*D_$NJf zqmoV*dWkLw_buPm4sAJj3uJE(-Z6-%EwLp1Wh7FdZvypFo%GH= zZpL}QeGDy^@!{Kp!YJ<_{P!>Z zb2f0#7A77izpG~WbNA*<_F4y6v3W3}F!ZzV7a;>isw`?S3(W?hrpV4NbIpZwJLz0# z6@D>4+Ml7&u?9;qQ0RI*OVYMKSrFewp;czC)Eawn7N5qJV^r9m;8MUcAbFE|XNhc(Rlgnqj32x`7U8@a zOo!$N#`8_WpMvgpAr73Yh3au|8-Ow`ZJg#QH768&S8ECkdyu0D8baU6nUTA1Y{xAA z9FS&_dI|&3@cGY=v01Y4b-Z!|ubjz<>H0F8jBuKF zPjT>!d3SNLaHo` zT1{$Wr7fy5`7VF=`u*z<{4hd?aT8;p4So-sHskIyKE}AW5{hcg@%Q@c^^?r%Edq^D zdC^kLLp2zW9{nJb*YO4X8h`Z>e|_D&k%7CC5+l2ZaW5ay;4jkm-j>;voGqmwncrs_ z;ele8*u$ScmCg-bkUDZbDd|jGLv zNE@Zdw&#ecdVj1F-09qOlXRNV&#!1zHii=~e+`%?Ek@J2@jmEhPU8>vRj#busf4|b(poD?~mvIYV&Q$zvLdh z`9>;V$Aer${_D8HhI)D2tPQuK#X*+1zsyO~kXfB%-`vw5=f>cfL0V_Njq}A{7#Fu{ zGI4`Bw!){A%=AHg_y&laDZINJ_++U{|J}!fjNpRs1InC#2hVAR9%^VCf)t%^L-!?< z11R0Y2uUm6Hap^zxZ+Cq(0mjPR77(RoOeRGQL4xCw5GxdxDq^}KEMzg(lVxxD!m4k zbt3Ul7MVyq2B~#^dYB9ldlf_htgU|Dk9mThj(PhN@WNv%E>=hy<1~28dwqkESu4CG z(tV6cuTUEvkTve6I+t@P zL5T@Y^$_*UkG|(De1SU^!qD@N!6XcomM9=Q8);{3CrOdPMob&nB_i$Y`Ib=@e5Hq( zY*}l*&tc0>OIO)zb7OA2Qs{A#k_AnyP(kv}jmO1HB$eG%F4yi!soIt3iBaJmAY5Q0 zoMtKDbbuF#;S?28rAa>Y6U_$YQRwbih~c=5X;ew9W99^wX=Pf9PJh%O9zL|JaTM$D z>}UXAx6NWYh0=o92%J4Ci695CJxp}=`;7?3*PQ|2UjR}%>?7A6!#^qyF7u^3ir%?>HTv65|i_gnJ&aNVnju}dz@`Bp-{CsMDq3-~qJ^0oDvO4rJ z@CFZUf)yCt8>BleZOAeQsrwNI<^CJukeH5e#(mlD`X%5CxFQDCl(&5nH%Km{2GOMc zBp1X?g8LEdad1Zx>4!f@8Jw_9$WzSEiL0^D7_(CE;(uW@C$%l{vB|k@?_>u_tE{HT zJ`73Qa|BZ$lqRlN?zb-Ox!$Ma>Uy8f_YZ4bhQ}U*^iGOmXTyr}*EWQq6+B*XIdpdI(>a@K) z+$g6%^wj@U#+3&WO|G~-)AnP~lj)K>%)aHrnwq6V38qsF5U}ZiyipARI4Wku{IVRj zYwgA;N3;A#8uhXC`y{6dw(0k`{1pGa`pINH&a>@7XQ5`%WF<;9Fh0S?O-=N zrV*;Yi-ilNNT9UcEmhOeydWaaDrz^L@Mg8`c9K{^pR<(Ad6jPept_~fbv!cH{KnMu zY#)98GEaK?kLKZVEHoQ`dTR>VJNc`r@8ywRq;sXA@jq}H=WpZiptg@0O*(&oRn&D| zDI8h+i}01B*l)ImnW()mmMhO*zklv}9kdICO4jodC^rw$bNwhuiF9>`r1FW#;oJ;C z*9XT$z^a39`DmkBa!o9JA+4Sq(2`-F$^OWTx74Q#Jd~(xpg}Yuxqhrk1!TRUIj%Kv zNuEIB$`lLpxyzG!@Cxyee2Z7}xn;1OWtuN0C7E=3mxxwxJ&r+D5q6H#SD050Qkc zgIP1SO+S}{=aqy zL)l)g*r8$)K%gKRWD-Kp}FdU4FxdoFhK9i8hjf4bRE0_S^DH3*fO#|DofD@Vw8FHJ3<)9O_86|jp zv3DO+YVZ~5@WaX|Paub0_Eq0UBxp;OdPC*h%2UoLQn*2mF?DkD#?^g`O656v0LB~- z;d~J&b>Yj~9a5tSg$7eXVR%5wtzfWWvsCP^h}zfq5Kc--lyxG3li}-BAqXwiV&9dT z*s!QLhWD$_;ut=&Q&b1UV8z9hsfe(C#nY8|U&aGPF5k_rmPzJD$t`X-NED@(U%Vj`C(Jx zBAu%44QBQ%sb-Qoy0kZGRgpuQ+(7}(qMLFozp29q@`&%$`j=*}I6Pmy zTBZwM2tV>b!6TW4U#UR8zrYC)9%rWEoLBA*!97ZyBDjq#e6K(-B=|A#P!4VbrQgst z$WvLm^c3BJ=dWj(+1}I}sbU;O^?*#f&~T)nah5LUWG;~7@8hgdK&1;VuNErK<5p;P zI&CloCr+%&DT`cWgLJiHW-Amf24X0Eg-%J5iqO;fTif6)iv=}EwUcWnS5!XQ{O-M` z1yWt$)p#Y^#!s8XTb>UM+2QGxZZOB>l`dGM^?S|pq(EKXt3$ISt1l^jVwWlC z8rrk$z%Z_c)fjXkwuo5>;&WsXqO4`Jm(P3-!F=c`^k;p8Y(EH&#v93s<8tV7q0Aq= zY*AzkeGKMQ@T-Ia1xN%1zljwgO_6aie!@-LYgsR6<=qp!>}~})_UBD^2a9MXB6=b{ zhOu|cg@pVUG^=9phNX&nRPbP?mh6EnFE6Y_sroO?u7}=GYW(qI(oAoDCrI&cyY2l{ z_q@)hjg3ITGOcNw0lh~{KT-|W{dxWGB;wkBk==Lu>G<$LM3Hpe^@)|iEFkanxvwZT ztN!t0*+VmNkdcj4G*1Au!o?OE;X7FH^)1w7|4;tn zdegbN{Ajf4x-A|x(k_*%ON;WU#VJIZ)3EZoC@nub`UVk69otkC8b*x)rld03A|e#Zp2|*^$bw{ zadp35Wg-k#G;O<6pX2mr{dJ|I`h7mJ8le_enIe6G(gMox-X}H$l=&&*7f4%u!2FsJ z@9_D@pd$*SJWlHT#EO=a8x?A6qUT9iQ@~Kl5y&l7S0#8+jaP*zgBZdjB?*+ly)Bxg zQ~)W9bO7WQ=iOr5nz?tt6o3;*Vv9;35=EX@4UyZOe?7l0A|Yql5M*z@P)Iu0kWV56 z=f*n1x0C4#Aq1|5H8{}(I!KlEiGQ{gQUB2QAyl-ykM5IJmGDy-8!(WFlJyNcDHQEK zk6P|Ig*uH37$;GrfS-cI92aGgHumdPR7gT!1bJ&m6DZz;$R)Rz1Cx8NjjIn}*8yqrpS>;+-8(gVi^Uh)4ly?z~SuD@6?iIXQavKQaZCLktpm1DUg&C zp4a^@=={(3Deqzq@iVr&$oI!7D%5ygEVbvwM?N3H`XYt2J5b@_9QH2qAjdQR@qUZU z9i+Q^fh{2TG4LV@ZKJA#n?Q%%b!Tx(YfN>}S!oSthf-*C^aUwEm~Mbzl0wxLZZCaJ zCNjfLZzw52CyVjKrUn8`49#df!nLe?nQQ+MDSgx@oBI^Cm$F-{W^)usEck>LW*26j zbr0IiUnUJ5PseljWWuTnbDXw?01P^vu#-%iYEcJM6^H0Jk+9dwsL~2U7v>-8mvt$7 zZPBj5!m&X0mo|?6)$D#5zpudmL6}0OR?8v|D1h-URPbS7fqf$z829D0Svm)Cs@mKd z#M8PaORMcT42$|n7DK0SZ`*O`v@%=KSl}wNtU@exU~^6T*k5HQ#%IRS-|nfFx~5uG zXDTa63=b$@!S>_I)Nn0b!Hl>jz(xu9B&Sg#jF!eziq$ zu-_g9Z<(PhQkO-`z!ZHeR2$FzDz!1APea4KDZdu=kwf|%z(2`sX)hdoI57K*ELH%_ z3TPBaq)n)Ffs{Q{h@J7BAEt{ZzAjr_h7>wkcuM4tIsEatTaw&EjhLgVTHLp$+&v~w z;H3$>*aYO&QUrNDyP9imaKykhH#lP8nJpI(ziDGD1^cyt;$3iD&77Z~37(I^&N$zO zo=rFP6XM(yI`$-*4;=WI5&*;`&j-_yeV|pY?2u^&%oK z1B-}ua5W*5!Uo=x=b@!>EqA!qU_6WJ=Fl_>)046Q0LBXr8xl^K;O7Wu*CkloyB@=3Ni(kan~pS|9m-XG{wbKDp`sDFp2N($9JBGH z>7rIK1A*)LpCRG+nas8)op0*t?PJK)mgPP|kit2d6}=n+jgD;ZDWi{ahh3SWL9q}qMccdV(Na^V|CTBc_c z>2v776%Kdf08kMxVy>vFjk_Mf%94|m|KmCcrGq@cY2jxSi!rsUA*Z6~05QPW9{oto zB%Jkd-Mdq3iFDDMC`)XUKyDTtyP)?30#iOe#mzEtnI2DhtLK{@gH3cjge%p`r6Bl- z7cO(?a{%pdooZt?oT+ss+F?KyCYSPrRQUtxs}I|~7NBm{P8O@34f+35T*-Km+nP$f zl+q>2a8g`fYyjlL#{d2=&|v#EO|X3;$R$ET+}A>b^*ew|n_R%@Xrh<%^>)AiR!fTV zcloa9?v9&J!oTCTM-CU~jwB@?D%csnk0wECS;u~DuqDrLCpuFi;XBv=Bx_Qa0tBLZEvp)e-Y? zLytt$j2t^Kr`lUZ)}1|Y1&b4)Bp_Nuv3kDaJp0}q^*YZ%sz#2-a0=p1QSU85T>TrMk^vJVK;&n{+69!6`Y2Ky@(0U1oITg#mhe`7 z`?mSE-ZuStiQ@u3iYWCT>aPbGi4?0B8HcD#d;UjA+jLy(y|?Wb@c5D1*!(y!^+KXFyZxjIY}j^tL1YXm^pyzDVds+uU}QjyBo)G>3t9>ewkghLz- zEI`?AzNh^5JUn>jn~=^nbkxiAp|-}*>PLvYUr(#2W-iRD$(^NaR7ZR=q=T?3awZm^ z@hm_rxaDL(Dz8KHFGa!AcZ#Ci6`ZD#67GDj>5gx*PNYB(9?U7MAlEdcY0&{)Mx`rJ zXkLw1E{KK^R$N+IFh!1!lUH|%koh%75JM%d<3O&!2=3wtw%{Mr_o8IVJf{4|l8wl% z*EN6#_yXyW`bSzE4~}3kE9t6uMVA~mjQK%;E_cUbpuR3-!7B!Y*a zB6KDdt9!eeq;4xZTARP5MphI}N$7iBDaLaheeFBlNW|FR>jcjtVxJX}G#FCoL>-o+ z8ZIiEHKU#Zrt8?O#dxIzYhVG|`|SrWpaMXp!2ZhD;NHR@>(2jT_yW=iL?Pi54e{I1$w~xdS>B!#o^3evIS@RUZ-Np2p%PTJoVz+l&ZOXE2R;GZ z3+_IM!ZE0k6I=@O^{efAy8}N|ZQrr+fBL)5nxP|vdgE7+$gwIz)RDxpX3qM1J18=pI)#C_kS+Ydn{Uja(dQ3CxGB@ec;q zi1-+=4rH#;3?3JDb_oZsPa^a%)qj2c?#;hmFMplv2~Vo@uOII4&w|!A;>59ozr`qd z8rhx`L@qy;JMpA=e^n;{V{Nix{pLHTo%w>v%hP1+b^4xNf5`sQLJ6HD_{dStl($dbbNP?G#%1RvX5m~ zGq>aKu#AYDat){#WNBK-34wt(87!tQ5P9O)JEcw41vVT1kLj0 z{ee8o1v~5%P2U#623S=_LxC(()o>Fg4Ju1i-v!GNJ(5!Hi}MjdGO<9b{c#vpU(Jb0 z9tV$aEA3RZ zV?W(Yi_5s{(^{xK*HXOm)E?8XZ2U0B7YidQB_*>Hl0Z(S@qUS?3YB*;PwP2ku@oD7 z<+-~o-kX-piHyDBwvIc)_p2O^*L9{hSU@zCl9W7o;XUp`GH?yNYtW{n$T?~^1e9gl zo>2^7BLkM32EB_cKG2^-yns^@o01pej7LgOHUn$)+TZgPL)Ds-rv^Vii6 zWq4vb3onCka9R#uMk6jBBW{UQ<@P?}xtB=}@n{5e^Zj^h0X^8^+6*-ex!}I_&*1?f z51w53Lj|`1x^lh^**pz#cij3fEk{qF%Zn)LOeEw9jV@8d*VMC;p#g1$JgoWT8~&pY zhdZhNEq7l;;z%6i`0^a#KGMjRz`$=G0O22ga$7BL{hp%?&kAx`woJRJ*R|Z#^4VRU zzeI>@!-@EH7d0VET%g-<8YoV0a?3!`?+0i#Esir^P zgpOpu$$XGQ5U|R0u9)OM3^Np_Av|Rb{2DUW;}X4v1eD#u@ZrV}S#2JU(D+~BCG$qU zJ>M2Cf5iN?d}M|LjpibodKBjr-VhbA5hQLXt7Wm#*S?g<9&H8V^sOWucH=9=k>;u{ z*Q<@F6Xq?~c=GPxJ=>Kg_77H*ZniTWA|j5c(QD$vy;liZ^6RVnXmHmfsumndxNe)P`|&y=Oc3$+4R zkAO)^0S@L}=MSeK{}{S6xao(36Y(}q_FITI=|zK@yd-vShK4n|UTX@t#tmQ1ukTr@ zE!-U(<9qlQaZPs3H-AqZCHQ6lTq$@INR)&QBpDA^@a|uq#tH->=D27oq88tAavfixnX6a>5!C*$Jjn?Fk!rcn01Ik? z5mkUy{5D49W5vk zJcq)JfJ~Y-IY3no=o@B?X(=l$t@M6xLrFVc}d*b&4~z4m|gZD7@T}WHx9C z-EfWidMwSyfF$k(YqMAVsU~0H@7{_$3#-3Q`wRgFj7yTbDn~2AOAHS{$-6E4ezOM= zU2Bk}-~!{AOY2$e%WPT9+-UT`5;5MwjEWVFn z>rz=SXTWlk@{*-K=DDszIWG5$#dKvBRXDErvL#j;D$3uobii8+Af&-+1yjXnTH4Mc z*ffEjUj<|EgUe5_uI9&H_Rm>hQ(T<(%n81fi!k+a-`#DtyWJ-xXc1sDXj8?dYFJ@Z z#JvM3n>4}_vAsj{KQ5Bd4fG$FK`yfk!VMBLIp)l38BCboab_$VV zB0P+7(RjnBn%;#EO!BxYR|#6s?62+bfMBnpvhTR z@6|Ui2Cuk|Jrk;!3?zeN8Om$# zloUy@rsf`#;%Jp+-szz{+)_mDO7k;;cOQYidIs;m?FmZm?*-Y?f&dfB1jQ3X`hbkW zI5eH|%k($b=ZuL>%#TSAP10IzN@54YzybwLSV!K|7)1{2!<)+ipL)}abToqpVl2f# z%o<>PV)iB&cF&1}UcL46^Jnmh zM-b&hpQR{$B1)t(Aw~ENMx5EyedwFhWY9dXqtq(?6~~4RqtRK?VI7)iRb8|=k1A4* z-XD(cw{<2wBM+jmhQQdaiHC^u`#S&?q-p1$MR%rC(S5wO-x746q7ekfmmNjGgE%4m z{^plg%LK)kiPr9dagFPC4#j0)u$9zmC2-AkeRiB6Sw9d$WPL3*X9!k}W8|!0PbB8& zSFmGp(2kyU-X!H3Hs8i+ngTndE_I8tc9~{3!~ueLXj>dd?9LBbP5zH&|4DXO=5z<4 zOF;lc2{-{kUQdPWS*bjy?BXO*J0rVTY}@~+?w~cdGZDFuV{3u^<}v7!Z%Ke?^t*R#0fa);z^Z{T=4__@xLY_?@8YRc z5+V3mq3)2f=fF;bOzf+SO^|H~Py9xQ3!44n`iz4Gl5HUgzhNMK&Rx*|kh4LN80H^Y zv?xe48nSQ%$`Ax%4o{GzrHtrlhOukb*SqE%B>P5sSkS?S+_6L0X!`EjRg7zJ-*pv} zwTietcjKN~p#zd&(?GPAmIbtkD7kpJS4}X@zC--8i34I&-JL6{5>GF)9(p-BDj~3Z0h}D_-cUAZewXmZRxkm@)Cts4Rs6 zy8EnCv$zRRFJP(WLlTSq!g9GgQn1s*wA7`@NqWOGBt*Mq{;ZH!H#D@%nt)bseI<<5 zzYIF;U99m(1Inca7TB;|_js8Jyhe`WR$(j+4-B3nVtn3} z?3jz;{M-2LCY%@c9=QaUjSdJ>AlVn2Eks>CP_?2AhpG&`h>oc`ZXZyqnn=Y8BJF^G z2F}cIjk&rY>D(0=lW=@`RIY)vi9)fyy&$_=cn)WrImHy*q06|N-U?m(`jG3^{4kvF zL`8i&eiPK(VsT!S8aE>DZdz-`1WPi3rU(uVamdvv7(QfD(n&NJY8vHh$TTHq8_vh* zAYbMRmpujV-S*pMfX*}KCOv#gOO18@*Sp=NznT7li@)TdFpfCxWg?`wVpB!QR9+TM zUVBq*tpemc-RMVaw(U->SyjJ~Xx)CfdOq_bCadrSVV!r#MiwMQh51fy!S|3$N+(Cf znerYd$gPYwuXkOlyD8A1FFworZ7-w+Z7ER$m8%jY--+X!r1K7$N%PLnSieaR*E6&U zbSr|>t=1~2-<#Aqb90OpBVpbUv$!LI)uOIJ#Y{*Q0*b6{(@mAr` zue~+9Mf`ug{(Qd>aTkIH3Mv`otq3-XZzi4;czATl9WeAcD5i!sfxM|D$n_gnP8`c~ zunr_LlG8V$UZWPQ51g~=!>Nr^?IG8X#Lln!EN`l~A@*hR z{_p0_Emo4_tm6ZL0D+Jol*A$tvV{R*DZ_M6Uu6k=yteTY+ga9LN3no$U-t|?mtkhs z-nDo_NHG!@3nCFAA+3Uh9K=I-;R!?}K$s^GPmw?V)Q1XCyjQM?CRkJg5PFL62 zIxBJPo$l%Bs_w3?>-YV?|6dr)&h6KRAPAzYq9F)We#~6ckO=vVNO@-mHP^QkA$Rp4 z*CZQ?YjB+zvM^y$#wdOi7_hmrju*P;CLE8IDBowAJBwm|4x(J9&Q=QisFs$^DeIfC6jD)K*`z^RK&P$R1DNp-PStCKI6HY zObP}8Y-5nKgO_vemJpWkeM|u@_~vm5QKK;9_}&HRRqrPO=iz-DsXw*}ySTT9)G{Yg)fqM-jypeK+LYTkV_zzgg3_f8DkqT(ygRf zR#{4Ee@xZ^kBN$RRB}0Di@;k}R4uAClSz^mKq#c6^Q61T@KP8qTg;kZf}6B}kt>Y@ zXSZ~gcsq(%ID7Xo;3vKFKz_0RMY+A}$R7|6hpX>hgjmje^MIS!Qf=Kz<1&`L)JE?| z32pt9gXPJS-X9R12@=q#L?^(Mp9TrUT zE%tF(=@8ap5o_pcNXME(XgYJztgw~`HXr6=5t#bO~ek8=>Nr_20hvzO^(Vqb28 zJR>LOO4Yg?UB!+~}YokNp<5FnN$OR@#dY!VV@i;WoR&f$PNUK0F zfiPvZLf^82(eyAQiodP%IIruZEi;Tml!3!KGniIO#o>Oa3kJ8Gb5R?uP-KbBXp2j>aKoF;_KIm)xJNr7=C#&C5Wa?P=Sm`=U>2arSF z72F!QEfrk36{RPD_bZ${TBtDfZEwYyl~f*M)6Y=l6eSn1Z_fS-cq#_o%;3T`wppWj zAkA%YQR(xM->9((^uO%3C8;fr|%>Ns0Oyj7p7r$Az1$|GmotD8F4V`{5R$sG+Ia zo>|!WdWCEM*Kf_2O)dO!!~ydv;w&U4poZxZ4+i!!*G9lN>fH#KwhP1cfoSWQW~4CDVW@29gCIAGrYbFjLQpBteBEEg^<=wx`3Tea-qyT~}w?RFUC@ORt)-_PSH8B^7+5pi* z&?*enw;6hMUC8hpE6bZ=SxF|SvSE^_sxU$wW*b5cm`=d?v7$5Fz<{^bt~VBoX8CM$ zyIb0B1gEE=jP*L84+ASKElJX5MNl^47w29(s~N%wplU@^FUUm{29^7^AYw&skSI#- z4JvE~r6fgldYZ97aIU|JZFVNtzn^7!iqJvSHaTimKvUeA+`)BOT7rIa(V|!%M%VZV z;u-d$!x^-64Iu2(6AGf_(j{JS&@hmvHO_E9Jm=n{YXF?exBdqcf42n_#s1qkZjP(P z7PvKVh0dXceF;xz8|mBzG^k|ypUyFhO9(Lu{GIWT$9NCTV8Sgg+jJmPKvG$I>!cEb z{p6XG&z@9GG(pGgXm-l(J=)3F*F{OV!s>8-%)$E6?t^B9=thvnMFRIqRAzak4evd) zlN(b%z2te(c-_hq@vPeonC^}i=cPM~M!G^S1z;WB%Lq?VQbZ`3=}Vo5+je`~u&P;l z6}LR5g8wRum(;{3m%8ZEH>qir*7;CdqjqOiPkw?c%9&r(<2@*woy`(;Az z=-q{2(6da5<$c~G5$&~S@1gHe-6ZO+Y*7iShy&5Cn`GaVkP3?cMwx_(0F#p`;ea|Q zKYC`~9Mw-Bp&NCwhP!ABDq7}Yfs4PK5QkF38Q?rYuz3&e?=h=3DMGqF#*;}z0F?8s z*gyf?$^*3q+;h9pMYUA{;ug)Pnh28m0$O9C&1c}&0DwyS4u7dlmeK7l5Y+UZ41|}! z9GKV$6Wkt!Nt^$pSP_WSO$SIPWO3s8CR~hJJ(X;dqWB3X5mH(OWM{^=H5f-@`nH}x z8ee!%Co@<#NAqLuF~J6geicj_EV`f}>6R?Ayb9;1u`GjD>7Hoa9zI^oab`7iKF0pa zqX#lEkbk-2_~1NggR<}?6rimlSYYTyRIBh%zZO|0-=<|{ZIkX&mV{GA`EzDQYPGl> zy7m06wL+GvnbEW)mIm^MQXuUyPI>*v#G`clqY$g$d|=fdMzVC2_YjF2BfWZp`RIft z>ggMlTvO(0Sz7j&wD<>Rr2n(J94mU(!yg_#8SK)hjq$t7GC zeE_`Cq3nZubM>NG!J?;&=4978Cj*i)2kdcAoXbl1#_6`tyEnx(lel}zj*wk6iE9Cb zh>1c%q6#=&f(8=rq;hu^#QyVJ>Yk-~NO34asO?yR@wj`3P$HeIj(CLe_$9r2y1cqw zBD;w?2GZB(t9i#!|FYVVA_?Q}sIch+0wMB!1}V_-4DCLFg0xgRVAm7m|4NqG&fzk2 zGyU~`yHTT_y1(4Hh_O<&@`fmQ5HIO8rQwK~Nw;!X>9CJr)DtdMfVS|hI#ykHP%U#+ z*HO|RB9{2uN@IVLCHQE(!ET9-U$-kz==)1RDVTG*@sTbuAQXxIyCeW|TDK;!Tlki- zj3bpve?%Q-hq^y_&OXpRI0{LNrEyKxI!0X4x<@A;I24V5)}Z z`&g6!Tws!0rp$OTIbX!NVvTaqIPMpl_0?+^g>fUGXX$Ai>+>Z{g7F_&+7%r`5I`0_ ze{*(v8wg4|KS7OcO<+G$fB^AAp&b%_VR>21^uoN#ni5LPFwvoKnrHz!hYCwI@AalI zNxVLRFQI0Ex7|N(S(?u><;k0a@UTS09ufi(gLW$;Avf;t_}ua!gv~pT+}8C-G4G%o z!Md|Nu2am!BD9iWDVFUDcdnvBX)9LO0bOWZPle*swKxb__ALzrJ$$nO_}ZU^jIs~X zC!SHC4Yt2++bLnYA-!A?CKrGuSl4VaoL<~=k^@btQ95s#2)EcOU0*5PqveHgFPVz^ z(sFXLJcCz3f14v^{L-`6pFVhMcJ-;*^9L^+{KC`M&o)XGpV}~UgX~c@GEspDguNh` z&6t@h0qf|wgI7K;vy>=BuevFS=nW=$Ww;9=QJTQzFKZrzA|lMOnQF#^b8gcQpEu`r zYs4@ZTZ+jo51yvK-nwN04As&C`#J(Z)AK}0Giffo9EE#0b1EPM08%pN{t%~<%>=E?E^44>2)jz(IFYa2Yy% z%(Q(w?bxRND}A=aCJM9x!BAxIm>cJBz}?fyhi0E+?>V4Ax!{3jtE0|-1wB?8SKu_N zu$;oBdPOUFXe=SCxPm%Ls|kV%PC$%YFvL6aFozSHKf|q# zV!#@BKUK_{q9XnU%0l>a(zHzLv}|F*ZHrpAw zH;5qNyQ~>Wq*d0C`+^Haj5aD#=Wa6${AUEr&i$(*Ch`6Uck3N69}Z-JC6u7E5T)-RVG$XyL|+>Hy`?n1I+iuA%+MnqDN$BmhfWY{tDf!tk0+ah!#$ts$VDx|-F4 z)V79lYoY{RTMC035#O92AI&>f@T4fqW%GIv9(3DzAz&`Oq;0aKo>obQ=yg#e_USw) zx`a^^KFy(iX0TFNkwFy0gA5WhQ7UQB2`eL>2&md!jL6D0?N|#y75CR?dHe_OI!lQ4 zny)1GdP;l?5qzee5gbx&eFjI zK<|d=N`ldu3fE5-Z(Pdftog`UGYM~yIz&(l8K$bm+wpU>h4HvYou~$I2nM7oiC*NB zm_KsfOxAsOG+Acc$k}OmaFbj3|8Y87uKBRy|{|&#j+7D zjFpJ$?9i6?CfS8zOb(l3vEk(m5|+^d)0u*UsWgyN^8s`dyzzK`vbcr%(-riJuFCGV zMQHaF^)m*c9B*Mezdb7i%K(Xfl0pv&L>e2mXom8bsq&m0H_M|r@X6oK@!%L_jIK}!a zh&<1I#V`RJ%i9pFHQX_!dzHtObk3n6bVGbPp4Zc@rjLSe02Iu*{Na zua_`OvO<>$x;$QYT|%c{C(*PZy560Z*(%!UR?IL=dE1sVeWl} z^n}K`M+F}l)1~1k1E7$jDGSG~)JMLmslY8nx0_H02;y5Itg(ym1l+q;LSn%E#qvuS%$*mTBlrs>WVc)CXVvNE#~BEC z1lMI2(d2bR^aZ++RZP`(9lsJwKkHVl0Spf`{lV@Y)vNw2C~MW*dxtkCQClZT$)Z}; z)Zt*LD@wbVH9%#A0DDWkW)TrMWt%Wlt3gF>{AN*};#b2Lfd&zN1|pla)+_jaVsD^& z6zS$ERftH)8ZqlgBC433nmUHhB1utCWTd6fllg+{d=-SN_d+D|U-H5gHq`$QRssT? zEEC$%cy;HPM!65T92^o%=u(@eDjo@HS83lu^87m>6AE~ zVl-|JXYH~$Zf1uynV4_nUR97;RLx>N>l!twRf2W7TB)38#d2BPQ5l+jIY(}V{JYyO zj^`CS-KDyO5*2`{jbjpVOfnJYBSZCdajQJxW;Wl!sY^cU)XvppzF}2r%zpO(<_pDb zcCmb$T{2!1*T2bl_p-+YRIMZLzfY3Gck%DLbxsStW452#yMmm%{r3}m`9A)c^uMEb z%=Y2!liB~Cz3&0vx6}WHPH(o4?w!A%{waR{-}m1?HP`fhYZ|n4CJNx91 znxx&Z~1LI{ae4H(wptuKV))NnV51jS^m>r`iFk)$Ge}*cJiC% zOtsy={=ez;AJ9L%`mLYqPJH!SDxb-2^38iUhrh{=+>=TFwod=HPXCTMQE&I(-+LVY zVM(ul-%r1PzIlGL{U6dvlQ-$_>g(Ut*Ei?s>^JRabDYAL@;B+<(dpmO=^wgkFaHmd zSlXUR|F!I(yVTdRN4o73I=N||=DOy&zQkGE*B?Eu(vKcj=|>;yve|r?^k(~U67QtH zrqf?j>EGR?R68b}Is7RS%Q18R@9OmL>h$mJKK`csO!`Mi&;O(SdScT5j5$$n=(O4|NP7L^8bUL^k4jf%q&Kux4X}K zALhE|$d`N4Kl+wRfA{BiM}YnGU+qc%_y730?h>CLcz=@LUK8okJ^bG){kwmyetnFi z-(;d>%HNFta(AZfbqV#ydtZ5_+xxFS))OdweE Date: Fri, 27 May 2022 17:29:23 -0500 Subject: [PATCH 24/77] Fix grpc/json gateway service port alignment (#2065) --- .../helm/fog-services/templates/fog-report-deployment.yaml | 2 +- .../helm/fog-services/templates/fog-view-deployment.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml index f5c6c908db..07a3398301 100644 --- a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml @@ -126,7 +126,7 @@ spec: imagePullPolicy: Always command: - /usr/bin/go-grpc-gateway - - -grpc-server-endpoint=127.0.0.1:3228 + - -grpc-server-endpoint=127.0.0.1:3222 - -grpc-insecure - -http-server-listen=:8222 - -logtostderr diff --git a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml index 52d8f590f7..402d4f8d27 100644 --- a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml @@ -137,7 +137,7 @@ spec: imagePullPolicy: Always command: - /usr/bin/go-grpc-gateway - - -grpc-server-endpoint=127.0.0.1:3228 + - -grpc-server-endpoint=127.0.0.1:3225 - -grpc-insecure - -http-server-listen=:8225 - -logtostderr From dafa1f6ec02cebf495e5ca8e897de869d2c7df25 Mon Sep 17 00:00:00 2001 From: Bernie Dolan Date: Sun, 29 May 2022 04:37:05 -0400 Subject: [PATCH 25/77] Parameterize TransactionBuilder for Token ID (#2064) * Parameterize TransactionBuilder for Token ID * Lint * from try_from to from --- android-bindings/src/bindings.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index b393a50224..d8bcc00118 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -46,9 +46,8 @@ use mc_transaction_core::{ create_shared_secret, recover_onetime_private_key, recover_public_subaddress_spend_key, }, ring_signature::KeyImage, - tokens::Mob, tx::{Tx, TxOut, TxOutConfirmationNumber, TxOutMembershipProof}, - Amount, BlockVersion, CompressedCommitment, MaskedAmount, Token, + Amount, BlockVersion, CompressedCommitment, MaskedAmount, TokenId, }; use mc_transaction_std::{ @@ -315,16 +314,16 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_init_1jni( obj: JObject, commitment: jbyteArray, masked_value: jlong, + masked_token_id: jbyteArray, ) { jni_ffi_call(&env, |env| { let commitment_bytes = env.convert_byte_array(commitment)?; + let masked_token_id_bytes = env.convert_byte_array(masked_token_id)?; - // FIXME #1595: We should get a masked token id also, here we default to - // 0 bytes, which is backwards compatible let masked_amount = MaskedAmount { commitment: CompressedCommitment::try_from(&commitment_bytes[..])?, masked_value: masked_value as u64, - masked_token_id: Default::default(), + masked_token_id: masked_token_id_bytes, }; Ok(env.set_rust_field(obj, RUST_OBJ_FIELD, masked_amount)?) }) @@ -336,14 +335,17 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_init_1jni_1with_1s obj: JObject, tx_out_shared_secret: JObject, masked_value: jlong, + masked_token_id: jbyteArray, ) { jni_ffi_call(&env, |env| { let tx_out_shared_secret: MutexGuard = env.get_rust_field(tx_out_shared_secret, RUST_OBJ_FIELD)?; - // FIXME #1595: the masked token id should be 0 or 4 bytes. - // To avoid breaking changes, it is hard coded to 0 bytes here - let masked_amount = - MaskedAmount::reconstruct(masked_value as u64, &[], &tx_out_shared_secret)?; + let masked_token_id_bytes = env.convert_byte_array(masked_token_id)?; + let masked_amount = MaskedAmount::reconstruct( + masked_value as u64, + &masked_token_id_bytes, + &tx_out_shared_secret, + )?; Ok(env.set_rust_field(obj, RUST_OBJ_FIELD, masked_amount)?) }) @@ -1666,19 +1668,17 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_init_1jni( fog_resolver: JObject, memo_builder_box: JObject, block_version: jint, + token_id: jlong, + minimum_fee: jlong, ) { jni_ffi_call(&env, |env| { let fog_resolver: MutexGuard = env.get_rust_field(fog_resolver, RUST_OBJ_FIELD)?; let block_version = BlockVersion::try_from(block_version as u32).unwrap(); - // Note: RTHMemoBuilder can be selected here, but we will only actually - // write memos if block_version is large enough that memos are supported. - // If block version is < 2, then transaction builder will filter out memos. let memo_builder_box: Box = env.take_rust_field(memo_builder_box, RUST_OBJ_FIELD)?; - // FIXME #1595: The token id should be a parameter and not hard coded to Mob - // here - let fee_amount = Amount::new(Mob::MINIMUM_FEE, Mob::ID); + let token_id = TokenId::from(token_id as u64); + let fee_amount = Amount::new(minimum_fee as u64, token_id); let tx_builder = TransactionBuilder::new_with_box( block_version, fee_amount, From 9c7b4491af054b30c9e6bd8c6a3bcb70ee4f2df3 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 31 May 2022 12:57:33 -0600 Subject: [PATCH 26/77] adjust MAX_TOMBSTONE_BLOCKS constant (#2073) --- transaction/core/src/constants.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/transaction/core/src/constants.rs b/transaction/core/src/constants.rs index f1432aee61..89c676f941 100644 --- a/transaction/core/src/constants.rs +++ b/transaction/core/src/constants.rs @@ -18,7 +18,21 @@ pub const MAX_OUTPUTS: u64 = 16; /// Maximum number of blocks in the future a transaction's tombstone block can /// be set to. -pub const MAX_TOMBSTONE_BLOCKS: u64 = 100; +/// +/// This is the limit enforced in the enclave as part of transaction +/// validation rules. However, untrusted may decide to evict pending +/// transactions from the queue before this point, so this is only a maximum on +/// how long a Tx can actually be pending. +/// +/// Note that clients are still in charge of setting the actual tombstone value. +/// For normal transactions, clients at time of writing are defaulting to +/// something like current block height + 100, so that they can know quickly if +/// a Tx succeeded or failed. +/// +/// Rationale for this number is, at a rate of 2 blocks / minute, this is 7 +/// days, which eases operations for minting agents which must perform a +/// multi-sig. +pub const MAX_TOMBSTONE_BLOCKS: u64 = 20160; /// The MobileCoin network will contain a fixed supply of 250 million /// mobilecoins (MOB). From 31f140f865ceb52e48ed956c5ef335e319b641b2 Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 31 May 2022 19:22:23 -0700 Subject: [PATCH 27/77] Final version and Changelog 1.2.0 (#2077) * Bump all crate versions to 1.2.0 * Update CHANGELOG.md for release. --- CHANGELOG.md | 3 +- Cargo.lock | 322 ++++++++++---------- account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- common/Cargo.toml | 2 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 +++--- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 +++---- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 +++--- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 +++---- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 2 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 2 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 177 files changed, 532 insertions(+), 531 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d599bbf11a..042679b143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem -## [1.2.0-pre1] - 2022-05-20 +## [1.2.0] - 2022-06-03 ### Added @@ -33,6 +33,7 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem - Enable `Bitcode` for `libmobilecoin`, reduce mobile artifact size by ~25% ([#1124]) - mobilecoind will now exit on startup when a ledger migration is necessary, unless the new `--ledger-db-migrate` command line argument is used, in which case it will migrate automatically. This flag does not do anything if the Ledger DB does not exist. - Bump SGX versions to 2.16. ([#1101], [#2018]) +- Increase the maximum tombstone block for transactions to `20,160` from `100`. #### Python diff --git a/Cargo.lock b/Cargo.lock index 45f3bf5200..084c3737d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2015,7 +2015,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "cbindgen", @@ -2197,7 +2197,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "criterion", "curve25519-dalek", @@ -2225,7 +2225,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2241,7 +2241,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -2256,7 +2256,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "anyhow", @@ -2293,7 +2293,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "bs58", "cargo-emit", @@ -2329,7 +2329,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "aes-gcm", @@ -2354,7 +2354,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "cargo-emit", @@ -2372,7 +2372,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "bincode", @@ -2404,7 +2404,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2417,7 +2417,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2437,7 +2437,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -2448,7 +2448,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2458,7 +2458,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2483,7 +2483,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "backtrace", "binascii", @@ -2520,7 +2520,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "cookie", @@ -2549,7 +2549,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2560,7 +2560,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "futures", @@ -2581,7 +2581,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2606,7 +2606,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "hex", @@ -2627,7 +2627,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2635,7 +2635,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "hex", @@ -2671,7 +2671,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2684,7 +2684,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2706,7 +2706,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2735,7 +2735,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "crossbeam-channel", "maplit", @@ -2758,7 +2758,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "mc-common", @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "chrono", @@ -2832,7 +2832,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "clap 3.1.18", @@ -2857,7 +2857,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2877,7 +2877,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "digest 0.10.3", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2906,7 +2906,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "proc-macro2", "quote", @@ -2915,7 +2915,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2923,7 +2923,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2932,7 +2932,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2940,7 +2940,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "blake2", "digest 0.10.3", @@ -2949,7 +2949,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "curve25519-dalek", @@ -2982,7 +2982,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "displaydoc", @@ -2996,7 +2996,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3010,7 +3010,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "aes-gcm", @@ -3031,7 +3031,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3042,7 +3042,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3055,7 +3055,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3067,7 +3067,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3078,7 +3078,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3089,7 +3089,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "displaydoc", @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3153,7 +3153,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "cookie", @@ -3177,7 +3177,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3216,7 +3216,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "criterion", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3268,7 +3268,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3276,7 +3276,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3309,7 +3309,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3322,7 +3322,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "dirs", @@ -3379,7 +3379,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3395,7 +3395,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "grpcio", @@ -3416,7 +3416,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3445,7 +3445,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3463,7 +3463,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3471,7 +3471,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3507,7 +3507,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3560,7 +3560,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3576,7 +3576,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -3605,14 +3605,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3623,7 +3623,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "aligned-cmov", @@ -3640,7 +3640,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "lazy_static", "mc-common", @@ -3648,7 +3648,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3700,7 +3700,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "futures", @@ -3719,7 +3719,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-util-serial", "prost", @@ -3728,7 +3728,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "binascii", @@ -3750,7 +3750,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "grpcio", @@ -3767,7 +3767,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3803,7 +3803,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3813,7 +3813,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3831,7 +3831,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3839,7 +3839,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3885,7 +3885,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3906,7 +3906,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3917,7 +3917,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3932,7 +3932,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "chrono", "clap 3.1.18", @@ -3965,7 +3965,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3996,7 +3996,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4027,7 +4027,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "crc", "displaydoc", @@ -4047,7 +4047,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-common", "mc-util-uri", @@ -4055,7 +4055,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "grpcio", "mc-attest-core", @@ -4075,7 +4075,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "criterion", @@ -4110,7 +4110,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4128,7 +4128,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4136,7 +4136,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4158,7 +4158,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4171,7 +4171,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4190,7 +4190,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -4213,7 +4213,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4263,7 +4263,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "lazy_static", @@ -4289,7 +4289,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "dirs", @@ -4311,7 +4311,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "mc-api", @@ -4322,7 +4322,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4335,7 +4335,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4366,7 +4366,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4399,7 +4399,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "futures", @@ -4413,7 +4413,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4477,7 +4477,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "futures", @@ -4495,7 +4495,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4602,7 +4602,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "grpcio", "hex", @@ -4625,7 +4625,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cc", "lazy_static", @@ -4635,7 +4635,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4643,7 +4643,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4652,7 +4652,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4660,7 +4660,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4669,21 +4669,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4694,7 +4694,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4710,7 +4710,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4720,18 +4720,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-urts" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-common", "mc-sgx-build", @@ -4742,7 +4742,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "hex", "mc-account-keys", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-account-keys", "mc-api", @@ -4764,7 +4764,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-util-test-vector", "serde", @@ -4773,7 +4773,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "hex", "mc-account-keys", @@ -4788,7 +4788,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "hex", "mc-account-keys", @@ -4810,7 +4810,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "bulletproofs-og", @@ -4852,7 +4852,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4869,7 +4869,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4896,7 +4896,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "hex", @@ -4905,7 +4905,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4921,7 +4921,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4929,7 +4929,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "json", @@ -4937,7 +4937,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "displaydoc", @@ -4948,7 +4948,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cc", @@ -4967,7 +4967,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "binascii", @@ -4979,18 +4979,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-util-from-random" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "hex", @@ -5009,7 +5009,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "clap 3.1.18", @@ -5043,7 +5043,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -5054,7 +5054,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "hex", @@ -5065,11 +5065,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-util-keyfile" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "clap 3.1.18", @@ -5097,7 +5097,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5107,7 +5107,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "proc-macro2", "quote", @@ -5116,7 +5116,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5124,7 +5124,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "chrono", "grpcio", @@ -5137,7 +5137,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "itertools", "mc-sgx-css", @@ -5145,7 +5145,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "generic-array", "prost", @@ -5155,7 +5155,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "hex", @@ -5168,7 +5168,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "prost", "serde", @@ -5177,7 +5177,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5188,7 +5188,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "itertools", @@ -5202,7 +5202,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "serde", "serde_json", @@ -5210,7 +5210,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "proc-macro2", "quote", @@ -5219,7 +5219,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "displaydoc", @@ -5237,7 +5237,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5281,7 +5281,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 6b17d80fa5..008294f9b5 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index 2e81156d9b..fb4839ee85 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index ae0da88d90..235d001130 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index 369db4c619..a26a8698fb 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/api/Cargo.toml b/api/Cargo.toml index 5efbf4495b..b4ab354fab 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index 1a5527fb9d..381a31c76a 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index 6ad6ca0b84..b56f9e8545 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index c5b62e2dc5..8e595a677f 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index f2706b741d..0c086dcb19 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index ac4b73ffe6..d3e48e9f34 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index 789be9a4fd..cce1f387ce 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index 25a058bc44..f753af5822 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index a9e203304b..d800173b2c 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/common/Cargo.toml b/common/Cargo.toml index 6ad81280d6..f7f9f9e80a 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/Cargo.toml b/connection/Cargo.toml index 8cc80b51f8..22cf59dcbe 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index 66ccdce1c2..ba43c1f931 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index 6831034085..8ebe307b2a 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index ba3d6f7cfd..73cc507003 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index 60a7c0255b..7867f69a89 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index b867c8d087..d7ccf529b5 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index 0d8e64b84c..36855e5cb4 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index 3169d18ff0..299fb0a938 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index c99346f035..47f04b1101 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index ea7297f860..e9504beeca 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-build" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-transaction-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index 51fc6dd709..a7c4e1259f 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index 9f2c8cd353..b2650cfd69 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index b7db57613b..f3363132d9 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index 4de4a8d410..3b7bc6a047 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index 66b049087b..aa66e1d854 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index 1bb070b430..406b8c754c 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index 6a5e661a47..f12dbd946b 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index f0b996a1be..2e6b45c948 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index ddb7b90f88..9b3987a16f 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index cd0f0114c0..2270ce10c4 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index 1162e6fa9d..98303fb7e7 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index ae1160422a..8eab9561c2 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index d1fc4edba5..6f86c2eb5f 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index 0393a85668..c41709546a 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index de5c5dd2ad..e686ad0272 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index 1ae75f3849..7d91109bce 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index 6ef9716e94..c99e5e8370 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index ef0ff91d6b..fd11243dcb 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index d880306e00..370467ac03 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index 552aee3640..803453fb08 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 12803ebd8f..10582403f0 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index 0627ed6719..0d77525147 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index 066d15b0a5..5901582f50 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index 36c6d16195..ed1962df8d 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index ecd69cd1d5..fa7062a437 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index fff2a4f5b3..39a9664f08 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 5864eb2ffa..741763d7bb 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index 50ed3a73f7..3a75519405 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index 6d507972a7..9fa099bd31 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index 6a54ba4b49..66fabc2c04 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index e9763914fd..e60a6efef8 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index c413600eb4..208d8d74e5 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 3124c993bb..792459de21 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-build" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-transaction-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index 7d5838d229..00b6ca6f5b 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index 9223f3be63..bd777ca712 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index 0b61e2d0d7..e728db1507 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index 4967a3eb95..fd8ee674c5 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index 25bd207f9a..41610f4b41 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index 5c8912864f..8ba33872b1 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index fefc595207..730ab185c9 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index 4c4ddff0d2..e555a3fae9 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index 963528ecfb..312c2b010c 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 5977ac1993..68bf082776 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-build" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-transaction-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index 5c044ec328..c11a4ab663 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index 9d644af734..54b82932fc 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index 61fd4253cd..3babe8bc12 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index f64f65db3f..45e8184129 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index 2e182f0e4d..436f3dbb22 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index 05ed53eddd..79186be6b7 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index 37aa010bf0..55c7f5be6c 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index 29958f8567..23e1ca041d 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 4ffe187ca8..731455aa14 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index 532b579957..7bde3126e5 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index 3ae9281c63..41789af393 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index 25959ec5cd..d8107efd02 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index 40fa6ae31d..11000148f2 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index a081c409b6..5ab0585465 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index 8c94172a09..0f341cc5c0 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index a7112b36ce..a41be0a1d2 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index 83e617941e..eb252a9a50 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index 744450d11d..09bb367770 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index ce39cefca2..4cc4aacca4 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index ab981a8882..b69a512694 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index 5cb4b63872..dc03ad8222 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index 959cddbe33..49295ac0e6 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index 9e13621aa2..d190d3d883 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 8360826050..402c88cc6e 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index b420ff26da..60b3156044 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index ea0330c703..ad38eff738 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index a991a9baf5..dc6fafcf2c 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index b2a2bcdfd6..628d9784d8 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index b3fcc076dd..2b3aefa7c8 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index 2d3569cfd6..90abbe6e14 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index d64a7c8e6b..fc544653f2 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index 78b25ea74e..79af6992f5 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index aaed4f8425..128c5e158f 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index e93d4348ae..fa2f3cbe7c 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-build" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0-pre1" +version = "1.2.0" [[package]] name = "mc-transaction-core" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0-pre1" +version = "1.2.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index 080b59cd9b..f27184668b 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index e251080711..277b21675c 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index 24847d557d..9a8cc8c62e 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index 5c0c0a4ab2..ca628bc200 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index c4271c68c4..456f6825ac 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index b267b7c510..94b3c416fb 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index 98238886e2..4461e8e548 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index 9ca5c95a60..6f05030830 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index f8835b5050..07303d433e 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index f07527f2e6..49525d51ea 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index ab439b2287..f26cb37bac 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index d0725de812..d309970f01 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index 3af943cbb9..4de11075c2 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index f01b3c0062..20f5e4083a 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index 224e1e6124..fb5ceb1a7a 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/peers/Cargo.toml b/peers/Cargo.toml index c6dbba1b6b..bd1d4d10c8 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index 7aba7ee781..082ca6b0e5 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index 3c43712528..ff0e1c47c6 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index 2f966affd6..66363dfe68 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index 53b5a4ded8..aba4938403 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index 8bba101275..682750164b 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index e5d1de8957..7e57d4e893 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index 40645a898f..909ecc3da7 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index 0aa49038aa..cd18e4c3af 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index 15c54c3153..219f22d1f3 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index 691fd511e3..b9f2673090 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index ce49f7142a..59b9646386 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index 614462c427..1c177378fc 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index 8b7a54f863..88a0628db2 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index 12ad04acad..a5680217e5 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index a7f61994ac..4578e2c418 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index 13a931cacc..92c81abf4c 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index 866eeb1647..f3ca4f5495 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index 11309b7158..b2c0d3a091 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index f6a9e2c45f..269b6e9423 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "1.2.0-pre1" +version = "1.2.0" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index 0a45b92541..e1a5120bff 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index 9eab65ba6a..36103bd463 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index 02ec18f05f..d5a3b2170a 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index e90df4645c..43ff4cb607 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index f58b5cbd21..ae37b1cb4f 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index 94535bec43..28f5caad38 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index ebd25143c7..d88f69cb0b 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 741cbb43f7..71e076461e 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index 6681465222..feca639764 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index 48dfa4ea6f..5485b2bb45 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index f8b37cc3f9..99598c3665 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index 72c74a0f81..b3eb35f15c 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index d129f216a1..0c5591da31 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index d50d008f65..1170f0ab4a 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index 5a465d0689..c6015de094 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index 6fefbf71b8..b87f7b5390 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index 3325000cc6..e9c0285375 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index 7826092a9a..31260b0a4d 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index 9aa93e34bb..f5b5f0005d 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index f6c3754d3e..0829a68e7f 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index c4f54a8bb8..535e5dd274 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index c44beb8d99..0127ddbc18 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 283f2adb9b..34770708cd 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index 58b5706d2f..07d220912b 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index ed4d62b91d..777ce63932 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index 4a5f861b10..64cd928bbf 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index f8e21dc766..514cf00166 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index 72f832b797..eb3ea6d4cc 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index e276275322..c710bf4c66 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index 6b8a6edbcf..f1e4c73537 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index ea7b393724..3f78b94f59 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index 675b05955a..500ec02fec 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index dd26c4c312..2891af0573 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index a94275327a..c8759fef20 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index cd90849450..b1d10c57e7 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index 6cd3d5d10b..fe10b2aacd 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index b904e3e9e7..b673a0e4b2 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index 61ce29aa4d..bb17e244dc 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index c4ce4aa2a5..0033588826 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "1.2.0-pre1" +version = "1.2.0" authors = ["MobileCoin"] edition = "2018" From 3e5a458bce1fdb1ceaf2befd2840378a0a489b53 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Fri, 3 Jun 2022 15:46:17 -0500 Subject: [PATCH 28/77] build 1.2.0 without an upgrade (#2086) * build 1.2.0 without an upgrade --- .internal-ci/docker/Dockerfile.node_hw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.internal-ci/docker/Dockerfile.node_hw b/.internal-ci/docker/Dockerfile.node_hw index 6b1e0f1892..2079e82dce 100644 --- a/.internal-ci/docker/Dockerfile.node_hw +++ b/.internal-ci/docker/Dockerfile.node_hw @@ -19,8 +19,9 @@ COPY ${RUST_BIN_PATH}/mc-util-grpc-admin-tool /usr/bin/ COPY ${RUST_BIN_PATH}/sample-keys /usr/local/bin/ COPY ${RUST_BIN_PATH}/generate-sample-ledger /usr/local/bin/ +COPY ${RUST_BIN_PATH}/read-pubfile /usr/local/bin/ COPY .internal-ci/util/generate_origin_data.sh /usr/local/bin/ - +COPY .internal-ci/util/sample-keys.1.1.3 /util/ # Populate origin data # We should pull origin data at runtime from an external source, like a public s3 url, but keep this for legacy. ARG ORIGIN_DATA_DIR=.internal-ci/sample_data From 86e062731098ca579beaa9d9bbaae471441e4d22 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Mon, 6 Jun 2022 13:30:04 -0600 Subject: [PATCH 29/77] fix block-version 0 behavior in consensus enclave (#2088) this is required because the mint_output function rejects any new token id if new token ids are not allowed yet, but the fee aggregation code would sometimes, under load, try to mint a fee output of alternate token ids, because of privacy considerations in MCIP #25 --- consensus/enclave/impl/src/lib.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/consensus/enclave/impl/src/lib.rs b/consensus/enclave/impl/src/lib.rs index 6cf121701a..477b87a56b 100644 --- a/consensus/enclave/impl/src/lib.rs +++ b/consensus/enclave/impl/src/lib.rs @@ -826,9 +826,18 @@ impl ConsensusEnclave for SgxConsensusEnclave { // // Note: The "take" here only makes sense because sort_zeros_to_end was called. // This ensures that everything we are ignoring via take has zero value. + let num_fee_outputs = if config.block_version.masked_token_id_feature_is_supported() { + min(total_fees.len(), transactions.len()) + } else { + // Before token ids are supported, 0 is the only valid token id. + // We must not attempt to create any other fee outputs or mint_output + // will return an error. + 1 + }; + let fee_outputs = total_fees .iter() - .take(min(total_fees.len(), transactions.len())) + .take(num_fee_outputs) .flat_map(|(token_id, total_fee)| { // While unlikely, it is technically possible for the accumulated // fee value to overflow a u64, particularly for custom tokens. From c27b390b535b96bf1c1b941d8da9502e758dec67 Mon Sep 17 00:00:00 2001 From: Adam Mork Date: Mon, 6 Jun 2022 14:51:12 -0700 Subject: [PATCH 30/77] Add get shared_secret & root_entropy FFIs to LibMobileCoin (#2076) * add get_shared_secret * Add back in the function to create view/spend keys with root_entropy * fix header file declaration * fix lint --- libmobilecoin/include/keys.h | 12 ++++++++++ libmobilecoin/include/transaction.h | 19 +++++++++++++++- libmobilecoin/libmobilecoin_cbindgen.h | 22 ++++++++++++++++++ libmobilecoin/src/keys.rs | 31 +++++++++++++++++++++++++- libmobilecoin/src/transaction.rs | 28 +++++++++++++++++++++++ 5 files changed, 110 insertions(+), 2 deletions(-) diff --git a/libmobilecoin/include/keys.h b/libmobilecoin/include/keys.h index cea0133293..6950e31db1 100644 --- a/libmobilecoin/include/keys.h +++ b/libmobilecoin/include/keys.h @@ -54,6 +54,18 @@ bool mc_account_key_get_subaddress_private_keys( ) MC_ATTRIBUTE_NONNULL(1, 2, 4, 5); +/// # Preconditions +/// +/// * `root_entropy` - must be 32 bytes in length. +/// * `out_view_private_key` - length must be >= 32. +/// * `out_spend_private_key` - length must be >= 32. +bool mc_account_private_keys_from_root_entropy( + const McBuffer* MC_NONNULL root_entropy, + McMutableBuffer* MC_NONNULL out_view_private_key, + McMutableBuffer* MC_NONNULL out_spend_private_key +) +MC_ATTRIBUTE_NONNULL(1, 2, 3); + /// # Preconditions /// /// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. diff --git a/libmobilecoin/include/transaction.h b/libmobilecoin/include/transaction.h index a75c2e8960..47fe4e8ffa 100644 --- a/libmobilecoin/include/transaction.h +++ b/libmobilecoin/include/transaction.h @@ -31,6 +31,23 @@ typedef struct _McTxOutMemoBuilder McTxOutMemoBuilder; /* ==== TxOut ==== */ +/// # Preconditions +/// +/// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. +/// * `tx_out_public_key` - must be a valid 32-byte Ristretto-format scalar. +/// +/// # Errors +/// +/// * `LibMcError::InvalidInput` +/// * `LibMcError::TransactionCrypto` +bool mc_tx_out_get_shared_secret( + const McBuffer* MC_NONNULL view_private_key, + const McBuffer* MC_NONNULL tx_out_public_key, + McMutableBuffer* MC_NONNULL out_shared_secret, + McError* MC_NULLABLE * MC_NULLABLE out_error +) +MC_ATTRIBUTE_NONNULL(1, 2, 3); + /// # Preconditions /// /// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. @@ -169,7 +186,7 @@ McTransactionBuilder* MC_NULLABLE mc_transaction_builder_create( const McFogResolver* MC_NULLABLE fog_resolver, McTxOutMemoBuilder* MC_NONNULL memo_builder, uint32_t block_version -); +) MC_ATTRIBUTE_NONNULL(5); void mc_transaction_builder_free( diff --git a/libmobilecoin/libmobilecoin_cbindgen.h b/libmobilecoin/libmobilecoin_cbindgen.h index d2fa919643..07e885b8fa 100644 --- a/libmobilecoin/libmobilecoin_cbindgen.h +++ b/libmobilecoin/libmobilecoin_cbindgen.h @@ -554,6 +554,17 @@ bool mc_fog_rng_peek(FfiRefPtr fog_rng, FfiMutPtr out */ bool mc_fog_rng_advance(FfiMutPtr fog_rng, FfiOptMutPtr out_output); +/** + * # Preconditions + * + * * `root_entropy` - must be 32 bytes in length. + * * `out_view_private_key` - length must be >= 32. + * * `out_spend_private_key` - length must be >= 32. + */ +bool mc_account_private_keys_from_root_entropy(FfiRefPtr root_entropy, + FfiMutPtr out_view_private_key, + FfiMutPtr out_spend_private_key); + /** * # Preconditions * @@ -623,6 +634,17 @@ bool mc_slip10_account_private_keys_from_mnemonic(FfiStr mnemonic, FfiMutPtr out_spend_private_key, FfiOptMutPtr> out_error); +/** + * # Preconditions + * + * * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. + * * `tx_out_public_key` - must be a valid 32-byte Ristretto-format scalar. + */ +bool mc_tx_out_get_shared_secret(FfiRefPtr view_private_key, + FfiRefPtr tx_out_public_key, + FfiMutPtr out_shared_secret, + FfiOptMutPtr> out_error); + /** * # Preconditions * diff --git a/libmobilecoin/src/keys.rs b/libmobilecoin/src/keys.rs index 964467b2c0..85fe4a9cb4 100644 --- a/libmobilecoin/src/keys.rs +++ b/libmobilecoin/src/keys.rs @@ -1,7 +1,7 @@ // Copyright (c) 2018-2022 The MobileCoin Foundation use crate::{common::*, LibMcError}; -use mc_account_keys::{AccountKey, PublicAddress, ShortAddressHash}; +use mc_account_keys::{AccountKey, PublicAddress, RootIdentity, ShortAddressHash}; use mc_crypto_keys::{ReprBytes, RistrettoPrivate, RistrettoPublic}; use mc_util_ffi::*; @@ -44,6 +44,35 @@ impl<'a> TryFromFfi<&McAccountKey<'a>> for AccountKey { } } +/// # Preconditions +/// +/// * `root_entropy` - must be 32 bytes in length. +/// * `out_view_private_key` - length must be >= 32. +/// * `out_spend_private_key` - length must be >= 32. +#[no_mangle] +pub extern "C" fn mc_account_private_keys_from_root_entropy( + root_entropy: FfiRefPtr, + out_view_private_key: FfiMutPtr, + out_spend_private_key: FfiMutPtr, +) -> bool { + ffi_boundary(|| { + let root_entropy = <&[u8; 32]>::try_from_ffi(&root_entropy) + .expect("root_entropy must be 32 bytes in length"); + let out_view_private_key = out_view_private_key + .into_mut() + .as_slice_mut_of_len(RistrettoPrivate::size()) + .expect("out_view_private_key length is insufficient"); + let out_spend_private_key = out_spend_private_key + .into_mut() + .as_slice_mut_of_len(RistrettoPrivate::size()) + .expect("out_spend_private_key length is insufficient"); + + let account_key = AccountKey::from(&RootIdentity::from(root_entropy)); + out_view_private_key.copy_from_slice(account_key.view_private_key().as_ref()); + out_spend_private_key.copy_from_slice(account_key.spend_private_key().as_ref()); + }) +} + /// # Preconditions /// /// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. diff --git a/libmobilecoin/src/transaction.rs b/libmobilecoin/src/transaction.rs index ac386b6114..e0f2e54386 100644 --- a/libmobilecoin/src/transaction.rs +++ b/libmobilecoin/src/transaction.rs @@ -61,6 +61,34 @@ impl From for McTxOutAmount { pub type McTxOutMemoBuilder = Option>; impl_into_ffi!(Option>); +/// # Preconditions +/// +/// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. +/// * `tx_out_public_key` - must be a valid 32-byte Ristretto-format scalar. +#[no_mangle] +pub extern "C" fn mc_tx_out_get_shared_secret( + view_private_key: FfiRefPtr, + tx_out_public_key: FfiRefPtr, + out_shared_secret: FfiMutPtr, + out_error: FfiOptMutPtr>, +) -> bool { + ffi_boundary_with_error(out_error, || { + let view_private_key = RistrettoPrivate::try_from_ffi(&view_private_key)?; + + let tx_out_public_key = RistrettoPublic::try_from_ffi(&tx_out_public_key)?; + + let shared_secret = get_tx_out_shared_secret(&view_private_key, &tx_out_public_key); + + let out_shared_secret = out_shared_secret + .into_mut() + .as_slice_mut_of_len(RistrettoPrivate::size()) + .expect("out_shared_secret length is insufficient"); + + out_shared_secret.copy_from_slice(&shared_secret.to_bytes()); + Ok(()) + }) +} + /// # Preconditions /// /// * `view_private_key` - must be a valid 32-byte Ristretto-format scalar. From 6048ef5b899f337ec2ab6f22a70e220780386ce0 Mon Sep 17 00:00:00 2001 From: Bernie Dolan Date: Mon, 6 Jun 2022 16:09:57 -0700 Subject: [PATCH 31/77] Use new TokenId class to create Amount (#2092) --- android-bindings/src/bindings.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index d8bcc00118..fc38e6d115 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -406,15 +406,20 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_MaskedAmount_unmask_1amount( .into(), ], )?; - let token_id = env.new_object( + let token_id_ul = env.new_object( "com/mobilecoin/lib/UnsignedLong", "(J)V", &[jni::objects::JValue::Long(*amount.token_id as i64)], )?; + let token_id = env.new_object( + "com/mobilecoin/lib/TokenId", + "(Lcom/mobilecoin/lib/UnsignedLong;)V", + &[jni::objects::JValue::Object(token_id_ul)], + )?; Ok(env .new_object( "com/mobilecoin/lib/Amount", - "(Ljava/math/BigInteger;Lcom/mobilecoin/lib/UnsignedLong;)V", + "(Ljava/math/BigInteger;Lcom/mobilecoin/lib/TokenId;)V", &[ jni::objects::JValue::Object(value), jni::objects::JValue::Object(token_id), From 196ca2eb14a3c4f377e8e471f80070dafde40f4a Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 6 Jun 2022 20:19:34 -0700 Subject: [PATCH 32/77] Bump all versions to 1.2.1, update changelog (#2095) * Bump all versions to 1.2.1, update changelog * Also bump version in maven. --- CHANGELOG.md | 12 + Cargo.lock | 322 +++++++++--------- account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- .../android-bindings/publish.gradle | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- common/Cargo.toml | 2 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 ++--- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 +++--- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 +++--- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 +++--- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 2 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 2 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 178 files changed, 543 insertions(+), 531 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 042679b143..49bd5f9d5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The crates in this repository do not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) at this time. +## [1.2.1] - 2022-06-06 + +### Changed + +- Expose the ability to get a TX shared secret to iOS SDK +- Restore the ability to derive an account from legacy root entropy to iOS SDK +- Improve the construction of `Amount` objects from Android SDK + +### Fixed + +- Fix panic when consensus service is configured for multiple tokens but still running in MOB-only block-version 0 mode. + ## [1.2.0] - 2022-06-03 diff --git a/Cargo.lock b/Cargo.lock index 084c3737d6..53280615c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2015,7 +2015,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "cbindgen", @@ -2197,7 +2197,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "criterion", "curve25519-dalek", @@ -2225,7 +2225,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "1.2.0" +version = "1.2.1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2241,7 +2241,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "grpcio", @@ -2256,7 +2256,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "anyhow", @@ -2293,7 +2293,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "bs58", "cargo-emit", @@ -2329,7 +2329,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "aes-gcm", @@ -2354,7 +2354,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "cargo-emit", @@ -2372,7 +2372,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "bincode", @@ -2404,7 +2404,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2417,7 +2417,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2437,7 +2437,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -2448,7 +2448,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2458,7 +2458,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2483,7 +2483,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0" +version = "1.2.1" dependencies = [ "backtrace", "binascii", @@ -2520,7 +2520,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "cookie", @@ -2549,7 +2549,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2560,7 +2560,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "futures", @@ -2581,7 +2581,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2606,7 +2606,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "hex", @@ -2627,7 +2627,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2635,7 +2635,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "hex", @@ -2671,7 +2671,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2684,7 +2684,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2706,7 +2706,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2735,7 +2735,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "1.2.0" +version = "1.2.1" dependencies = [ "crossbeam-channel", "maplit", @@ -2758,7 +2758,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "mc-common", @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "chrono", @@ -2832,7 +2832,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "clap 3.1.18", @@ -2857,7 +2857,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2877,7 +2877,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "digest 0.10.3", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2906,7 +2906,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0" +version = "1.2.1" dependencies = [ "proc-macro2", "quote", @@ -2915,7 +2915,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2923,7 +2923,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2932,7 +2932,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2940,7 +2940,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "blake2", "digest 0.10.3", @@ -2949,7 +2949,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "curve25519-dalek", @@ -2982,7 +2982,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "displaydoc", @@ -2996,7 +2996,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3010,7 +3010,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "aes-gcm", @@ -3031,7 +3031,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3042,7 +3042,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3055,7 +3055,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3067,7 +3067,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3078,7 +3078,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3089,7 +3089,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "displaydoc", @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3153,7 +3153,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "cookie", @@ -3177,7 +3177,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "1.2.0" +version = "1.2.1" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3216,7 +3216,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "criterion", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -3268,7 +3268,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3276,7 +3276,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3309,7 +3309,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3322,7 +3322,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "dirs", @@ -3379,7 +3379,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0" +version = "1.2.1" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3395,7 +3395,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "grpcio", @@ -3416,7 +3416,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3445,7 +3445,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -3463,7 +3463,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3471,7 +3471,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3507,7 +3507,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3560,7 +3560,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3576,7 +3576,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "grpcio", @@ -3605,14 +3605,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3623,7 +3623,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "aligned-cmov", @@ -3640,7 +3640,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "lazy_static", "mc-common", @@ -3648,7 +3648,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -3700,7 +3700,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "futures", @@ -3719,7 +3719,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-util-serial", "prost", @@ -3728,7 +3728,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "binascii", @@ -3750,7 +3750,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "grpcio", @@ -3767,7 +3767,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3803,7 +3803,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3813,7 +3813,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-account-keys", @@ -3831,7 +3831,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3839,7 +3839,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3885,7 +3885,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-account-keys", @@ -3906,7 +3906,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3917,7 +3917,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -3932,7 +3932,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "1.2.0" +version = "1.2.1" dependencies = [ "chrono", "clap 3.1.18", @@ -3965,7 +3965,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3996,7 +3996,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4027,7 +4027,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0" +version = "1.2.1" dependencies = [ "crc", "displaydoc", @@ -4047,7 +4047,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-common", "mc-util-uri", @@ -4055,7 +4055,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "1.2.0" +version = "1.2.1" dependencies = [ "grpcio", "mc-attest-core", @@ -4075,7 +4075,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "criterion", @@ -4110,7 +4110,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -4128,7 +4128,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4136,7 +4136,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4158,7 +4158,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4171,7 +4171,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "grpcio", @@ -4190,7 +4190,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-account-keys", @@ -4213,7 +4213,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4263,7 +4263,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "lazy_static", @@ -4289,7 +4289,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "dirs", @@ -4311,7 +4311,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "mc-api", @@ -4322,7 +4322,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4335,7 +4335,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "1.2.0" +version = "1.2.1" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4366,7 +4366,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4399,7 +4399,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "futures", @@ -4413,7 +4413,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4477,7 +4477,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "futures", @@ -4495,7 +4495,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "grpcio", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "1.2.0" +version = "1.2.1" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4602,7 +4602,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "1.2.0" +version = "1.2.1" dependencies = [ "grpcio", "hex", @@ -4625,7 +4625,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cc", "lazy_static", @@ -4635,7 +4635,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4643,7 +4643,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4652,7 +4652,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4660,7 +4660,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4669,21 +4669,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -4694,7 +4694,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -4710,7 +4710,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4720,18 +4720,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-urts" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-common", "mc-sgx-build", @@ -4742,7 +4742,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "hex", "mc-account-keys", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-account-keys", "mc-api", @@ -4764,7 +4764,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-util-test-vector", "serde", @@ -4773,7 +4773,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "1.2.0" +version = "1.2.1" dependencies = [ "hex", "mc-account-keys", @@ -4788,7 +4788,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "1.2.0" +version = "1.2.1" dependencies = [ "hex", "mc-account-keys", @@ -4810,7 +4810,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "bulletproofs-og", @@ -4852,7 +4852,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4869,7 +4869,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "1.2.0" +version = "1.2.1" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4896,7 +4896,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "hex", @@ -4905,7 +4905,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4921,7 +4921,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4929,7 +4929,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "json", @@ -4937,7 +4937,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "displaydoc", @@ -4948,7 +4948,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cc", @@ -4967,7 +4967,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "binascii", @@ -4979,18 +4979,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-util-from-random" -version = "1.2.0" +version = "1.2.1" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "hex", @@ -5009,7 +5009,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "clap 3.1.18", @@ -5043,7 +5043,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "grpcio", @@ -5054,7 +5054,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "hex", @@ -5065,11 +5065,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-util-keyfile" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "clap 3.1.18", @@ -5097,7 +5097,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5107,7 +5107,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "1.2.0" +version = "1.2.1" dependencies = [ "proc-macro2", "quote", @@ -5116,7 +5116,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "1.2.0" +version = "1.2.1" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5124,7 +5124,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "1.2.0" +version = "1.2.1" dependencies = [ "chrono", "grpcio", @@ -5137,7 +5137,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "1.2.0" +version = "1.2.1" dependencies = [ "itertools", "mc-sgx-css", @@ -5145,7 +5145,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "generic-array", "prost", @@ -5155,7 +5155,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "hex", @@ -5168,7 +5168,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0" +version = "1.2.1" dependencies = [ "prost", "serde", @@ -5177,7 +5177,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5188,7 +5188,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "itertools", @@ -5202,7 +5202,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "1.2.0" +version = "1.2.1" dependencies = [ "serde", "serde_json", @@ -5210,7 +5210,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "1.2.0" +version = "1.2.1" dependencies = [ "proc-macro2", "quote", @@ -5219,7 +5219,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "displaydoc", @@ -5237,7 +5237,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "1.2.0" +version = "1.2.1" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5281,7 +5281,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 008294f9b5..8b8a6a0e5e 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index fb4839ee85..72c4c214ac 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index 235d001130..153201f0f2 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index a26a8698fb..bf5c3ed984 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/android-bindings/lib-wrapper/android-bindings/publish.gradle b/android-bindings/lib-wrapper/android-bindings/publish.gradle index 8e4cdeb936..288d6a7545 100644 --- a/android-bindings/lib-wrapper/android-bindings/publish.gradle +++ b/android-bindings/lib-wrapper/android-bindings/publish.gradle @@ -1,6 +1,6 @@ apply plugin: 'maven-publish' -version '1.3.0-pre0' +version '1.2.1' group 'com.mobilecoin' Properties properties = new Properties() diff --git a/api/Cargo.toml b/api/Cargo.toml index b4ab354fab..070ee66bec 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index 381a31c76a..04d40ddab5 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index b56f9e8545..50a00d1ac2 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index 8e595a677f..d32a3e75e0 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index 0c086dcb19..ac59b0e24e 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index d3e48e9f34..cd6e675aac 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index cce1f387ce..50117d2662 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index f753af5822..0c699be3dd 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index d800173b2c..8f5480c488 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/common/Cargo.toml b/common/Cargo.toml index f7f9f9e80a..8d8dbeafd8 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/Cargo.toml b/connection/Cargo.toml index 22cf59dcbe..148d74da58 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index ba43c1f931..4fd998333c 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index 8ebe307b2a..46955e7570 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index 73cc507003..64a3316e89 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index 7867f69a89..315cafedd7 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index d7ccf529b5..42873b26c1 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index 36855e5cb4..8922280334 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index 299fb0a938..00adeae2f3 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index 47f04b1101..87fbd89b70 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index e9504beeca..749ec29a52 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0" +version = "1.2.1" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-build" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-transaction-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0" +version = "1.2.1" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0" +version = "1.2.1" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index a7c4e1259f..b4d20f6862 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index b2650cfd69..2c1d648f15 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index f3363132d9..27653e3bb3 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index 3b7bc6a047..ed992cceba 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index aa66e1d854..187ae2553c 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index 406b8c754c..38fb37fcd5 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index f12dbd946b..3e05797dd1 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index 2e6b45c948..aa8124e47d 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index 9b3987a16f..7c0b4bd6a2 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index 2270ce10c4..2c6191b241 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index 98303fb7e7..4486fe2750 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index 8eab9561c2..7b84bd48ea 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index 6f86c2eb5f..0df9250bba 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index c41709546a..0693d5fd75 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index e686ad0272..51b28860e0 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index 7d91109bce..fcf5a4dfcd 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index c99e5e8370..a44b5c537f 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index fd11243dcb..38d2ea71cf 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index 370467ac03..e2cc466916 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index 803453fb08..3bd1b35cfc 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 10582403f0..254cb12013 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index 0d77525147..de3e75e832 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index 5901582f50..dab52f7375 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index ed1962df8d..d0dc462f15 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index fa7062a437..59b470577f 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index 39a9664f08..af8f645262 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 741763d7bb..6ed4aa3332 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index 3a75519405..5dcc14fc45 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index 9fa099bd31..afdef7eaba 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index 66fabc2c04..cc9cb97a9c 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index e60a6efef8..fe8af01230 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index 208d8d74e5..a23f5bb9ba 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 792459de21..1a9f3d4c6c 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0" +version = "1.2.1" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0" +version = "1.2.1" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0" +version = "1.2.1" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-build" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-transaction-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0" +version = "1.2.1" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0" +version = "1.2.1" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index 00b6ca6f5b..7d521d6011 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index bd777ca712..34f0e27a5f 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index e728db1507..d0b738b2fc 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "1.2.0" +version = "1.2.1" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index fd8ee674c5..80013beff9 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index 41610f4b41..dff459d487 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index 8ba33872b1..eb0a82308e 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index 730ab185c9..d432daa602 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index e555a3fae9..8f162af6cb 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index 312c2b010c..7ea5936f69 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 68bf082776..fe066b3cb0 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0" +version = "1.2.1" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0" +version = "1.2.1" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0" +version = "1.2.1" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-build" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-transaction-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0" +version = "1.2.1" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0" +version = "1.2.1" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index c11a4ab663..83555f6ecc 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index 54b82932fc..7fa6b7c63a 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index 3babe8bc12..32c1efac3d 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "1.2.0" +version = "1.2.1" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index 45e8184129..35ff9bfb5f 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index 436f3dbb22..0f4a5d71f7 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index 79186be6b7..8f2947e05a 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index 55c7f5be6c..a5bbaf835d 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index 23e1ca041d..de315fa0ac 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 731455aa14..955c6c04ba 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index 7bde3126e5..24ed86298e 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index 41789af393..703a10d64b 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index d8107efd02..aadc1acc10 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index 11000148f2..2e23f59a1c 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index 5ab0585465..c14f37012c 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index 0f341cc5c0..2211750aa4 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index a41be0a1d2..55defeb920 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "1.2.0" +version = "1.2.1" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index eb252a9a50..45261c76f4 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index 09bb367770..610f803033 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index 4cc4aacca4..370989389e 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index b69a512694..f3db139f85 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index dc03ad8222..d2e44c334d 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index 49295ac0e6..2f8b36b1b5 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index d190d3d883..ca62aa5e68 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "1.2.0" +version = "1.2.1" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 402c88cc6e..8712d326ef 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index 60b3156044..5f4eed6dde 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index ad38eff738..27851fa755 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index dc6fafcf2c..943df1faa9 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index 628d9784d8..7001247c25 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index 2b3aefa7c8..e754bf903c 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index 90abbe6e14..eb770de11d 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index fc544653f2..20fe843279 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index 79af6992f5..a3adb12b69 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index 128c5e158f..43fdd90efc 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index fa2f3cbe7c..15eed45db2 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.0" +version = "1.2.1" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.0" +version = "1.2.1" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.0" +version = "1.2.1" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.0" +version = "1.2.1" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-build" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.0" +version = "1.2.1" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.0" +version = "1.2.1" [[package]] name = "mc-transaction-core" -version = "1.2.0" +version = "1.2.1" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.0" +version = "1.2.1" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.0" +version = "1.2.1" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.0" +version = "1.2.1" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.0" +version = "1.2.1" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.0" +version = "1.2.1" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index f27184668b..be92143b2d 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index 277b21675c..592c89b418 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index 9a8cc8c62e..5653adc7b2 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index ca628bc200..efdfb52675 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index 456f6825ac..7d0deb1dc9 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index 94b3c416fb..a5d6a6f43f 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index 4461e8e548..9b0dd141e6 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index 6f05030830..37a6325396 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index 07303d433e..2d6005419c 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index 49525d51ea..0a4a692ab0 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index f26cb37bac..8c0b3bbf93 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index d309970f01..6d2ed6172d 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index 4de11075c2..1afab3ea81 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index 20f5e4083a..ec065f3d0d 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index fb5ceb1a7a..c9be196eda 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/peers/Cargo.toml b/peers/Cargo.toml index bd1d4d10c8..71672e1670 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index 082ca6b0e5..3fb49dec3d 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index ff0e1c47c6..40e6e41754 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index 66363dfe68..a90bd04271 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index aba4938403..a4bf07bdc2 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index 682750164b..cb972a614d 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index 7e57d4e893..0f613f7ac5 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index 909ecc3da7..f74e1081c4 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index cd18e4c3af..b32b00a10c 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index 219f22d1f3..0d0f00caa5 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index b9f2673090..cb52bf6a48 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index 59b9646386..0ca0d01ae3 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index 1c177378fc..0fba868145 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index 88a0628db2..ca7fc81159 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index a5680217e5..ac5f0e1b0e 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index 4578e2c418..5df314becb 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index 92c81abf4c..489a71505b 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index f3ca4f5495..bd02f32f84 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index b2c0d3a091..c2c4a6bb79 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index 269b6e9423..ca1983b9ec 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "1.2.0" +version = "1.2.1" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index e1a5120bff..d02e5244b4 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index 36103bd463..4febd30469 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index d5a3b2170a..b8d0219962 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index 43ff4cb607..f175b329ad 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index ae37b1cb4f..788f573e39 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index 28f5caad38..aeec31acfb 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index d88f69cb0b..ab5a851162 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 71e076461e..674075e527 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index feca639764..8ad8369b7f 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index 5485b2bb45..3728ce80b5 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index 99598c3665..8e7dd690d5 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index b3eb35f15c..e2c07974ca 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index 0c5591da31..24c104dd71 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index 1170f0ab4a..062cf11bf1 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index c6015de094..ccc733c612 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index b87f7b5390..75700ee6c5 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index e9c0285375..cc9bf89f78 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index 31260b0a4d..6e82227b5d 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index f5b5f0005d..bf7612258d 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index 0829a68e7f..edc9d3ceff 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index 535e5dd274..e66add4dc4 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index 0127ddbc18..349267b428 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 34770708cd..4b381f7531 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index 07d220912b..e19d0bd84f 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index 777ce63932..5ac11a5256 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index 64cd928bbf..8644fed3ca 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index 514cf00166..b8d089e98f 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index eb3ea6d4cc..48b1255fbe 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index c710bf4c66..462dbc8e42 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index f1e4c73537..343e72d3da 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index 3f78b94f59..f8df89eaf6 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index 500ec02fec..47f793a875 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index 2891af0573..28e842455b 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index c8759fef20..34f5f04aa2 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index b1d10c57e7..e8f8fd8ae3 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index fe10b2aacd..1f880b446c 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index b673a0e4b2..32f230e4d6 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index bb17e244dc..defc90bfcb 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index 0033588826..af8ade1dbf 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "1.2.0" +version = "1.2.1" authors = ["MobileCoin"] edition = "2018" From 895ee6695becc27fefb917bf70fdfcd0e2481225 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Wed, 8 Jun 2022 15:22:06 -0500 Subject: [PATCH 33/77] use zerossl service for dev (#2109) --- .github/workflows/mobilecoin-dev-cd.yaml | 2 +- .github/workflows/mobilecoin-workflow-dev-deploy.yaml | 2 ++ .../consensus-node/templates/client-grpc-ingress.yaml | 3 +++ .../helm/consensus-node/templates/gateway-ingress.yaml | 3 +++ .../helm/consensus-node/templates/node-certificate.yaml | 9 +++++---- .../helm/consensus-node/templates/peer-grpc-ingress.yaml | 3 +++ .internal-ci/helm/consensus-node/values.yaml | 5 ++--- .../fog-services/templates/fog-ledger-grpc-ingress.yaml | 3 +++ .../fog-services/templates/fog-ledger-http-ingress.yaml | 3 +++ .../fog-services/templates/fog-report-grpc-ingress.yaml | 3 +++ .../fog-services/templates/fog-report-http-ingress.yaml | 3 +++ .../fog-services/templates/fog-view-grpc-ingress.yaml | 3 +++ .../fog-services/templates/fog-view-http-ingress.yaml | 3 +++ .internal-ci/helm/fog-services/values.yaml | 9 +++------ 14 files changed, 40 insertions(+), 14 deletions(-) diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 242e059dcc..075202465b 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -106,7 +106,7 @@ jobs: VIEW_ENCLAVE_PRIVKEY: ${{ env.ENCLAVE_SIGNING_KEY_PATH }} INGEST_ENCLAVE_PRIVKEY: ${{ env.ENCLAVE_SIGNING_KEY_PATH }} run: | - ls -al "${ENCLAVE_SIGNING_KEY_PATH}" + git config --global --add safe.directory '*' cargo build --release \ -p mc-admin-http-gateway \ -p mc-consensus-mint-client \ diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml index f09940158f..2f68f299bc 100644 --- a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -265,6 +265,7 @@ jobs: chart_version: ${{ inputs.version }} chart_set: | --set=image.org=${{ inputs.docker_image_org }} + --set=global.certManagerClusterIssuer=zerossl-prod-http chart_wait_timeout: 10m release_name: ${{ matrix.release_name }} namespace: ${{ inputs.namespace }} @@ -376,6 +377,7 @@ jobs: chart_wait_timeout: 10m chart_set: | --set=image.org=${{ inputs.docker_image_org }} + --set=global.certManagerClusterIssuer=zerossl-prod-http release_name: fog-services namespace: ${{ inputs.namespace }} rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} diff --git a/.internal-ci/helm/consensus-node/templates/client-grpc-ingress.yaml b/.internal-ci/helm/consensus-node/templates/client-grpc-ingress.yaml index 320bc11da4..e347e2d9a4 100644 --- a/.internal-ci/helm/consensus-node/templates/client-grpc-ingress.yaml +++ b/.internal-ci/helm/consensus-node/templates/client-grpc-ingress.yaml @@ -4,6 +4,9 @@ kind: Ingress metadata: name: {{ include "consensusNode.fullname" . }}-client-grpc annotations: + {{- if .Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ .Values.global.certManagerClusterIssuer }} + {{- end }} {{- toYaml .Values.node.client.ingress.annotations | nindent 4 }} labels: {{- include "consensusNode.labels" . | nindent 4 }} diff --git a/.internal-ci/helm/consensus-node/templates/gateway-ingress.yaml b/.internal-ci/helm/consensus-node/templates/gateway-ingress.yaml index c7f8b37e6e..913bcd1b4d 100644 --- a/.internal-ci/helm/consensus-node/templates/gateway-ingress.yaml +++ b/.internal-ci/helm/consensus-node/templates/gateway-ingress.yaml @@ -4,6 +4,9 @@ kind: Ingress metadata: name: {{ include "consensusNode.fullname" . }}-grpc-gateway annotations: + {{- if .Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ .Values.global.certManagerClusterIssuer }} + {{- end }} {{- toYaml .Values.grpcGateway.ingress | nindent 4}} labels: {{- include "consensusNode.labels" . | nindent 4 }} diff --git a/.internal-ci/helm/consensus-node/templates/node-certificate.yaml b/.internal-ci/helm/consensus-node/templates/node-certificate.yaml index 87d35b9f44..3a927c4695 100644 --- a/.internal-ci/helm/consensus-node/templates/node-certificate.yaml +++ b/.internal-ci/helm/consensus-node/templates/node-certificate.yaml @@ -1,5 +1,5 @@ # Copyright (c) 2018-2022 The MobileCoin Foundation -apiVersion: cert-manager.io/v1alpha2 +apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: {{ include "consensusNode.fullname" . }}-internal-tls @@ -10,9 +10,10 @@ spec: secretName: {{ include "consensusNode.fullname" . }}-internal-tls duration: 8760h # 365d renewBefore: 360h # 15d - keySize: 2048 - keyAlgorithm: rsa - keyEncoding: pkcs1 + privateKey: + size: 2048 + algorithm: RSA + encoding: PKCS1 usages: - server auth - client auth diff --git a/.internal-ci/helm/consensus-node/templates/peer-grpc-ingress.yaml b/.internal-ci/helm/consensus-node/templates/peer-grpc-ingress.yaml index 193457a4ed..bdbd83d0b6 100644 --- a/.internal-ci/helm/consensus-node/templates/peer-grpc-ingress.yaml +++ b/.internal-ci/helm/consensus-node/templates/peer-grpc-ingress.yaml @@ -4,6 +4,9 @@ kind: Ingress metadata: name: {{ include "consensusNode.fullname" . }}-peer-grpc annotations: + {{- if .Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ .Values.global.certManagerClusterIssuer }} + {{- end }} {{- toYaml .Values.node.peer.ingress.annotations | nindent 4 }} labels: {{- include "consensusNode.labels" . | nindent 4 }} diff --git a/.internal-ci/helm/consensus-node/values.yaml b/.internal-ci/helm/consensus-node/values.yaml index df046a5ec8..4abc298a7a 100644 --- a/.internal-ci/helm/consensus-node/values.yaml +++ b/.internal-ci/helm/consensus-node/values.yaml @@ -10,6 +10,8 @@ image: ### Shared values with child charts. global: + certManagerClusterIssuer: letsencrypt-production-http + # Shared across all instances of consensusNodeConfig config. node: ledgerDistribution: @@ -149,7 +151,6 @@ node: client: ingress: annotations: - cert-manager.io/cluster-issuer: letsencrypt-production-http # HAProxy Ingress haproxy.org/server-proto: 'h2' # Force GRPC/H2 mode haproxy.org/server-ssl: 'false' # The backend (server) is http @@ -166,7 +167,6 @@ node: peer: ingress: annotations: - cert-manager.io/cluster-issuer: letsencrypt-production-http # HAProxy Ingress haproxy.org/server-proto: 'h2' # Force GRPC/H2 mode haproxy.org/server-ssl: 'false' # The backend (server) is http @@ -187,7 +187,6 @@ grpcGateway: name: go-grpc-gateway nodeSelector: {} ingress: - cert-manager.io/cluster-issuer: letsencrypt-production-http #HAProxy Ingress haproxy.org/path-rewrite: /gw/(.*) /\1 # Strip the /gw prefix haproxy.org/server-ssl: 'false' # The backend (server) is http diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-grpc-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-grpc-ingress.yaml index 487881b8a5..4fc0e27868 100644 --- a/.internal-ci/helm/fog-services/templates/fog-ledger-grpc-ingress.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-grpc-ingress.yaml @@ -7,6 +7,9 @@ metadata: app: fog-ledger {{- include "fogServices.labels" . | nindent 4 }} annotations: + {{- if .Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ .Values.global.certManagerClusterIssuer }} + {{- end }} {{ toYaml (tpl .Values.fogLedger.ingress.grpc.annotations . | fromYaml)| nindent 4 }} spec: tls: diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-http-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-http-ingress.yaml index 6f740b62f9..7a9e33343b 100644 --- a/.internal-ci/helm/fog-services/templates/fog-ledger-http-ingress.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-http-ingress.yaml @@ -7,6 +7,9 @@ metadata: app: fog-ledger {{- include "fogServices.labels" . | nindent 4 }} annotations: + {{- if .Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ .Values.global.certManagerClusterIssuer }} + {{- end }} {{ toYaml (tpl .Values.fogLedger.ingress.http.annotations . | fromYaml)| nindent 4 }} spec: tls: diff --git a/.internal-ci/helm/fog-services/templates/fog-report-grpc-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-report-grpc-ingress.yaml index 8fdf3b58de..ea527cccbc 100644 --- a/.internal-ci/helm/fog-services/templates/fog-report-grpc-ingress.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-report-grpc-ingress.yaml @@ -10,6 +10,9 @@ metadata: app: fog-report {{- include "fogServices.labels" $ | nindent 4 }} annotations: + {{- if $.Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ $.Values.global.certManagerClusterIssuer }} + {{- end }} {{- toYaml $.Values.fogReport.ingress.grpc.annotations | nindent 4 }} spec: tls: diff --git a/.internal-ci/helm/fog-services/templates/fog-report-http-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-report-http-ingress.yaml index 07daa248db..ec5c1db2ef 100644 --- a/.internal-ci/helm/fog-services/templates/fog-report-http-ingress.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-report-http-ingress.yaml @@ -10,6 +10,9 @@ metadata: app: fog-report {{- include "fogServices.labels" $ | nindent 4 }} annotations: + {{- if $.Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ $.Values.global.certManagerClusterIssuer }} + {{- end }} {{- toYaml $.Values.fogReport.ingress.http.annotations | nindent 4 }} spec: tls: diff --git a/.internal-ci/helm/fog-services/templates/fog-view-grpc-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-view-grpc-ingress.yaml index 445bfb4165..cfa9d1b084 100644 --- a/.internal-ci/helm/fog-services/templates/fog-view-grpc-ingress.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-view-grpc-ingress.yaml @@ -7,6 +7,9 @@ metadata: app: fog-view {{- include "fogServices.labels" . | nindent 4 }} annotations: + {{- if .Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ .Values.global.certManagerClusterIssuer }} + {{- end }} {{ toYaml (tpl .Values.fogView.ingress.grpc.annotations . | fromYaml)| nindent 4 }} spec: tls: diff --git a/.internal-ci/helm/fog-services/templates/fog-view-http-ingress.yaml b/.internal-ci/helm/fog-services/templates/fog-view-http-ingress.yaml index eecce0ca5b..b2e6607c43 100644 --- a/.internal-ci/helm/fog-services/templates/fog-view-http-ingress.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-view-http-ingress.yaml @@ -7,6 +7,9 @@ metadata: app: fog-view {{- include "fogServices.labels" . | nindent 4 }} annotations: + {{- if .Values.global.certManagerClusterIssuer }} + cert-manager.io/cluster-issuer: {{ .Values.global.certManagerClusterIssuer }} + {{- end }} {{ toYaml (tpl .Values.fogView.ingress.http.annotations . | fromYaml)| nindent 4 }} spec: tls: diff --git a/.internal-ci/helm/fog-services/values.yaml b/.internal-ci/helm/fog-services/values.yaml index d147b547fd..8b55c52af7 100644 --- a/.internal-ci/helm/fog-services/values.yaml +++ b/.internal-ci/helm/fog-services/values.yaml @@ -21,6 +21,9 @@ image: org: mobilecoin tag: '' # Overrides the image tag whose default is the chart appVersion. +global: + certManagerClusterIssuer: letsencrypt-production-http + ### Fog Report Service fogReport: replicaCount: 2 @@ -42,7 +45,6 @@ fogReport: ingress: grpc: annotations: - cert-manager.io/cluster-issuer: letsencrypt-production-http haproxy.org/server-proto: "h2" # Force GRPC/H2 mode haproxy.org/server-ssl: "false" # The backend (server) is http haproxy.org/timeout-client: 239s # 4 min timeout on azure @@ -54,7 +56,6 @@ fogReport: http: annotations: - cert-manager.io/cluster-issuer: letsencrypt-production-http haproxy.org/server-ssl: "false" # The backend (server) is http haproxy.org/timeout-client: 239s # 4 min timeout on azure haproxy.org/timeout-server: 239s @@ -100,7 +101,6 @@ fogView: ingress: grpc: annotations: |- - cert-manager.io/cluster-issuer: letsencrypt-production-http haproxy.org/server-proto: "h2" # Force GRPC/H2 mode haproxy.org/server-ssl: "false" # The backend (server) is http haproxy.org/timeout-client: 239s # 4 min timeout on azure @@ -113,7 +113,6 @@ fogView: cookie VIEW insert indirect nocache dynamic http: annotations: |- - cert-manager.io/cluster-issuer: letsencrypt-production-http haproxy.org/server-ssl: "false" # The backend (server) is http haproxy.org/timeout-client: 239s # 4 min timeout on azure haproxy.org/timeout-server: 239s @@ -187,7 +186,6 @@ fogLedger: ingress: grpc: annotations: |- - cert-manager.io/cluster-issuer: letsencrypt-production-http haproxy.org/server-proto: "h2" # Force GRPC/H2 mode haproxy.org/server-ssl: "false" # The backend (server) is http # haproxy.org/cookie-persistence: "fog-ledger" @@ -202,7 +200,6 @@ fogLedger: http: annotations: |- - cert-manager.io/cluster-issuer: letsencrypt-production-http haproxy.org/server-ssl: "false" # The backend (server) is http haproxy.org/timeout-client: 239s # 4 min timeout on azure haproxy.org/timeout-server: 239s From 35d6095b32b37e8daa0f24f96677395ee5c2e8e6 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Tue, 14 Jun 2022 19:02:05 -0500 Subject: [PATCH 34/77] Feature/v1.2.2 ledger from archive (#2116) * ledger-from-archive [skip current-release-v2-update] [skip current-release-v2-test] [skip current-release-v0-test] [skip current-release-v0-deploy] * add ledger-from-archive functionality, make consensus node_hw smarter when keeping existing data * cleanup and fix ledger-distribution logic [skip ci] * remove startfrom from the consensus chart [skip ci] * Update .internal-ci/docker/entrypoints/node_hw.sh [skip ci] Co-authored-by: Remoun Metyas * remove redirect from ledger-distribution superviosr [skip ci] Co-authored-by: Remoun Metyas --- .internal-ci/docker/Dockerfile.node_hw | 22 ++- .internal-ci/docker/Dockerfile.runtime-base | 8 +- .internal-ci/docker/entrypoints/node_hw.sh | 182 ++++++++++++++++++ .../node_hw/bin/wrapper-consensus-service.sh | 83 ++++++++ .../bin/wrapper-ledger-distribution.sh | 56 ++++++ .../docker/support/node_hw/filebeat.yml | 39 ++++ .../supervisor/conf.d/admin-http-gw.conf | 13 ++ .../supervisor/conf.d/aesm-service.conf | 15 ++ .../supervisor/conf.d/consensus-service.conf | 12 ++ .../node_hw/supervisor/conf.d/filebeat.conf | 15 ++ .../conf.d/ledger-distribution.conf | 12 ++ .../node_hw/supervisor/conf.d/supervisor.conf | 4 + .../templates/_helpers.tpl | 27 +++ .../templates/node-config-configmap.yaml | 9 +- .../node-ledger-distribution-secret.yaml | 3 +- .../templates/node-msg-signer-key-secret.yaml | 2 +- .../node-network-config-configmap.yaml | 33 +--- .../helm/consensus-node-config/values.yaml | 3 + .../consensus-node/templates/_helpers.tpl | 14 +- .../templates/node-deployment.yaml | 54 ++---- .../supervisor-admin-gateway-configmap.yaml | 21 -- ...upervisor-consensus-service-configmap.yaml | 31 --- .../supervisor-daemon-configmap.yaml | 11 -- ...ervisor-ledger-distribution-configmap.yaml | 23 --- .../templates/supervisor-sgx-configmap.yaml | 17 -- .internal-ci/helm/consensus-node/values.yaml | 56 +----- .../templates/ias-secret.yaml | 2 + .../helm/mc-core-dev-env-setup/values.yaml | 5 + 28 files changed, 531 insertions(+), 241 deletions(-) create mode 100755 .internal-ci/docker/entrypoints/node_hw.sh create mode 100755 .internal-ci/docker/support/node_hw/bin/wrapper-consensus-service.sh create mode 100755 .internal-ci/docker/support/node_hw/bin/wrapper-ledger-distribution.sh create mode 100644 .internal-ci/docker/support/node_hw/filebeat.yml create mode 100644 .internal-ci/docker/support/node_hw/supervisor/conf.d/admin-http-gw.conf create mode 100644 .internal-ci/docker/support/node_hw/supervisor/conf.d/aesm-service.conf create mode 100644 .internal-ci/docker/support/node_hw/supervisor/conf.d/consensus-service.conf create mode 100644 .internal-ci/docker/support/node_hw/supervisor/conf.d/filebeat.conf create mode 100644 .internal-ci/docker/support/node_hw/supervisor/conf.d/ledger-distribution.conf create mode 100644 .internal-ci/docker/support/node_hw/supervisor/conf.d/supervisor.conf delete mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-admin-gateway-configmap.yaml delete mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-consensus-service-configmap.yaml delete mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-daemon-configmap.yaml delete mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-ledger-distribution-configmap.yaml delete mode 100644 .internal-ci/helm/consensus-node/templates/supervisor-sgx-configmap.yaml diff --git a/.internal-ci/docker/Dockerfile.node_hw b/.internal-ci/docker/Dockerfile.node_hw index 2079e82dce..31e155fc53 100644 --- a/.internal-ci/docker/Dockerfile.node_hw +++ b/.internal-ci/docker/Dockerfile.node_hw @@ -16,20 +16,28 @@ COPY ${RUST_BIN_PATH}/libconsensus-enclave.signed.so /usr/bin/ COPY ${RUST_BIN_PATH}/mc-admin-http-gateway /usr/bin/ COPY ${RUST_BIN_PATH}/mc-ledger-migration /usr/bin/ COPY ${RUST_BIN_PATH}/mc-util-grpc-admin-tool /usr/bin/ - COPY ${RUST_BIN_PATH}/sample-keys /usr/local/bin/ COPY ${RUST_BIN_PATH}/generate-sample-ledger /usr/local/bin/ COPY ${RUST_BIN_PATH}/read-pubfile /usr/local/bin/ COPY .internal-ci/util/generate_origin_data.sh /usr/local/bin/ COPY .internal-ci/util/sample-keys.1.1.3 /util/ + # Populate origin data # We should pull origin data at runtime from an external source, like a public s3 url, but keep this for legacy. ARG ORIGIN_DATA_DIR=.internal-ci/sample_data COPY ${ORIGIN_DATA_DIR}/ledger /var/lib/mobilecoin/origin_data -# Entrypoint -# COPY docker/entrypoints/consensus_validator.sh /usr/bin/entrypoint.sh -# ENTRYPOINT ["/usr/bin/entrypoint.sh"] +# Supervisord +COPY .internal-ci/docker/support/node_hw/supervisor/conf.d /etc/supervisor/conf.d +COPY .internal-ci/docker/support/node_hw/filebeat.yml /etc/filebeat/filebeat.yml + +# Wrapper scripts +COPY .internal-ci/docker/support/node_hw/bin /usr/local/bin + +# Entrypoint and command +COPY .internal-ci/docker/entrypoints/node_hw.sh /usr/bin/entrypoint.sh +ENTRYPOINT ["/usr/bin/entrypoint.sh"] +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] # Rust defaults ENV RUST_BACKTRACE="1" @@ -43,3 +51,9 @@ EXPOSE 8000 EXPOSE 3223 # GRPC Peer EXPOSE 8443 + +# Volumes +VOLUME /config +VOLUME /sealed +VOLUME /var/run/aesmd +VOLUME /ledger diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base index f33382613a..2c09db8903 100644 --- a/.internal-ci/docker/Dockerfile.runtime-base +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -15,16 +15,20 @@ RUN apt-get update \ curl \ gnupg \ supervisor \ - libpq5 + libpq5 \ + jq # Install Filebeat repo RUN curl --retry 5 -fL https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add - \ && echo "deb https://artifacts.elastic.co/packages/oss-8.x/apt stable main" > /etc/apt/sources.list.d/elastic-8.x.list -# Install SGX ASEM repo +# Install SGX AESM repo COPY .internal-ci/docker/support/intel-sgx-archive-keyring.gpg /etc/apt/trusted.gpg.d/ RUN echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ focal main" > /etc/apt/sources.list.d/intel-sgx.list +ENV AESM_PATH="/opt/intel/sgx-aesm-service/aesm" +ENV LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" + # Install packages RUN apt-get update \ && apt-get install -y \ diff --git a/.internal-ci/docker/entrypoints/node_hw.sh b/.internal-ci/docker/entrypoints/node_hw.sh new file mode 100755 index 0000000000..0bddb814d2 --- /dev/null +++ b/.internal-ci/docker/entrypoints/node_hw.sh @@ -0,0 +1,182 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# Entrypoint script for node_hw (consensus and friends). +# + +# Optional Load vars from .env file +# DOTENV_CONFIG_FILE +# default /config/.env + +# Required Vars +# MC_BRANCH - mobilecoin network for monitoring/logs +# example test (for testnet), prod (for mainnet), alpha + +# Required Vars consensus-service +# MC_PEER_RESPONDER_ID - fully qualified name:port that fronts the peer port +# example peer1.test.mobilecoin.com:443 +# MC_CLIENT_RESPONDER_ID - fully qualified name:port that fronts the client port +# example client1.test.mobilecoin.com:443 +# MC_MSG_SIGNER_KEY - private key for signing messages +# MC_IAS_API_KEY - Intel IAS API key +# MC_IAS_SPID - Intel IAS spid + +# Optional Vars consensus-service +# MC_TX_SOURCE_URL - http url to retrieve archive (s3) blocks for node +# example https://s3-eu-central-1.amazonaws.com/mobilecoin.chain/node1.test.mobilecoin.com/ +# MC_PEER_LISTEN_URI +# default insecure-mcp://0.0.0.0:8443/ +# tls example mcp://0.0.0.0:8443/?tls-chain=cert.pem&tls-key=key.pem +# MC_CLIENT_LISTEN_URI +# default insecure-mc://0.0.0.0:3223/ +# tls example mc://0.0.0.0:3223/?tls-chain=cert.pem&tls-key=key.pem +# MC_ADMIN_LISTEN_URI - grpc port for admin - use mc-admin-http-gw to interact. +# default insecure-mca://127.0.0.1:8001/ +# MC_NETWORK - path to network config file +# default /config/network.toml +# MC_TOKENS - path to signed tokens config file +# default /config/tokens.signed.json +# MC_LEDGER_PATH - directory for ledger database +# default /ledger +# MC_SCP_DEBUG_DUMP - directory for debugging +# default /scp-debug-dump +# MC_SEALED_BLOCK_SIGNING_KEY - file path for sealed signing key +# default /sealed/block-signing-key + +# Required Vars ledger-distribution +# MC_DEST - s3 path for publish ledger +# example s3://mobilecoin.chain/node1.test.mobilecoin.com?region=eu-central-1 + +# AWS_ACCESS_KEY_ID - standard AWS vars +# AWS_SECRET_ACCESS_KEY - standard AWS vars +# AWS_REGION - standard AWS vars + +# Optional Vars - Sentry Monitoring +# LEDGER_DISTRIBUTION_SENTRY_DSN - sentry DSN +# CONSENSUS_SERVICE_SENTRY_DSN - sentry DSN + +# Optional Vars - Remote Logging +# ES_HOST +# ES_USERNAME +# ES_PASSWORD +# ES_PORT + +set -e + +# is_set +# check to see if required variable has a value +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + exit 1 + fi +} + +echo "Starting Up with command ${1}" + +# archive_curl +# Do HEAD to see if origin block exists +archive_curl() +{ + /usr/bin/curl -IfsSL --retry 3 "${1}00/00/00/00/00/00/00/0000000000000000.pb" +} + +############################################## +# Optional, load env vars from .env file +DOTENV_CONFIG_FILE=${DOTENV_CONFIG_FILE:-"/config/.env"} +if [[ -f "${DOTENV_CONFIG_FILE}" ]] +then + # Automatically export all loaded vars + set -o allexport + # shellcheck disable=SC1090 # optional import of .env + source "${DOTENV_CONFIG_FILE}" + set +o allexport +fi + +###################################################################### +# set up optional filebeat and bootstrap the ledger on normal start +if [[ "${1}" == "/usr/bin/supervisord" ]] +then + # check for required vars + is_set MC_BRANCH + is_set MC_PEER_RESPONDER_ID + is_set MC_CLIENT_RESPONDER_ID + is_set MC_MSG_SIGNER_KEY + is_set MC_IAS_API_KEY + is_set MC_IAS_SPID + is_set MC_DEST + is_set AWS_ACCESS_KEY_ID + is_set AWS_SECRET_ACCESS_KEY + is_set AWS_REGION + + # Enable filebeat if provided with ElasticSearch target vars. + if [[ -n "${ES_HOST}" ]] + then + echo "Found ES_HOST - enabling filebeat log shipping" + # required vars for shipping logs via filebeat + is_set ES_PASSWORD + is_set ES_USERNAME + + export ES_PORT=${ES_PORT:-443} + export ES_INDEX=${ES_INDEX:-"filebeat"} + export MC_LOG_UDP_JSON=127.0.0.1:16666 + + # enable filebeat in supervisord + sed -i '' 's/numprocs=0/numprocs=1/g' /etc/supervisor/conf.d/filebeat.conf + fi + + # Ledger + echo "Bootstrapping ledger database" + + # Optional Vars + # MC_TX_SOURCE_URL - http source to retrieve block data. + + # Default vars + export MC_LEDGER_PATH=${MC_LEDGER_PATH:-"/ledger"} + export MC_STATE_FILE=${MC_STATE_FILE:-"/ledger/.distribution-state"} + export ORIGIN_LEDGER_PATH=${ORIGIN_LEDGER_PATH:-"/var/lib/mobilecoin/origin_data/data.mdb"} + + if [[ -f "${MC_LEDGER_PATH}/data.mdb" ]] + then + echo "Existing database found at ${MC_LEDGER_PATH}/data.mdb" + echo "Migrating ledger to latest version" + cp /ledger/data.mdb "/ledger/data.mdb.$(date +%y%m%d-%H%M%S)" + /usr/bin/mc-ledger-migration --ledger-db "${MC_LEDGER_PATH}" + else + # Look for wallet keys seed - development and CD deploys + if [[ -n "${INITIAL_KEYS_SEED}" ]] + then + echo "INITIAL_KEYS_SEED found - populating origin data" + export INITIALIZE_LEDGER="true" + + /usr/local/bin/generate_origin_data.sh + + cp /tmp/sample_data/ledger/data.mdb "${MC_LEDGER_PATH}" + + # Try to find origin block from s3 archive - preserve existing data, testnet/mainnet + elif archive_curl "${MC_TX_SOURCE_URL}" + then + echo "Remote archive ledger found - restore with ledger-from-archive" + echo " Note: RUST_LOG=warn so we don't get 1m+ lines of logs" + echo " Please be patient" + + RUST_LOG=warn /usr/bin/ledger-from-archive --ledger-db "${MC_LEDGER_PATH}" + + # Copy ledger from embedded origin block + elif [[ -f "${ORIGIN_LEDGER_PATH}" ]] + then + echo "Found origin ledger at ${ORIGIN_LEDGER_PATH}" + cp "${ORIGIN_LEDGER_PATH}" "${MC_LEDGER_PATH}" + else + # We ain't found nothin, bail out! + echo "INITIAL_KEYS_SEED not set, no remote ledger and cannot find origin ledger file" + exit 1 + fi + fi +fi + +# Run with docker command - probably /usr/bin/supervisord +exec "$@" diff --git a/.internal-ci/docker/support/node_hw/bin/wrapper-consensus-service.sh b/.internal-ci/docker/support/node_hw/bin/wrapper-consensus-service.sh new file mode 100755 index 0000000000..d3596fc6cb --- /dev/null +++ b/.internal-ci/docker/support/node_hw/bin/wrapper-consensus-service.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# wrapper-consensus-service.sh - Wrapper script around consensus-service to +# make sure required services have started and stayed running. + +# is_set +# check to see if required variable has a value +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + exit 1 + fi +} + +# super_status +# get status from a supervisord service +super_status() +{ + supervisorctl status "${1}" | awk '{print $2}' +} + +# Required vars +is_set MC_BRANCH +is_set MC_PEER_RESPONDER_ID +is_set MC_CLIENT_RESPONDER_ID +is_set MC_MSG_SIGNER_KEY +is_set MC_IAS_API_KEY +is_set MC_IAS_SPID + +# Default vars +export MC_PEER_LISTEN_URI=${MC_PEER_LISTEN_URI:-"insecure-mcp://0.0.0.0:8443/"} +export MC_CLIENT_LISTEN_URI=${MC_CLIENT_LISTEN_URI:-"insecure-mc://0.0.0.0:3223/"} +export MC_ADMIN_LISTEN_URI=${MC_ADMIN_LISTEN_URI:-"insecure-mca://127.0.0.1:8001/"} +export MC_NETWORK=${MC_NETWORK:-"/config/network.json"} +export MC_TOKENS=${MC_TOKENS:-"/config/tokens.signed.json"} +export MC_LEDGER_PATH=${MC_LEDGER_PATH:-"/ledger"} +export MC_SCP_DEBUG_DUMP=${MC_SCP_DEBUG_DUMP:-"/scp-debug-dump"} +export MC_SEALED_BLOCK_SIGNING_KEY=${MC_SEALED_BLOCK_SIGNING_KEY:-"/sealed/block-signing-key"} +export MC_SENTRY_DSN=${CONSENSUS_SERVICE_SENTRY_DSN} + +# Optional vars - sentry/logging +# CONSENSUS_SERVICE_SENTRY_DSN +# MC_LOG_UDP_JSON + +# Check to see if aesm service is ready. +aesm_socket=/var/run/aesmd/aesm.socket +aesm=0 +ledger=0 +echo "mc.app:wrapper-consensus-service Wait for ledger-distribution and aesm service to become ready" +while [[ ${aesm} -le 1 ]] || [[ ${ledger} -le 1 ]] +do + sleep 10 + + aesm_status=$(super_status aesm-service) + ledger_distribution_status=$(super_status ledger-distribution) + + # does the aesm socket exist, is the service in RUNNING? + if [[ -S "${aesm_socket}" ]] && [[ "${aesm_status}" == "RUNNING" ]] + then + echo "mc.app:wrapper-consensus-service aesm-service is RUNNING and ${aesm_socket} found - success ${aesm}" + ((aesm++)) + else + echo "mc.app:wrapper-consensus-service aesm-service is not RUNNING or ${aesm_socket} not found - reset counter" + aesm=0 + fi + + # is ledger-distribution running? + if [[ "${ledger_distribution_status}" == "RUNNING" ]] + then + echo "mc.app:wrapper-consensus-service ledger-distribution is RUNNING - success ${ledger}" + ((ledger++)) + else + echo "mc.app:wrapper-consensus-service ledger-distribution is not RUNNING - reset counter" + ledger=0 + fi +done + +# Run consensus-service with ENV var options +/usr/bin/consensus-service diff --git a/.internal-ci/docker/support/node_hw/bin/wrapper-ledger-distribution.sh b/.internal-ci/docker/support/node_hw/bin/wrapper-ledger-distribution.sh new file mode 100755 index 0000000000..5145af39ad --- /dev/null +++ b/.internal-ci/docker/support/node_hw/bin/wrapper-ledger-distribution.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# wrapper-ledger-distribution.sh - Wrapper script around ledger-distribution to +# solve last/next and missing state logic. + +set -e + +# is_set +# check to see if required variable has a value +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + exit 1 + fi +} + +is_set MC_DEST +is_set AWS_ACCESS_KEY_ID +is_set AWS_SECRET_ACCESS_KEY +is_set AWS_REGION +is_set MC_BRANCH + +# Optional - for sentry monitoring +# LEDGER_DISTRIBUTION_SENTRY_DSN +# MC_LOG_UDP_JSON + +# Default vars +export MC_LEDGER_PATH=${MC_LEDGER_PATH:-"/ledger"} +export MC_STATE_FILE=${MC_STATE_FILE:-"/ledger/.distribution-state"} +export MC_SENTRY_DSN=${LEDGER_DISTRIBUTION_SENTRY_DSN} + + +if [[ -f "${MC_STATE_FILE}" ]] +then + # Check for valid state file + echo "mc.app:wrapper-ledger-distribution - State file found MC_START_FROM=last" + echo "mc.app:wrapper-ledger-distribution - Check for valid next_block" + + next_block=$(jq -r .next_block "${MC_STATE_FILE}") + if [[ "${next_block}" -le 0 ]] + then + echo "mc.app:wrapper-ledger-distribution - Invalid next_block <= 0" + exit 1 + fi + + export MC_START_FROM=last +else + echo "mc.app:wrapper-ledger-distribution - no state file found MC_START_FROM=next" + export MC_START_FROM=next +fi + +/usr/bin/ledger-distribution diff --git a/.internal-ci/docker/support/node_hw/filebeat.yml b/.internal-ci/docker/support/node_hw/filebeat.yml new file mode 100644 index 0000000000..22844328f6 --- /dev/null +++ b/.internal-ci/docker/support/node_hw/filebeat.yml @@ -0,0 +1,39 @@ +logging: + level: error + to_stderr: true + +filebeat.inputs: +- type: udp + max_message_size: 65KiB + host: localhost:16666 + fields_under_root: true + fields: + mc.network: ${MC_BRANCH} + mc.local_node_id: ${MC_CLIENT_RESPONDER_ID} + +processors: +- rename: + fields: + - from: agent + to: beat_agent + ignore_missing: true +- rename: + fields: + - from: log.file.path + to: source + ignore_missing: true + +output: + elasticsearch: + enabled: true + hosts: ["${ES_HOST}:${ES_PORT}"] + protocol: https + username: "${ES_USERNAME}" + password: "${ES_PASSWORD}" + index: "${ES_INDEX:filebeat}-%{+yyyy.MM.dd}" + +setup: + template: + enabled: true + name: ${ES_INDEX:filebeat} + pattern: ${ES_INDEX:filebeat} diff --git a/.internal-ci/docker/support/node_hw/supervisor/conf.d/admin-http-gw.conf b/.internal-ci/docker/support/node_hw/supervisor/conf.d/admin-http-gw.conf new file mode 100644 index 0000000000..10e280a906 --- /dev/null +++ b/.internal-ci/docker/support/node_hw/supervisor/conf.d/admin-http-gw.conf @@ -0,0 +1,13 @@ +; Copyright (c) 2018-2022 The MobileCoin Foundation +[program:mc-admin-http-gateway] +priority=100 +; If we don't start in 20 seconds, then go to fatal. +startsecs=20 +command=/usr/bin/mc-admin-http-gateway + --listen-host 0.0.0.0 + --listen-port 8000 + --admin-uri insecure-mca://127.0.0.1:8001/ + +stdout_logfile=/dev/null +stderr_logfile=/dev/null +autorestart=true diff --git a/.internal-ci/docker/support/node_hw/supervisor/conf.d/aesm-service.conf b/.internal-ci/docker/support/node_hw/supervisor/conf.d/aesm-service.conf new file mode 100644 index 0000000000..1441cee255 --- /dev/null +++ b/.internal-ci/docker/support/node_hw/supervisor/conf.d/aesm-service.conf @@ -0,0 +1,15 @@ +; Copyright (c) 2018-2022 The MobileCoin Foundation +[program:aesm-service] +priority=50 +; if we don't start in 20 seconds go to fatal +startsecs=20 +environment=AESM_PATH="/opt/intel/sgx-aesm-service/aesm",LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" +command=/opt/intel/sgx-aesm-service/aesm/aesm_service + --no-daemon + --no-syslog + +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/fd/2 +stderr_logfile_maxbytes=0 +autorestart=true diff --git a/.internal-ci/docker/support/node_hw/supervisor/conf.d/consensus-service.conf b/.internal-ci/docker/support/node_hw/supervisor/conf.d/consensus-service.conf new file mode 100644 index 0000000000..60b9aad879 --- /dev/null +++ b/.internal-ci/docker/support/node_hw/supervisor/conf.d/consensus-service.conf @@ -0,0 +1,12 @@ +; Copyright (c) 2018-2022 The MobileCoin Foundation +[program:consensus-service] +priority=100 +; if we don't start in 60 seconds go to fatal. +startsecs=60 +command=/usr/local/bin/wrapper-consensus-service.sh + +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/fd/2 +stderr_logfile_maxbytes=0 +autorestart=true diff --git a/.internal-ci/docker/support/node_hw/supervisor/conf.d/filebeat.conf b/.internal-ci/docker/support/node_hw/supervisor/conf.d/filebeat.conf new file mode 100644 index 0000000000..bb27a06188 --- /dev/null +++ b/.internal-ci/docker/support/node_hw/supervisor/conf.d/filebeat.conf @@ -0,0 +1,15 @@ +; Copyright (c) 2018-2022 The MobileCoin Foundation +[program:filebeat] +priority=10 +; if we don't start in 60 seconds go to fatal +startsecs=60 +; don't start by default, entrypoint will sed 1 if ES vars are set +numprocs=0 +command=/usr/bin/filebeat + --path.config /etc/filebeat + +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/fd/2 +stderr_logfile_maxbytes=0 +autorestart=true diff --git a/.internal-ci/docker/support/node_hw/supervisor/conf.d/ledger-distribution.conf b/.internal-ci/docker/support/node_hw/supervisor/conf.d/ledger-distribution.conf new file mode 100644 index 0000000000..eecdebb8a9 --- /dev/null +++ b/.internal-ci/docker/support/node_hw/supervisor/conf.d/ledger-distribution.conf @@ -0,0 +1,12 @@ +; Copyright (c) 2018-2022 The MobileCoin Foundation +[program:ledger-distribution] +priority=50 +; if we don't start in 20 seconds go to fatal +startsecs=20 +command=/usr/local/bin/wrapper-ledger-distribution.sh + +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/fd/2 +stderr_logfile_maxbytes=0 +autorestart=true diff --git a/.internal-ci/docker/support/node_hw/supervisor/conf.d/supervisor.conf b/.internal-ci/docker/support/node_hw/supervisor/conf.d/supervisor.conf new file mode 100644 index 0000000000..a59c1e178b --- /dev/null +++ b/.internal-ci/docker/support/node_hw/supervisor/conf.d/supervisor.conf @@ -0,0 +1,4 @@ +; Copyright (c) 2018-2022 The MobileCoin Foundation +[supervisord] +nodaemon=true +user=root diff --git a/.internal-ci/helm/consensus-node-config/templates/_helpers.tpl b/.internal-ci/helm/consensus-node-config/templates/_helpers.tpl index fe4b8c7526..334e4e11c7 100644 --- a/.internal-ci/helm/consensus-node-config/templates/_helpers.tpl +++ b/.internal-ci/helm/consensus-node-config/templates/_helpers.tpl @@ -64,7 +64,34 @@ app.kubernetes.io/instance: {{ .Release.Name }} {{- tpl .Values.node.peer.hostname . }} {{- end }} +{{/* TX_SOURCE_URL */}} +{{- define "consensusNodeConfig.txSourceUrl" -}} +{{- tpl .Values.node.txSourceUrl . }} +{{- end }} + {{/* ledgerDistributionAWSPath */}} {{- define "consensusNodeConfig.ledgerDistributionAWSPath" -}} {{ printf "s3://%s/%s?region=%s" .Values.global.node.ledgerDistribution.s3Bucket (include "consensusNodeConfig.clientHostname" .) .Values.global.node.ledgerDistribution.awsRegion }} {{- end }} + +{{/* networkJson */}} +{{- define "consensusNodeConfig.networkJson" -}} +{{- $peers := .Values.global.node.networkConfig.peers }} +{{- $localPeer := (include "consensusNodeConfig.peerHostname" .) }} +{{- $threshold := .Values.global.node.networkConfig.threshold }} +{{- $broadcastPeers := list }} +{{- $txSourceUrls := list }} +{{- $members := list }} +{{- range $key, $value := $peers }} +{{- $peer := tpl $value.peer.hostname $ }} +{{- $archive := tpl $value.ledgerArchiveLocation $ }} +{{- if not (eq $peer $localPeer) }} +{{- $broadcastPeers = append $broadcastPeers (printf "mcp://%s:%s/?consensus-msg-key=%s" $peer $value.peer.port $value.signerPublicKey) }} +{{- $txSourceUrls = append $txSourceUrls $archive }} +{{- $members = append $members (dict "type" "Node" "args" (printf "%s:%s" $peer $value.peer.port)) }} +{{- end }} +{{- end }} +{{- $quorumSet := dict "threshold" (atoi $threshold) "members" $members }} +{{- $networkJson := dict "broadcast_peers" $broadcastPeers "tx_source_urls" $txSourceUrls "quorum_set" $quorumSet }} +{{- toPrettyJson $networkJson }} +{{- end }} diff --git a/.internal-ci/helm/consensus-node-config/templates/node-config-configmap.yaml b/.internal-ci/helm/consensus-node-config/templates/node-config-configmap.yaml index 00a3a24bd3..23e904d5f5 100644 --- a/.internal-ci/helm/consensus-node-config/templates/node-config-configmap.yaml +++ b/.internal-ci/helm/consensus-node-config/templates/node-config-configmap.yaml @@ -6,6 +6,9 @@ metadata: labels: {{- include "consensusNodeConfig.labels" . | nindent 4 }} data: - clientHostname: {{ include "consensusNodeConfig.clientHostname" . | squote }} - peerHostname: {{ include "consensusNodeConfig.peerHostname" . | squote }} - blockVersion: {{ .Values.global.node.nodeConfig.blockVersion | squote }} + CLIENT_HOSTNAME: {{ include "consensusNodeConfig.clientHostname" . | squote }} + PEER_HOSTNAME: {{ include "consensusNodeConfig.peerHostname" . | squote }} + MC_TX_SOURCE_URL: {{ include "consensusNodeConfig.txSourceUrl" . | squote }} + MC_BLOCK_VERSION: {{ .Values.global.node.nodeConfig.blockVersion | squote }} + MC_CLIENT_RESPONDER_ID: "{{ include "consensusNodeConfig.clientHostname" . }}:443" + MC_PEER_RESPONDER_ID: "{{ include "consensusNodeConfig.peerHostname" . }}:443" diff --git a/.internal-ci/helm/consensus-node-config/templates/node-ledger-distribution-secret.yaml b/.internal-ci/helm/consensus-node-config/templates/node-ledger-distribution-secret.yaml index 4370780dfc..996119ee17 100644 --- a/.internal-ci/helm/consensus-node-config/templates/node-ledger-distribution-secret.yaml +++ b/.internal-ci/helm/consensus-node-config/templates/node-ledger-distribution-secret.yaml @@ -12,6 +12,5 @@ stringData: AWS_SECRET_ACCESS_KEY: {{ .awsSecretAccessKey | quote }} AWS_REGION: {{ .awsRegion | quote }} LEDGER_DISTRIBUTION_S3_BUCKET: {{ .s3Bucket | quote }} - LEDGER_DISTRIBUTION_START_FROM: {{ .startFrom | quote }} - LEDGER_DISTRIBUTION_S3_PATH: {{ tpl .awsPath $ | quote }} + MC_DEST: {{ tpl .awsPath $ | quote }} {{- end }} diff --git a/.internal-ci/helm/consensus-node-config/templates/node-msg-signer-key-secret.yaml b/.internal-ci/helm/consensus-node-config/templates/node-msg-signer-key-secret.yaml index f6e5ce1d76..c3a85d0d63 100644 --- a/.internal-ci/helm/consensus-node-config/templates/node-msg-signer-key-secret.yaml +++ b/.internal-ci/helm/consensus-node-config/templates/node-msg-signer-key-secret.yaml @@ -7,4 +7,4 @@ metadata: labels: {{- include "consensusNodeConfig.labels" . | nindent 4 }} stringData: - NODE_SIGNER_KEY: {{ .Values.node.msgSignerKey.privateKey | quote }} + MC_MSG_SIGNER_KEY: {{ .Values.node.msgSignerKey.privateKey | quote }} diff --git a/.internal-ci/helm/consensus-node-config/templates/node-network-config-configmap.yaml b/.internal-ci/helm/consensus-node-config/templates/node-network-config-configmap.yaml index 2ae9296bd6..ffbe1a2247 100644 --- a/.internal-ci/helm/consensus-node-config/templates/node-network-config-configmap.yaml +++ b/.internal-ci/helm/consensus-node-config/templates/node-network-config-configmap.yaml @@ -1,7 +1,4 @@ # Copyright (c) 2018-2022 The MobileCoin Foundation -{{- $peers := .Values.global.node.networkConfig.peers }} -{{- $threshold := .Values.global.node.networkConfig.threshold }} -{{- $localPeerHostname := (include "consensusNodeConfig.peerHostname" .) }} apiVersion: v1 kind: ConfigMap metadata: @@ -9,31 +6,5 @@ metadata: labels: {{- include "consensusNodeConfig.labels" . | nindent 4 }} data: - network.toml: | - broadcast_peers = [ - {{- range $key, $value := $peers }} - {{- $peerHostname := tpl $value.peer.hostname $ }} - {{- if not (eq $peerHostname $localPeerHostname) }} - "mcp://{{ $peerHostname }}:{{ $value.peer.port }}/?consensus-msg-key={{ $value.signerPublicKey }}", - {{- end }} - {{- end }} - ] - - tx_source_urls = [ - {{- range $key, $value := $peers }} - {{- $peerHostname := tpl $value.peer.hostname $ }} - {{- $ledgerArchiveLocation := tpl $value.ledgerArchiveLocation $ }} - {{- if not (eq $peerHostname $localPeerHostname) }} - "{{ $ledgerArchiveLocation }}", - {{- end }} - {{- end }} - ] - - quorum_set = { threshold = {{ $threshold }}, members = [ - {{- range $key, $value := $peers }} - {{- $peerHostname := tpl $value.peer.hostname $ }} - {{- if not (eq $peerHostname $localPeerHostname) }} - { type = "Node", args = "{{ $peerHostname }}:{{ $value.peer.port }}" }, - {{- end }} - {{- end }} - ] } + network.json: |- + {{- include "consensusNodeConfig.networkJson" . | nindent 4 }} diff --git a/.internal-ci/helm/consensus-node-config/values.yaml b/.internal-ci/helm/consensus-node-config/values.yaml index debc3fe477..0fc3a3a441 100644 --- a/.internal-ci/helm/consensus-node-config/values.yaml +++ b/.internal-ci/helm/consensus-node-config/values.yaml @@ -13,6 +13,9 @@ node: peer: hostname: '' + ### S3 bucket for thin node's ledger + txSourceUrl: '' + ### This nodes's Message Signing Key msgSignerKey: privateKey: '' diff --git a/.internal-ci/helm/consensus-node/templates/_helpers.tpl b/.internal-ci/helm/consensus-node/templates/_helpers.tpl index 4a29bfac84..e346988982 100644 --- a/.internal-ci/helm/consensus-node/templates/_helpers.tpl +++ b/.internal-ci/helm/consensus-node/templates/_helpers.tpl @@ -71,7 +71,7 @@ lookup name from configmap if we have created the objects in consensus-node-conf */}} {{- define "consensusNode.peerHostname" -}} {{- if eq .Values.consensusNodeConfig.enabled false }} - {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.peerHostname | default "" }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.PEER_HOSTNAME | default "" }} {{- else }} {{- tpl .Values.consensusNodeConfig.node.peer.hostname . }} {{- end }} @@ -79,7 +79,7 @@ lookup name from configmap if we have created the objects in consensus-node-conf {{- define "consensusNode.clientHostname" -}} {{- if eq .Values.consensusNodeConfig.enabled false }} - {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.clientHostname | default "" }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.CLIENT_HOSTNAME | default "" }} {{- else }} {{- tpl .Values.consensusNodeConfig.node.client.hostname . }} {{- end }} @@ -87,12 +87,20 @@ lookup name from configmap if we have created the objects in consensus-node-conf {{- define "consensusNode.blockVersion" -}} {{- if eq .Values.consensusNodeConfig.enabled false }} - {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.blockVersion | default "false" }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.BLOCK_VERSION | default "false" }} {{- else }} {{- tpl .Values.global.node.nodeConfig.blockVersion . }} {{- end }} {{- end }} +{{- define "consensusNode.txSourceUrl" -}} + {{- if eq .Values.consensusNodeConfig.enabled false }} + {{- (lookup "v1" "ConfigMap" .Release.Namespace (include "consensusNode.nodeConfig.configMap.name" .)).data.TX_SOURCE_URL | default "false" }} + {{- else }} + {{- tpl .Values.global.node.nodeConfig.txSourceUrl . }} + {{- end }} +{{- end }} + {{/* Mobilecoin Network monitoring labels */}} {{- define "consensusNode.mobileCoinNetwork.network" -}} {{- if eq .Values.mcCoreCommonConfig.enabled false }} diff --git a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml index 05eec2a49a..5cdec76462 100644 --- a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml +++ b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml @@ -46,13 +46,14 @@ spec: {{- toYaml .Values.node.tolerations | nindent 6 }} imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 6 }} + {{- if .Values.node.initContainers }} initContainers: {{- tpl (toYaml .Values.node.initContainers) . | nindent 6 }} + {{- end }} containers: - name: node image: '{{ .Values.node.image.org | default .Values.image.org }}/{{ .Values.node.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' imagePullPolicy: Always - command: [ '/usr/bin/supervisord' ] ports: - name: cns-client containerPort: 3223 @@ -72,8 +73,16 @@ spec: command: - '/usr/local/bin/grpc_health_probe' - '-addr=:8443' - failureThreshold: 30 + failureThreshold: 2 + periodSeconds: 10 + startupProbe: + exec: + command: + - '/usr/local/bin/grpc_health_probe' + - '-addr=:8443' + failureThreshold: 120 periodSeconds: 30 + initialDelaySeconds: 30 envFrom: - secretRef: name: {{ include "consensusNode.ledgerDistribution.secret.name" . }} @@ -81,6 +90,8 @@ spec: name: {{ include "consensusNode.msgSignerKey.secret.name" . }} - secretRef: name: ias + - configMapRef: + name: {{ include "consensusNode.nodeConfig.configMap.name" . }} env: - name: PATH value: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64' @@ -88,19 +99,6 @@ spec: value: '1' - name: RUST_LOG value: 'info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn' - - name: LOCAL_NODE_ID - valueFrom: - configMapKeyRef: - name: {{ include "consensusNode.nodeConfig.configMap.name" . }} - key: peerHostname - # Responder ID will need to be made variable when we fix load balanced consensus nodes. - - name: CLIENT_RESPONDER_ID - valueFrom: - configMapKeyRef: - name: {{ include "consensusNode.nodeConfig.configMap.name" . }} - key: clientHostname - - name: MC_LOG_EXTRA_CONTEXT - value: 'mc.local_node_id=$(LOCAL_NODE_ID)' - name: CONSENSUS_SERVICE_SENTRY_DSN valueFrom: configMapKeyRef: @@ -116,17 +114,9 @@ spec: configMapKeyRef: name: mobilecoin-network key: network - - name: MC_BLOCK_VERSION - valueFrom: - configMapKeyRef: - name: {{ include "consensusNode.nodeConfig.configMap.name" . }} - key: blockVersion - # This file is generated at consensus node startup and should be persistent as long as its on the same node. - - name: SEALED_BLOCK_SIGNING_KEY - value: /sealed-signing-key/block-signing-key volumeMounts: - name: sealed-signing-key - mountPath: /sealed-signing-key + mountPath: /sealed - name: aesm-socket-dir mountPath: /var/run/aesmd - name: config-dir @@ -138,9 +128,6 @@ spec: - name: node-cert mountPath: /certs readOnly: true - - name: supervisor-conf - mountPath: /etc/supervisor/conf.d - readOnly: true resources: {{- toYaml .Values.node.resources | nindent 10}} {{- if eq .Values.jaegerTracing.enabled true }} @@ -196,19 +183,6 @@ spec: - name: node-cert secret: secretName: {{ include "consensusNode.fullname" . }}-internal-tls - - name: supervisor-conf - projected: - sources: - - configMap: - name: {{ include "consensusNode.fullname" . }}-supervisor-daemon - - configMap: - name: {{ include "consensusNode.fullname" . }}-supervisor-sgx - - configMap: - name: {{ include "consensusNode.fullname" . }}-supervisor-consensus - - configMap: - name: {{ include "consensusNode.fullname" . }}-supervisor-ledger-distribution - - configMap: - name: {{ include "consensusNode.fullname" . }}-supervisor-admin-http-gw - name: ledger-db-dir {{- if eq .Values.node.persistence.enabled true }} persistentVolumeClaim: diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-admin-gateway-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-admin-gateway-configmap.yaml deleted file mode 100644 index a42cd3261d..0000000000 --- a/.internal-ci/helm/consensus-node/templates/supervisor-admin-gateway-configmap.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2018-2022 The MobileCoin Foundation -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "consensusNode.fullname" . }}-supervisor-admin-http-gw - labels: - {{- include "consensusNode.labels" . | nindent 4 }} -data: - admin_http_gw.conf: | - [program:mc-admin-http-gateway] - priority=200 - command=/usr/bin/mc-admin-http-gateway - --listen-host 0.0.0.0 - --listen-port 8000 - --admin-uri insecure-mca://127.0.0.1:8001/ - - stdout_logfile=/dev/fd/1 - stdout_logfile_maxbytes=0 - stderr_logfile=/dev/fd/2 - stderr_logfile_maxbytes=0 - autorestart=true diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-consensus-service-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-consensus-service-configmap.yaml deleted file mode 100644 index c7cbf2f144..0000000000 --- a/.internal-ci/helm/consensus-node/templates/supervisor-consensus-service-configmap.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2018-2022 The MobileCoin Foundation -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "consensusNode.fullname" . }}-supervisor-consensus - labels: - {{- include "consensusNode.labels" . | nindent 4 }} -data: - consensus-service-node.conf: | - [program:consensus-service] - priority=100 - environment=MC_SENTRY_DSN="%(ENV_CONSENSUS_SERVICE_SENTRY_DSN)s" - command=/usr/bin/consensus-service - --client-responder-id "%(ENV_CLIENT_RESPONDER_ID)s:443" - --peer-responder-id "%(ENV_LOCAL_NODE_ID)s:443" - --peer-listen-uri=insecure-mcp://0.0.0.0:8443/ - --admin-listen-uri=insecure-mca://127.0.0.1:8001/ - --network /config/network.toml - --tokens /config/tokens.signed.json - --ledger-path /ledger - --ias-spid "%(ENV_IAS_SPID)s" - --ias-api-key "%(ENV_IAS_API_KEY)s" - --msg-signer-key "%(ENV_NODE_SIGNER_KEY)s" - --sealed-block-signing-key "%(ENV_SEALED_BLOCK_SIGNING_KEY)s" - --scp-debug-dump /scp-debug-dump - - stdout_logfile=/dev/fd/1 - stdout_logfile_maxbytes=0 - stderr_logfile=/dev/fd/2 - stderr_logfile_maxbytes=0 - autorestart=true diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-daemon-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-daemon-configmap.yaml deleted file mode 100644 index 0cef1a4458..0000000000 --- a/.internal-ci/helm/consensus-node/templates/supervisor-daemon-configmap.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2018-2022 The MobileCoin Foundation -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "consensusNode.fullname" . }}-supervisor-daemon - labels: - {{- include "consensusNode.labels" . | nindent 4 }} -data: - supervisor.conf: | - [supervisord] - nodaemon=true diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-ledger-distribution-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-ledger-distribution-configmap.yaml deleted file mode 100644 index 7559883cae..0000000000 --- a/.internal-ci/helm/consensus-node/templates/supervisor-ledger-distribution-configmap.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2018-2022 The MobileCoin Foundation -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "consensusNode.fullname" . }}-supervisor-ledger-distribution - labels: - {{- include "consensusNode.labels" . | nindent 4 }} -data: - ledger_dist.conf: | - [program:ledger-distribution] - priority=20 - environment=MC_SENTRY_DSN="%(ENV_LEDGER_DISTRIBUTION_SENTRY_DSN)s" - command=/usr/bin/ledger-distribution - --dest "%(ENV_LEDGER_DISTRIBUTION_S3_PATH)s" - --ledger-path /ledger - --state-file /ledger/.distribution-state - --start-from "%(ENV_LEDGER_DISTRIBUTION_START_FROM)s" - - stdout_logfile=/dev/fd/1 - stdout_logfile_maxbytes=0 - stderr_logfile=/dev/fd/2 - stderr_logfile_maxbytes=0 - autorestart=true diff --git a/.internal-ci/helm/consensus-node/templates/supervisor-sgx-configmap.yaml b/.internal-ci/helm/consensus-node/templates/supervisor-sgx-configmap.yaml deleted file mode 100644 index 8734bf3e5d..0000000000 --- a/.internal-ci/helm/consensus-node/templates/supervisor-sgx-configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2018-2022 The MobileCoin Foundation -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "consensusNode.fullname" . }}-supervisor-sgx - labels: - {{- include "consensusNode.labels" . | nindent 4 }} -data: - sgx.conf: | - [program:aesm-service] - priority=10 - command=/opt/intel/sgx-aesm-service/aesm/aesm_service --no-daemon - environment=AESM_PATH="/opt/intel/sgx-aesm-service/aesm",LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" - - stdout_logfile=/dev/null - stderr_logfile=/dev/null - autorestart=true diff --git a/.internal-ci/helm/consensus-node/values.yaml b/.internal-ci/helm/consensus-node/values.yaml index 4abc298a7a..88e892ec17 100644 --- a/.internal-ci/helm/consensus-node/values.yaml +++ b/.internal-ci/helm/consensus-node/values.yaml @@ -39,6 +39,9 @@ consensusNodeConfig: hostname: '' peer: hostname: '' + txSourceUrl: '' + msgSignerKey: + privateKey: '' ### Enable to launch child chart to create core common configMaps and secrets. # See helm/mc-core-common-config/values.yaml for config details. @@ -85,58 +88,7 @@ node: value: 'true' effect: NoSchedule - initContainers: - - name: copy-ledger-from-container - image: '{{ .Values.node.image.org | default .Values.image.org }}/{{ .Values.node.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' - imagePullPolicy: Always - env: - - name: INITIAL_KEYS_SEED - valueFrom: - secretKeyRef: - name: sample-keys-seeds - key: INITIAL_KEYS_SEED - optional: true - command: [ '/bin/bash' ] - # CBB 1.2+ - convert to using MNEMONIC keys - args: - - -c - - | - set -e - if [ ! -f /ledger/data.mdb ]; then - if [[ -n "${INITIAL_KEYS_SEED}" ]]; then - echo "INITIAL_KEYS_SEED found - populating origin data" - export INITIALIZE_LEDGER="true" - /usr/local/bin/generate_origin_data.sh - cp /tmp/sample_data/ledger/data.mdb /ledger - elif [ -f /var/lib/mobilecoin/origin_data/data.mdb ]; then - echo "Copying ledger /var/lib/mobilecoin/origin_data/data.mdb to /ledger" - cp /var/lib/mobilecoin/origin_data/data.mdb /ledger - else - echo "INITIAL_KEYS_SEED not set and cannot find origin ledger file" - exit 1 - fi - else - echo "Ledger /ledger/data.mdb already exists" - fi - volumeMounts: - - name: ledger-db-dir - mountPath: /ledger - - name: migrate-ledger - image: '{{ .Values.node.image.org | default .Values.image.org }}/{{ .Values.node.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}' - imagePullPolicy: Always - command: [ '/bin/bash' ] - args: - - -c - - | - set -e - if [[ -f "/ledger/data.mdb" ]] - then - cp /ledger/data.mdb /ledger/data.mdb.bak - /usr/bin/mc-ledger-migration --ledger-db /ledger - fi - volumeMounts: - - name: ledger-db-dir - mountPath: /ledger + initContainers: [] persistence: enabled: true diff --git a/.internal-ci/helm/mc-core-common-config/templates/ias-secret.yaml b/.internal-ci/helm/mc-core-common-config/templates/ias-secret.yaml index 6367979026..0763296f3f 100644 --- a/.internal-ci/helm/mc-core-common-config/templates/ias-secret.yaml +++ b/.internal-ci/helm/mc-core-common-config/templates/ias-secret.yaml @@ -9,3 +9,5 @@ type: Opaque stringData: IAS_API_KEY: {{ .Values.ias.key | quote }} IAS_SPID: {{ .Values.ias.spid | quote }} + MC_IAS_API_KEY: {{ .Values.ias.key | quote }} + MC_IAS_SPID: {{ .Values.ias.spid | quote }} diff --git a/.internal-ci/helm/mc-core-dev-env-setup/values.yaml b/.internal-ci/helm/mc-core-dev-env-setup/values.yaml index b02082c7d7..c36958ac63 100644 --- a/.internal-ci/helm/mc-core-dev-env-setup/values.yaml +++ b/.internal-ci/helm/mc-core-dev-env-setup/values.yaml @@ -74,6 +74,7 @@ consensusNodeConfig1: hostname: '{{ printf "node1.%s.development.mobilecoin.com" .Release.Namespace }}' peer: hostname: '{{ printf "peer1.%s.development.mobilecoin.com" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node1.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' consensusNodeConfig2: enabled: true @@ -83,6 +84,7 @@ consensusNodeConfig2: hostname: '{{ printf "node2.%s.development.mobilecoin.com" .Release.Namespace }}' peer: hostname: '{{ printf "peer2.%s.development.mobilecoin.com" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node2.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' consensusNodeConfig3: enabled: true @@ -92,6 +94,7 @@ consensusNodeConfig3: hostname: '{{ printf "node3.%s.development.mobilecoin.com" .Release.Namespace }}' peer: hostname: '{{ printf "peer3.%s.development.mobilecoin.com" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node3.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' consensusNodeConfig4: enabled: true @@ -101,6 +104,7 @@ consensusNodeConfig4: hostname: '{{ printf "node4.%s.development.mobilecoin.com" .Release.Namespace }}' peer: hostname: '{{ printf "peer4.%s.development.mobilecoin.com" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node4.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' consensusNodeConfig5: enabled: true @@ -110,6 +114,7 @@ consensusNodeConfig5: hostname: '{{ printf "node5.%s.development.mobilecoin.com" .Release.Namespace }}' peer: hostname: '{{ printf "peer5.%s.development.mobilecoin.com" .Release.Namespace }}' + txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node5.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' fogIngestConfig: enabled: true From bd94bf25105b13c3fe9cc3914d38a6bb400f0c24 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Wed, 15 Jun 2022 08:05:08 -0500 Subject: [PATCH 35/77] update manual build and trigger CD build (#2143) --- .../util/manual_republish_existing_build.sh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.internal-ci/util/manual_republish_existing_build.sh b/.internal-ci/util/manual_republish_existing_build.sh index bd5971fd44..ab6d064759 100755 --- a/.internal-ci/util/manual_republish_existing_build.sh +++ b/.internal-ci/util/manual_republish_existing_build.sh @@ -12,14 +12,14 @@ echo "no foot-guns, check the tag vars and remove this exit 0 to use!" exit 0 source_org=mobilecoin -source_tag=demo-v20220307170316 +source_tag=v1.2.1-dev push_org=mobilecoin -push_tag=v1.1.3-dev +push_tag=v1.2.2-dev images=(bootstrap-tools fogingest fog-ledger fogreport fogview go-grpc-gateway mobilecoind node_hw fog-test-client) -charts=(consensus-node consensus-node-config fog-ingest fog-ingest-config fog-services fog-services-config mc-core-common-config mc-core-dev-env-setup mobilecoind ) +charts=(consensus-node consensus-node-config fog-ingest fog-ingest-config fog-services fog-services-config mc-core-common-config mc-core-dev-env-setup mobilecoind) for i in "${images[@]}" do @@ -35,8 +35,15 @@ docker cp "bootstrap-tools:/usr/local/bin/generate-sample-ledger" ./ docker cp "bootstrap-tools:/usr/local/bin/sample-keys" ./ docker cp "bootstrap-tools:/usr/local/bin/fog-distribution" ./ docker cp "bootstrap-tools:/usr/local/bin/fog_ingest_client" ./ -# docker cp "bootstrap-tools:/usr/local/bin/mc-consensus-mint-client" ./ -# docker cp "bootstrap-tools:/usr/local/bin/mc-util-seeded-ed25519-key-gen" ./ +docker cp "bootstrap-tools:/usr/local/bin/mc-consensus-mint-client" ./ +docker cp "bootstrap-tools:/usr/local/bin/mc-util-seeded-ed25519-key-gen" ./ +docker cp "bootstrap-tools:/usr/local/bin/fog-report-cli" ./ +docker cp "bootstrap-tools:/usr/local/bin/read-pubfile" ./ +docker cp "bootstrap-tools:/usr/local/bin/mc-util-grpc-token-generator" ./ +docker cp "bootstrap-tools:/usr/local/bin/test_client" ./ +docker cp "mobilecoind:/usr/bin/mc-mint-auditor" ./ +docker cp "mobilecoind:/usr/bin/mobilecoind-json" ./ +docker cp "mobilecoind:/enclaves/libingest-enclave.css" ./ docker cp "fog-ledger:/usr/bin/libledger-enclave.signed.so" ./ docker cp "fog-ledger:/usr/bin/ledger_server" ./ docker cp "fog-ledger:/usr/bin/mobilecoind" ./ @@ -53,8 +60,6 @@ docker cp "node_hw:/usr/bin/consensus-service" ./ docker cp "node_hw:/usr/bin/ledger-distribution" ./ docker cp "node_hw:/usr/bin/ledger-from-archive" ./ docker cp "node_hw:/usr/bin/libconsensus-enclave.signed.so" ./ -docker cp "fog-test-client:/usr/local/bin/test_client" ./ -docker cp "fog-test-client:/usr/local/bin/mc-util-grpc-token-generator" ./ popd || exit 1 for i in "${images[@]}" From b3eb1e384fd4dfe5b60fb263c17c8009fd6666ea Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 15 Jun 2022 09:17:02 -0700 Subject: [PATCH 36/77] Bump all versions to 1.2.2, update changelog. (#2111) --- CHANGELOG.md | 15 +- Cargo.lock | 322 ++++++++++---------- account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- common/Cargo.toml | 2 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 +++--- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 +++---- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 +++--- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 +++---- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 2 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 2 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 177 files changed, 543 insertions(+), 532 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49bd5f9d5b..dc4761032d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The crates in this repository do not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) at this time. -## [1.2.1] - 2022-06-06 +## [1.2.2] - 2022-06-09 + +### Changed + +- Update CI deployments to use zerossl instead of letsencrypt + + +## [1.2.1] - YANKED + +[This was never released] ### Changed @@ -19,7 +28,9 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem - Fix panic when consensus service is configured for multiple tokens but still running in MOB-only block-version 0 mode. -## [1.2.0] - 2022-06-03 +## [1.2.0] - YANKED + +[This was never released] ### Added diff --git a/Cargo.lock b/Cargo.lock index 53280615c3..18fea28111 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2015,7 +2015,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "cbindgen", @@ -2197,7 +2197,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "criterion", "curve25519-dalek", @@ -2225,7 +2225,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "1.2.1" +version = "1.2.2" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2241,7 +2241,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "grpcio", @@ -2256,7 +2256,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "anyhow", @@ -2293,7 +2293,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "bs58", "cargo-emit", @@ -2329,7 +2329,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "aes-gcm", @@ -2354,7 +2354,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "cargo-emit", @@ -2372,7 +2372,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "bincode", @@ -2404,7 +2404,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2417,7 +2417,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2437,7 +2437,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -2448,7 +2448,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2458,7 +2458,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2483,7 +2483,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.1" +version = "1.2.2" dependencies = [ "backtrace", "binascii", @@ -2520,7 +2520,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "cookie", @@ -2549,7 +2549,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2560,7 +2560,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "futures", @@ -2581,7 +2581,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2606,7 +2606,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "hex", @@ -2627,7 +2627,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2635,7 +2635,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "hex", @@ -2671,7 +2671,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2684,7 +2684,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2706,7 +2706,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2735,7 +2735,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "1.2.1" +version = "1.2.2" dependencies = [ "crossbeam-channel", "maplit", @@ -2758,7 +2758,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "mc-common", @@ -2770,7 +2770,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "chrono", @@ -2832,7 +2832,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "clap 3.1.18", @@ -2857,7 +2857,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2877,7 +2877,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "digest 0.10.3", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2906,7 +2906,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.1" +version = "1.2.2" dependencies = [ "proc-macro2", "quote", @@ -2915,7 +2915,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2923,7 +2923,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2932,7 +2932,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2940,7 +2940,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "blake2", "digest 0.10.3", @@ -2949,7 +2949,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "curve25519-dalek", @@ -2982,7 +2982,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "displaydoc", @@ -2996,7 +2996,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3010,7 +3010,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "aes-gcm", @@ -3031,7 +3031,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3042,7 +3042,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3055,7 +3055,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3067,7 +3067,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3078,7 +3078,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3089,7 +3089,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "displaydoc", @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3153,7 +3153,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "cookie", @@ -3177,7 +3177,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "1.2.1" +version = "1.2.2" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3216,7 +3216,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "criterion", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -3268,7 +3268,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3276,7 +3276,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3309,7 +3309,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3322,7 +3322,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "dirs", @@ -3379,7 +3379,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.1" +version = "1.2.2" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3395,7 +3395,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "grpcio", @@ -3416,7 +3416,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3445,7 +3445,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -3463,7 +3463,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3471,7 +3471,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3507,7 +3507,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3560,7 +3560,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3576,7 +3576,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "grpcio", @@ -3605,14 +3605,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3623,7 +3623,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "aligned-cmov", @@ -3640,7 +3640,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "lazy_static", "mc-common", @@ -3648,7 +3648,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -3700,7 +3700,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "futures", @@ -3719,7 +3719,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-util-serial", "prost", @@ -3728,7 +3728,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "binascii", @@ -3750,7 +3750,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "grpcio", @@ -3767,7 +3767,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3803,7 +3803,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3813,7 +3813,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-account-keys", @@ -3831,7 +3831,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3839,7 +3839,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3885,7 +3885,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-account-keys", @@ -3906,7 +3906,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3917,7 +3917,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -3932,7 +3932,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "1.2.1" +version = "1.2.2" dependencies = [ "chrono", "clap 3.1.18", @@ -3965,7 +3965,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3996,7 +3996,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4027,7 +4027,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.1" +version = "1.2.2" dependencies = [ "crc", "displaydoc", @@ -4047,7 +4047,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-common", "mc-util-uri", @@ -4055,7 +4055,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "1.2.1" +version = "1.2.2" dependencies = [ "grpcio", "mc-attest-core", @@ -4075,7 +4075,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "criterion", @@ -4110,7 +4110,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -4128,7 +4128,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4136,7 +4136,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4158,7 +4158,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4171,7 +4171,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "grpcio", @@ -4190,7 +4190,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-account-keys", @@ -4213,7 +4213,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4263,7 +4263,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "lazy_static", @@ -4289,7 +4289,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "dirs", @@ -4311,7 +4311,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "mc-api", @@ -4322,7 +4322,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4335,7 +4335,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "1.2.1" +version = "1.2.2" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4366,7 +4366,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4399,7 +4399,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "futures", @@ -4413,7 +4413,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4477,7 +4477,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "futures", @@ -4495,7 +4495,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "grpcio", @@ -4570,7 +4570,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "1.2.1" +version = "1.2.2" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4602,7 +4602,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "1.2.1" +version = "1.2.2" dependencies = [ "grpcio", "hex", @@ -4625,7 +4625,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cc", "lazy_static", @@ -4635,7 +4635,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4643,7 +4643,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4652,7 +4652,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4660,7 +4660,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4669,21 +4669,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -4694,7 +4694,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -4710,7 +4710,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4720,18 +4720,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-urts" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-common", "mc-sgx-build", @@ -4742,7 +4742,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "hex", "mc-account-keys", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-account-keys", "mc-api", @@ -4764,7 +4764,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-util-test-vector", "serde", @@ -4773,7 +4773,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "1.2.1" +version = "1.2.2" dependencies = [ "hex", "mc-account-keys", @@ -4788,7 +4788,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "1.2.1" +version = "1.2.2" dependencies = [ "hex", "mc-account-keys", @@ -4810,7 +4810,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "bulletproofs-og", @@ -4852,7 +4852,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4869,7 +4869,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "1.2.1" +version = "1.2.2" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4896,7 +4896,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "hex", @@ -4905,7 +4905,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4921,7 +4921,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4929,7 +4929,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "json", @@ -4937,7 +4937,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "displaydoc", @@ -4948,7 +4948,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cc", @@ -4967,7 +4967,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "binascii", @@ -4979,18 +4979,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-util-from-random" -version = "1.2.1" +version = "1.2.2" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "hex", @@ -5009,7 +5009,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "clap 3.1.18", @@ -5043,7 +5043,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "grpcio", @@ -5054,7 +5054,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "hex", @@ -5065,11 +5065,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-util-keyfile" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "clap 3.1.18", @@ -5097,7 +5097,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5107,7 +5107,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "1.2.1" +version = "1.2.2" dependencies = [ "proc-macro2", "quote", @@ -5116,7 +5116,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "1.2.1" +version = "1.2.2" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5124,7 +5124,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "1.2.1" +version = "1.2.2" dependencies = [ "chrono", "grpcio", @@ -5137,7 +5137,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "1.2.1" +version = "1.2.2" dependencies = [ "itertools", "mc-sgx-css", @@ -5145,7 +5145,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "generic-array", "prost", @@ -5155,7 +5155,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "hex", @@ -5168,7 +5168,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.1" +version = "1.2.2" dependencies = [ "prost", "serde", @@ -5177,7 +5177,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5188,7 +5188,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "itertools", @@ -5202,7 +5202,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "1.2.1" +version = "1.2.2" dependencies = [ "serde", "serde_json", @@ -5210,7 +5210,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "1.2.1" +version = "1.2.2" dependencies = [ "proc-macro2", "quote", @@ -5219,7 +5219,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "displaydoc", @@ -5237,7 +5237,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "1.2.1" +version = "1.2.2" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5281,7 +5281,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 8b8a6a0e5e..73c7e38a66 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index 72c4c214ac..a084160496 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index 153201f0f2..d198ecb56f 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index bf5c3ed984..2edc6fd084 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/api/Cargo.toml b/api/Cargo.toml index 070ee66bec..533acb6d12 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index 04d40ddab5..d0f1799f18 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index 50a00d1ac2..fa62084037 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index d32a3e75e0..8d7cb8bb5e 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index ac59b0e24e..1d6fa33784 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index cd6e675aac..840aaa3fd8 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index 50117d2662..5066410106 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index 0c699be3dd..6b444b9486 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index 8f5480c488..347f1048ec 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/common/Cargo.toml b/common/Cargo.toml index 8d8dbeafd8..535f196dd9 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/Cargo.toml b/connection/Cargo.toml index 148d74da58..3f65176f8a 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index 4fd998333c..de6cf3daec 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index 46955e7570..b4e883ae73 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index 64a3316e89..2b75394895 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index 315cafedd7..d93dc80848 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index 42873b26c1..2b61303028 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index 8922280334..cc76946aa3 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index 00adeae2f3..779feb61b4 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index 87fbd89b70..4898d5688c 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index 749ec29a52..058eb2b2ef 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.1" +version = "1.2.2" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-build" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-enclave-id" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-transaction-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.1" +version = "1.2.2" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.1" +version = "1.2.2" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index b4d20f6862..9131a73fff 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index 2c1d648f15..8b54e32524 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index 27653e3bb3..b40a4a98dc 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index ed992cceba..0bfe5f345e 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index 187ae2553c..75d4fbc265 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index 38fb37fcd5..c9dc969351 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index 3e05797dd1..e13a484ff6 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index aa8124e47d..86073b1305 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index 7c0b4bd6a2..7e1499b20b 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index 2c6191b241..2ec2dcbebb 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index 4486fe2750..af3b2109e1 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index 7b84bd48ea..938bb2c30f 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index 0df9250bba..deb2de5243 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index 0693d5fd75..66b6da81e4 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index 51b28860e0..0fce90e375 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index fcf5a4dfcd..f3ae9938e1 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index a44b5c537f..7f198fd8ec 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index 38d2ea71cf..ed02612fe0 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index e2cc466916..6d457c7897 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index 3bd1b35cfc..d5b69416db 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 254cb12013..69b228e606 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index de3e75e832..b3aa7177d0 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index dab52f7375..1ef297e055 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index d0dc462f15..bf3ef5dec4 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index 59b470577f..75924f0a3b 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index af8f645262..59d2d05f05 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 6ed4aa3332..71cc2579a7 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index 5dcc14fc45..14e925d56f 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index afdef7eaba..21a8546b17 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index cc9cb97a9c..ed3b14191f 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index fe8af01230..645cfd74a9 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index a23f5bb9ba..9554a1169c 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 1a9f3d4c6c..6af26b86c2 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.1" +version = "1.2.2" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.1" +version = "1.2.2" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.1" +version = "1.2.2" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-build" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-transaction-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.1" +version = "1.2.2" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.1" +version = "1.2.2" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index 7d521d6011..3067fba2b8 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index 34f0e27a5f..a849303fbd 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index d0b738b2fc..1069863976 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "1.2.1" +version = "1.2.2" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index 80013beff9..e4ec348e79 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index dff459d487..c83342d38b 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index eb0a82308e..2383cfd452 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index d432daa602..b1483ff48f 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index 8f162af6cb..4652bc5442 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index 7ea5936f69..f17c0c81fb 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index fe066b3cb0..7a16a8b75c 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.1" +version = "1.2.2" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.1" +version = "1.2.2" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.1" +version = "1.2.2" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-build" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-transaction-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.1" +version = "1.2.2" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.1" +version = "1.2.2" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index 83555f6ecc..b37b82d026 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index 7fa6b7c63a..a352a487c8 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index 32c1efac3d..952d70d93b 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "1.2.1" +version = "1.2.2" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index 35ff9bfb5f..5fe9212b61 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index 0f4a5d71f7..7baf1cd52a 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index 8f2947e05a..13b70f7436 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index a5bbaf835d..14cfb2643b 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index de315fa0ac..53ff25b33a 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 955c6c04ba..012c850e60 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index 24ed86298e..12e759858c 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index 703a10d64b..0469931f46 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index aadc1acc10..87e10343bf 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index 2e23f59a1c..2fee842c60 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index c14f37012c..fcadb82f44 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index 2211750aa4..68b96271c2 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index 55defeb920..067d132a2b 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "1.2.1" +version = "1.2.2" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index 45261c76f4..1539e654d4 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index 610f803033..e5c4522fb5 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index 370989389e..29acfc50fc 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index f3db139f85..ac733c99d3 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index d2e44c334d..ba5d7fb696 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index 2f8b36b1b5..4ea7c8b5cc 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index ca62aa5e68..823ad619b9 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "1.2.1" +version = "1.2.2" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 8712d326ef..269b086aca 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index 5f4eed6dde..293b9cfef7 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index 27851fa755..c00cc10d89 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index 943df1faa9..87353b5d02 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index 7001247c25..b8ecbd3378 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index e754bf903c..21171e81f6 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index eb770de11d..453014a099 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index 20fe843279..f2b9874601 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index a3adb12b69..097ba7edab 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index 43fdd90efc..277f6607b5 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index 15eed45db2..79ef42c064 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.1" +version = "1.2.2" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.1" +version = "1.2.2" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.1" +version = "1.2.2" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.1" +version = "1.2.2" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-build" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.1" +version = "1.2.2" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.1" +version = "1.2.2" [[package]] name = "mc-transaction-core" -version = "1.2.1" +version = "1.2.2" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.1" +version = "1.2.2" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.1" +version = "1.2.2" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.1" +version = "1.2.2" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.1" +version = "1.2.2" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.1" +version = "1.2.2" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.1" +version = "1.2.2" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index be92143b2d..6f06400592 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index 592c89b418..4cea093221 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index 5653adc7b2..8fd9d6b503 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index efdfb52675..ffb68e833e 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index 7d0deb1dc9..b65770134c 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index a5d6a6f43f..6734c7969f 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index 9b0dd141e6..a3875fad1b 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index 37a6325396..acea3a820b 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index 2d6005419c..319600b401 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index 0a4a692ab0..debb090fdd 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index 8c0b3bbf93..fe4c93e6fe 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index 6d2ed6172d..a1d02c1995 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index 1afab3ea81..20763373b9 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index ec065f3d0d..6bca63f1e1 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index c9be196eda..1e5f57248d 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/peers/Cargo.toml b/peers/Cargo.toml index 71672e1670..ce9c8cad99 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index 3fb49dec3d..67e2b62c5b 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index 40e6e41754..afe5614414 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index a90bd04271..0803ea11fa 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index a4bf07bdc2..5aeb6b61bb 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index cb972a614d..5a4d948460 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index 0f613f7ac5..9a4f40e7d5 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index f74e1081c4..35b0d61168 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index b32b00a10c..28243aef92 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index 0d0f00caa5..1705c274b7 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index cb52bf6a48..ac1bf54e41 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index 0ca0d01ae3..a36c57fdc1 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index 0fba868145..5af54ffb09 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index ca7fc81159..73ca4e2919 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index ac5f0e1b0e..9bd5190d20 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index 5df314becb..de58902c4f 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index 489a71505b..a28691fb8f 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index bd02f32f84..d660933ba0 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index c2c4a6bb79..0e6bb1db5b 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index ca1983b9ec..c6e313b3b6 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "1.2.1" +version = "1.2.2" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index d02e5244b4..fef4dea234 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index 4febd30469..0290789ad4 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index b8d0219962..72c7b80205 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index f175b329ad..be343e1a3d 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index 788f573e39..e196f7a7f9 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index aeec31acfb..f76f6fb2ae 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index ab5a851162..ddb9c8d784 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 674075e527..5ac8d15dd9 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index 8ad8369b7f..b5629af94f 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index 3728ce80b5..a2b8947164 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index 8e7dd690d5..4e44b117ba 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index e2c07974ca..ab6e6a95a4 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index 24c104dd71..2f2df6e477 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index 062cf11bf1..219bf1da2d 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index ccc733c612..d42de57ede 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index 75700ee6c5..adebdea788 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index cc9bf89f78..389044b84f 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index 6e82227b5d..afe8f28a57 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index bf7612258d..81fd576ace 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index edc9d3ceff..9cc121a758 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index e66add4dc4..bb48defc8f 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index 349267b428..72a9d6122c 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 4b381f7531..9a96489370 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index e19d0bd84f..922bcf88b5 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index 5ac11a5256..b9e6f0bb64 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index 8644fed3ca..261a7b9171 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index b8d089e98f..79c4e5a5ee 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index 48b1255fbe..7869f93ce3 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index 462dbc8e42..8baba5cf2c 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index 343e72d3da..1cbafb045f 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index f8df89eaf6..8a7af302f6 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index 47f793a875..c068a93a39 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index 28e842455b..30cf8d4d3b 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index 34f5f04aa2..491b0555f6 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index e8f8fd8ae3..d3c21d422d 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index 1f880b446c..4b9e250427 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index 32f230e4d6..91ea310279 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index defc90bfcb..9e22307b30 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index af8ade1dbf..83dfd023a0 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "1.2.1" +version = "1.2.2" authors = ["MobileCoin"] edition = "2018" From 6e39ac5f4395066916de79d55c4c1f7a0d970f7b Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Thu, 16 Jun 2022 11:33:12 -0500 Subject: [PATCH 37/77] Fix OMAP settings and adjust probe timings. (#2144) * fix omap settings, update probe timings * pin aesm/epid packages --- .../mobilecoin-workflow-dev-deploy.yaml | 2 ++ .internal-ci/docker/Dockerfile.fog-ledger | 2 +- .internal-ci/docker/Dockerfile.fogview | 2 +- .internal-ci/docker/Dockerfile.runtime-base | 26 ++++++++++++++++--- .../templates/fog-ingest-statefulset.yaml | 1 + .../helm/fog-services-config/values.yaml | 4 +-- .../templates/fog-ledger-statefulset.yaml | 6 +++-- .../templates/fog-report-deployment.yaml | 1 + .../templates/fog-view-deployment.yaml | 6 ++--- .internal-ci/helm/fog-services/values.yaml | 2 ++ 10 files changed, 40 insertions(+), 12 deletions(-) diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml index 2f68f299bc..1544788456 100644 --- a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -375,9 +375,11 @@ jobs: chart_name: fog-services chart_version: ${{ inputs.version }} chart_wait_timeout: 10m + # Set orderedReady for compatibility with 1.1.3 chart - remove after 1.2.x chart_set: | --set=image.org=${{ inputs.docker_image_org }} --set=global.certManagerClusterIssuer=zerossl-prod-http + --set=fogLedger.podManagementPolicy=OrderedReady release_name: fog-services namespace: ${{ inputs.namespace }} rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} diff --git a/.internal-ci/docker/Dockerfile.fog-ledger b/.internal-ci/docker/Dockerfile.fog-ledger index 77eb27228e..7094dccfa9 100644 --- a/.internal-ci/docker/Dockerfile.fog-ledger +++ b/.internal-ci/docker/Dockerfile.fog-ledger @@ -32,4 +32,4 @@ EXPOSE 8000 EXPOSE 3228 # App Defaults -ENV OMAP_CAPACITY=2097152 +ENV MC_OMAP_CAPACITY=4194304 diff --git a/.internal-ci/docker/Dockerfile.fogview b/.internal-ci/docker/Dockerfile.fogview index 35e369b559..534b75b197 100644 --- a/.internal-ci/docker/Dockerfile.fogview +++ b/.internal-ci/docker/Dockerfile.fogview @@ -30,4 +30,4 @@ EXPOSE 8000 EXPOSE 3225 # App Defaults -ENV OMAP_CAPACITY=2097152 +ENV MC_OMAP_CAPACITY=4194304 diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base index 2c09db8903..ea56da8fce 100644 --- a/.internal-ci/docker/Dockerfile.runtime-base +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -29,12 +29,32 @@ RUN echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-ke ENV AESM_PATH="/opt/intel/sgx-aesm-service/aesm" ENV LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" -# Install packages +# Since we are specifying versions (thanks intel), we need to install all the deps. +# libsgx-ae-epid libsgx-ae-le libsgx-ae-pce +# libsgx-aesm-epid-plugin libsgx-aesm-launch-plugin libsgx-aesm-pce-plugin +# libsgx-enclave-common libsgx-epid libsgx-launch libsgx-pce-logic libsgx-urts +# sgx-aesm-service +# Use `apt show -a sgx-aesm-service` to find version +ENV AESM_VERSION=2.16.100.4-focal1 +# Use `apt show -a libsgx-pce-logic` to find the version thats compatible with aesm. +ENV PCE_LOGIC_VERSION=1.13.100.4-focal1 + +# Install packages RUN apt-get update \ && apt-get install -y \ filebeat \ - sgx-aesm-service \ - libsgx-epid \ + sgx-aesm-service=${AESM_VERSION} \ + libsgx-epid=${AESM_VERSION} \ + libsgx-ae-epid=${AESM_VERSION} \ + libsgx-ae-le=${AESM_VERSION} \ + libsgx-ae-pce=${AESM_VERSION} \ + libsgx-aesm-epid-plugin=${AESM_VERSION} \ + libsgx-aesm-launch-plugin=${AESM_VERSION} \ + libsgx-aesm-pce-plugin=${AESM_VERSION} \ + libsgx-enclave-common=${AESM_VERSION} \ + libsgx-launch=${AESM_VERSION} \ + libsgx-urts=${AESM_VERSION} \ + libsgx-pce-logic=${PCE_LOGIC_VERSION} \ && apt-get clean \ && rm -r /var/lib/apt/lists diff --git a/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml b/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml index 0f3b95f7e8..968eae98b2 100644 --- a/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml +++ b/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml @@ -6,6 +6,7 @@ metadata: labels: {{- include "fogIngest.labels" . | nindent 4 }} spec: + podManagementPolicy: Parallel replicas: {{ .Values.fogIngest.replicaCount }} selector: matchLabels: diff --git a/.internal-ci/helm/fog-services-config/values.yaml b/.internal-ci/helm/fog-services-config/values.yaml index 66d89f13ca..4c71eea4c8 100644 --- a/.internal-ci/helm/fog-services-config/values.yaml +++ b/.internal-ci/helm/fog-services-config/values.yaml @@ -48,7 +48,7 @@ fogView: POSTGRES_MAX_LIFETIME: '120' POSTGRES_CONNECTION_TIMEOUT: '5' POSTGRES_MAX_CONNECTIONS: '3' - OMAP_CAPACITY: '4194304' + MC_OMAP_CAPACITY: '4194304' fogLedger: ### Cookie salts will be generated if no values are provided @@ -60,7 +60,7 @@ fogLedger: cookie: salt: '' configMap: - OMAP_CAPACITY: '4194304' + MC_OMAP_CAPACITY: '4194304' ### fogPublicFQDN # Public domain names for ingres into fog services. diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml index fec0a5f8de..f957abe00e 100644 --- a/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml @@ -6,6 +6,7 @@ metadata: labels: {{- include "fogServices.labels" . | nindent 4 }} spec: + podManagementPolicy: {{ .Values.fogLedger.podManagementPolicy }} replicas: {{ .Values.fogLedger.replicaCount }} selector: matchLabels: @@ -76,8 +77,9 @@ spec: command: - "/usr/local/bin/grpc_health_probe" - "-addr=:3228" - failureThreshold: 30 - periodSeconds: 10 + # Wait up to 2 hours for startup + failureThreshold: 240 + periodSeconds: 30 # Will wait for startup probe to succeed. When this passes k8s won't kill the service. livenessProbe: exec: diff --git a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml index 07a3398301..c1fcbdb79c 100644 --- a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml @@ -94,6 +94,7 @@ spec: command: - "/usr/local/bin/grpc_health_probe" - "-addr=:3222" + # Wait 5 min for startup failureThreshold: 30 periodSeconds: 10 # Will wait for startup probe to succeed. When this passes k8s won't kill the service. diff --git a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml index 402d4f8d27..b372536872 100644 --- a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml @@ -105,9 +105,9 @@ spec: command: - "/usr/local/bin/grpc_health_probe" - "-addr=:3225" - failureThreshold: 120 - periodSeconds: 60 - initialDelaySeconds: 60 + # wait up to 2 hours for start up + failureThreshold: 240 + periodSeconds: 30 # Will wait for startup probe to succeed. When this passes k8s won't kill the service. livenessProbe: exec: diff --git a/.internal-ci/helm/fog-services/values.yaml b/.internal-ci/helm/fog-services/values.yaml index 8b55c52af7..0941b5ac17 100644 --- a/.internal-ci/helm/fog-services/values.yaml +++ b/.internal-ci/helm/fog-services/values.yaml @@ -151,6 +151,8 @@ fogLedger: name: fog-ledger pullPolicy: Always + podManagementPolicy: Parallel + rust: backtrace: full log: info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn From 071c5e343ff304964fdb49d6e9b9f2683af46c03 Mon Sep 17 00:00:00 2001 From: Bernie Dolan Date: Thu, 16 Jun 2022 10:36:26 -0700 Subject: [PATCH 38/77] Add bindings for CRC computation (#2149) --- Cargo.lock | 1 + android-bindings/Cargo.toml | 3 +++ .../android-bindings/publish.gradle | 2 +- android-bindings/src/bindings.rs | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 18fea28111..deb8ba5745 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2260,6 +2260,7 @@ version = "1.2.2" dependencies = [ "aes-gcm", "anyhow", + "crc", "displaydoc", "generic-array", "jni", diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index 2edc6fd084..06e36ae11a 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -11,6 +11,9 @@ name = "mobilecoin_android" crate-type = ["cdylib"] [dependencies] +# External dependencies +crc = "3.0.0" + # fog mc-fog-kex-rng = { path = "../fog/kex_rng" } diff --git a/android-bindings/lib-wrapper/android-bindings/publish.gradle b/android-bindings/lib-wrapper/android-bindings/publish.gradle index 288d6a7545..0be9afcde8 100644 --- a/android-bindings/lib-wrapper/android-bindings/publish.gradle +++ b/android-bindings/lib-wrapper/android-bindings/publish.gradle @@ -1,6 +1,6 @@ apply plugin: 'maven-publish' -version '1.2.1' +version '1.2.2' group 'com.mobilecoin' Properties properties = new Properties() diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index fc38e6d115..a10978a25c 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -13,6 +13,7 @@ use crate::{ use aes_gcm::Aes256Gcm; use bip39::{Language, Mnemonic}; use core::convert::TryFrom; +use crc::Crc; use generic_array::{typenum::U66, GenericArray}; use jni::{ objects::{JObject, JString}, @@ -2048,6 +2049,23 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_Util_get_1shared_1secret( ) } +#[no_mangle] +pub unsafe extern "C" fn Java_com_mobilecoin_lib_Util_compute_1commitment_1crc32( + env: JNIEnv, + _obj: JObject, + commitment_bytes: jbyteArray, +) -> jint { + jni_ffi_call_or( + || Ok(0), + &env, + |env| { + let commitment_bytes = env.convert_byte_array(commitment_bytes)?; + let crc32 = Crc::::new(&crc::CRC_32_ISO_HDLC).checksum(&commitment_bytes); + Ok(crc32 as jint) + }, + ) +} + /******************************************************************** * Receipt */ From ec13c62bfb228899c655822451738fd9798b3bd8 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Thu, 16 Jun 2022 20:31:39 -0500 Subject: [PATCH 39/77] Longer startup, topology and affinity rules (#2155) * add affinity and topology rules --- .github/workflows/mobilecoin-dev-cd.yaml | 3 ++ .../templates/node-deployment.yaml | 33 ++++++++++++------- .../templates/fog-ingest-statefulset.yaml | 22 +++++++++++++ .../templates/fog-ledger-statefulset.yaml | 22 +++++++++++++ .../templates/fog-report-deployment.yaml | 12 +++++++ .../templates/fog-view-deployment.yaml | 31 +++++++++++++++-- .internal-ci/helm/fog-services/values.yaml | 2 +- 7 files changed, 110 insertions(+), 15 deletions(-) diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 075202465b..aaeebcf99a 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -16,6 +16,9 @@ on: - feature/* - develop +# don't run more than one at a time for a branch/tag +concurrency: mobilecoin-dev-cd-${{ github.ref }} + jobs: ############################################ # Generate environment information diff --git a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml index 5cdec76462..27ffe72598 100644 --- a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml +++ b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml @@ -28,20 +28,29 @@ spec: client-load-balanced: 'true' {{- end }} spec: - nodeSelector: - {{- toYaml .Values.node.nodeSelector | nindent 8 }} + # Try to balance pods across zones + topologySpreadConstraints: + - topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + # Wait until we have nodes + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + # match app and helm chart version + app: consensus-node + helm.sh/chart: {{ include "consensusNode.chart" . }} affinity: podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - consensus-node - topologyKey: 'kubernetes.io/hostname' + requiredDuringSchedulingIgnoredDuringExecution: + # Require pods to be on separate nodes. + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + # match all consensus-nodes deployed by the same chart version + app: consensus-node + helm.sh/chart: {{ include "consensusNode.chart" . }} + nodeSelector: + {{- toYaml .Values.node.nodeSelector | nindent 8 }} tolerations: {{- toYaml .Values.node.tolerations | nindent 6 }} imagePullSecrets: diff --git a/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml b/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml index 968eae98b2..ba35efc7e1 100644 --- a/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml +++ b/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml @@ -21,6 +21,28 @@ spec: app: fog-ingest {{- include "fogIngest.labels" . | nindent 8 }} spec: + # Try to balance pods across zones + topologySpreadConstraints: + - topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + # Wait until we have nodes + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + # match on this helm chart install + app: fog-ingest + helm.sh/chart: {{ include "fogIngest.chart" . }} + {{- include "fogIngest.selectorLabels" . | nindent 12 }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + # Require pods to be on separate nodes. + - topologyKey: kubernetes.io/hostname + labelSelector: + # match on this helm chart install + app: fog-ingest + helm.sh/chart: {{ include "fogIngest.chart" . }} + {{- include "fogIngest.selectorLabels" . | nindent 14 }} imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 6 }} terminationGracePeriodSeconds: 30 diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml index f957abe00e..eeb7f5f5ee 100644 --- a/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml @@ -21,6 +21,28 @@ spec: app: fog-ledger {{- include "fogServices.labels" . | nindent 8 }} spec: + # Try to balance pods across zones + topologySpreadConstraints: + - topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + # Wait until we have nodes + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + # match on this helm chart install + app: fog-ledger + helm.sh/chart: {{ include "fogServices.chart" . }} + {{- include "fogServices.selectorLabels" . | nindent 12 }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + # Require pods to be on separate nodes. + - topologyKey: kubernetes.io/hostname + labelSelector: + # match on this helm chart install + app: fog-ledger + helm.sh/chart: {{ include "fogServices.chart" . }} + {{- include "fogServices.selectorLabels" . | nindent 14 }} imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 6 }} terminationGracePeriodSeconds: 30 diff --git a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml index c1fcbdb79c..8eec153a9c 100644 --- a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml @@ -20,6 +20,18 @@ spec: app: fog-report {{- include "fogServices.labels" . | nindent 8 }} spec: + # Try to balance pods across zones + topologySpreadConstraints: + - topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + # Wait until we have nodes + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + # match on this helm chart install + app: fog-report + helm.sh/chart: {{ include "fogServices.chart" . }} + {{- include "fogServices.selectorLabels" . | nindent 12 }} imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }} initContainers: diff --git a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml index b372536872..875ed06ab6 100644 --- a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml @@ -8,6 +8,11 @@ metadata: {{- include "fogServices.labels" . | nindent 4 }} spec: replicas: {{ .Values.fogView.replicaCount }} + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 50% selector: matchLabels: app: fog-view @@ -20,6 +25,28 @@ spec: app: fog-view {{- include "fogServices.labels" . | nindent 8 }} spec: + # Try to balance pods across zones + topologySpreadConstraints: + - topologyKey: topology.kubernetes.io/zone + maxSkew: 1 + # Wait until we have nodes + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + # match on this helm chart install + app: fog-view + helm.sh/chart: {{ include "fogServices.chart" . }} + {{- include "fogServices.selectorLabels" . | nindent 12 }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + # Require pods to be on separate nodes. + - topologyKey: kubernetes.io/hostname + labelSelector: + # match on this helm chart install + app: fog-view + helm.sh/chart: {{ include "fogServices.chart" . }} + {{- include "fogServices.selectorLabels" . | nindent 14 }} imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 6 }} initContainers: @@ -105,8 +132,8 @@ spec: command: - "/usr/local/bin/grpc_health_probe" - "-addr=:3225" - # wait up to 2 hours for start up - failureThreshold: 240 + # wait up to 4 hours for start up + failureThreshold: 480 periodSeconds: 30 # Will wait for startup probe to succeed. When this passes k8s won't kill the service. livenessProbe: diff --git a/.internal-ci/helm/fog-services/values.yaml b/.internal-ci/helm/fog-services/values.yaml index 0941b5ac17..900b0e5885 100644 --- a/.internal-ci/helm/fog-services/values.yaml +++ b/.internal-ci/helm/fog-services/values.yaml @@ -88,7 +88,7 @@ fogReport: POSTGRES_MAX_CONNECTIONS: '3' fogView: - replicaCount: 2 + replicaCount: 4 image: org: '' name: fogview From 344bc424307a21b7ad523676b3bbb9c4561e2ea6 Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 17 Jun 2022 11:10:24 -0700 Subject: [PATCH 40/77] SGX 2.17 in 1.2.2 (#2164) * Update SGX to 2.17, mitigate INTEL-SA-00615 - Update SGX SDK to 2.17 in scripts - Update verifier creation points to allow INTEL-SA-00615 - Change EDLs to use [out] instead of [user_check] - Flip relevant tests in trusted ECALLs * Bump dockerfile-version * Update fog/distribution/src/config.rs Co-authored-by: Remoun Metyas * Update builder image version in CI * Add some stub JSON tests, fix some verifier flaws. * Add passing single-value mrenclave_config_sw test. * Add a bunch more unit tests around verifiers. * Apply suggestions from code review Co-authored-by: Jason Greathouse Co-authored-by: Remoun Metyas * rustfmt * Fix build. * Update rust-sgx-base image. Co-authored-by: Remoun Metyas Co-authored-by: Jason Greathouse --- .circleci/config.yml | 2 +- .github/workflows/mobilecoin-dev-cd.yaml | 2 +- .internal-ci/docker/Dockerfile.runtime-base | 5 +- CHANGELOG.md | 6 +- attest/verifier/README.md | 3 +- .../data/test/ias_config_sw_334_615.json | 1 + attest/verifier/data/test/ias_sw_334_615.json | 1 + attest/verifier/src/lib.rs | 28 +- attest/verifier/src/status.rs | 462 +++++++++++++++++- consensus/enclave/build.rs | 2 +- consensus/enclave/edl/enclave.edl | 6 +- consensus/enclave/measurement/build.rs | 2 +- consensus/enclave/measurement/src/lib.rs | 2 +- consensus/enclave/trusted/build.rs | 2 +- consensus/enclave/trusted/src/lib.rs | 6 +- consensus/service/BUILD.md | 8 +- crypto/ake/enclave/src/lib.rs | 6 +- docker/Dockerfile-version | 2 +- docker/install_sgx.sh | 6 +- fog/distribution/src/config.rs | 3 +- fog/ingest/enclave/build.rs | 2 +- fog/ingest/enclave/edl/enclave.edl | 6 +- fog/ingest/enclave/measurement/build.rs | 2 +- fog/ingest/enclave/measurement/src/lib.rs | 2 +- fog/ingest/enclave/trusted/build.rs | 2 +- fog/ingest/enclave/trusted/src/lib.rs | 6 +- fog/ledger/enclave/build.rs | 2 +- fog/ledger/enclave/edl/enclave.edl | 6 +- fog/ledger/enclave/measurement/build.rs | 2 +- fog/ledger/enclave/measurement/src/lib.rs | 2 +- fog/ledger/enclave/trusted/build.rs | 2 +- fog/ledger/enclave/trusted/src/lib.rs | 6 +- fog/ledger/server/tests/connection.rs | 8 +- fog/sample-paykit/src/client_builder.rs | 14 +- fog/view/enclave/build.rs | 2 +- fog/view/enclave/edl/enclave.edl | 6 +- fog/view/enclave/measurement/build.rs | 2 +- fog/view/enclave/measurement/src/lib.rs | 2 +- fog/view/enclave/trusted/build.rs | 2 +- fog/view/enclave/trusted/src/lib.rs | 6 +- fog/view/server/tests/smoke_tests.rs | 3 +- jenkins/build-pod.yaml | 2 +- ledger/sync/src/test_app/main.rs | 3 +- mobilecoind/src/bin/main.rs | 3 +- mobilecoind/src/config.rs | 3 +- ops/Dockerfile-consensus | 4 +- 46 files changed, 552 insertions(+), 103 deletions(-) create mode 100644 attest/verifier/data/test/ias_config_sw_334_615.json create mode 100644 attest/verifier/data/test/ias_sw_334_615.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 7cc3a88c30..670bde1f90 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ version: 2.1 defaults: - builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_28 + builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_29 android-bindings-builder: &android-bindings-builder gcr.io/mobilenode-211420/android-bindings-builder:1_4 default-xcode-version: &default-xcode-version "12.0.0" diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index aaeebcf99a..88565104e9 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -60,7 +60,7 @@ jobs: build-rust-hardware-projects: runs-on: [self-hosted, Linux, large] container: - image: mobilecoin/rust-sgx-base@sha256:6e9ec00ee70045392599cc3c25e74184e072e3d5a5d7abdd713c25207043afda + image: mobilecoin/rust-sgx-base@sha256:1be28a65be74022072feb929bb9b900cf303de3cd8d3a1af49d583407b0c002b env: ENCLAVE_SIGNING_KEY_PATH: ${{ github.workspace }}/.tmp/enclave_signing.pem MINTING_TRUST_ROOT_PUBLIC_KEY_PEM: ${{ github.workspace }}/.tmp/minting_trust_root.public.pem diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base index ea56da8fce..887d27cd9b 100644 --- a/.internal-ci/docker/Dockerfile.runtime-base +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -35,9 +35,10 @@ ENV LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" # libsgx-enclave-common libsgx-epid libsgx-launch libsgx-pce-logic libsgx-urts # sgx-aesm-service # Use `apt show -a sgx-aesm-service` to find version -ENV AESM_VERSION=2.16.100.4-focal1 +ENV AESM_VERSION=2.17.100.3-focal1 # Use `apt show -a libsgx-pce-logic` to find the version thats compatible with aesm. -ENV PCE_LOGIC_VERSION=1.13.100.4-focal1 +ENV PCE_LOGIC_VERSION=1.14.100.3-focal1 + # Install packages RUN apt-get update \ diff --git a/CHANGELOG.md b/CHANGELOG.md index dc4761032d..7cebb8297f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The crates in this repository do not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) at this time. -## [1.2.2] - 2022-06-09 +## [1.2.2] - 2022-06-17 ### Changed - Update CI deployments to use zerossl instead of letsencrypt +### Security + +- Bump SGX to 2.17, mitigate INTEL-SA-00615 + ## [1.2.1] - YANKED diff --git a/attest/verifier/README.md b/attest/verifier/README.md index 8a9b5daaff..e21919cffa 100644 --- a/attest/verifier/README.md +++ b/attest/verifier/README.md @@ -14,7 +14,8 @@ use mc_util_encodings::FromHex; // Create a new status verifier for a MRENCLAVE measurement value let mut enclave_verifier = MrEnclaveVerifier::new(MrEnclave::from_hex("BEEFCAFEDEADBEEFCAFEBEEF")); // Whitelist the LVI hardening advisory (assume the BEEF... enclave is hardened) -enclave_verifier.allow_hardening_advisory("INTEL-SA-00334"); +// Whitelist the MMIO hardening advisory (assume the enclave uses [out] and 8-byte aligned writes) +enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); // Construct a new verifier using hard-coded IAS signing certificates let mut verifier = Verifier::default(); diff --git a/attest/verifier/data/test/ias_config_sw_334_615.json b/attest/verifier/data/test/ias_config_sw_334_615.json new file mode 100644 index 0000000000..c85c879900 --- /dev/null +++ b/attest/verifier/data/test/ias_config_sw_334_615.json @@ -0,0 +1 @@ +{"nonce":"b6cb5af2a11cfe2f9c19b944b32c3aac","id":"329097353241719791874006404947982878982","timestamp":"2019-06-19T22:11:17.616333","version":4,"isvEnclaveQuoteStatus":"CONFIGURATION_AND_SW_HARDENING_NEEDED","platformInfoBlob":"1502006504000900000606020401010000000000000000000008000009000000020000000000000B2E053D80C01A089F0FA1A633CC53611B1A0036EDB3F1F2BE80EC8EBFBE7068A89AB679C2AA72E244115A57E18CA3A6F7447E56FBECE241C99F8656F14398E5971C","isvEnclaveQuoteBody":"AgAAAC4LAAAIAAcAAAAAALaz7oQLP7WmorFMVCIaq2p5e9wQ7TqvPTsPR5QKGmaqBQYCBP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAPe0ax8pySkpICoZTwcd6IoJtI/DbvTF9fcVyj32vHzqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+5eKddGI/28b78UVL5vO7C4bBI2a3tHitEzU+RN6EEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvSKQevPwdZqe2xCUIrsL3mYyozfbRpMAB+FyQiHHNMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00615"],"advisoryURL":"https://wouldntyouliketobeapeppertoo.com/"} diff --git a/attest/verifier/data/test/ias_sw_334_615.json b/attest/verifier/data/test/ias_sw_334_615.json new file mode 100644 index 0000000000..c1b1437df4 --- /dev/null +++ b/attest/verifier/data/test/ias_sw_334_615.json @@ -0,0 +1 @@ +{"nonce":"b6cb5af2a11cfe2f9c19b944b32c3aac","id":"329097353241719791874006404947982878982","timestamp":"2019-06-19T22:11:17.616333","version":4,"isvEnclaveQuoteStatus":"SW_HARDENING_NEEDED","platformInfoBlob":"1502006504000900000606020401010000000000000000000008000009000000020000000000000B2E053D80C01A089F0FA1A633CC53611B1A0036EDB3F1F2BE80EC8EBFBE7068A89AB679C2AA72E244115A57E18CA3A6F7447E56FBECE241C99F8656F14398E5971C","isvEnclaveQuoteBody":"AgAAAC4LAAAIAAcAAAAAALaz7oQLP7WmorFMVCIaq2p5e9wQ7TqvPTsPR5QKGmaqBQYCBP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAPe0ax8pySkpICoZTwcd6IoJtI/DbvTF9fcVyj32vHzqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+5eKddGI/28b78UVL5vO7C4bBI2a3tHitEzU+RN6EEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvSKQevPwdZqe2xCUIrsL3mYyozfbRpMAB+FyQiHHNMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00615"],"advisoryURL":"https://wouldntyouliketobeapeppertoo.com/"} diff --git a/attest/verifier/src/lib.rs b/attest/verifier/src/lib.rs index 5cc818028f..9df93b3826 100644 --- a/attest/verifier/src/lib.rs +++ b/attest/verifier/src/lib.rs @@ -392,7 +392,9 @@ mod test { "../data/Dev_AttestationReportSigningCACert.pem" )]; - fn get_ias_report() -> VerificationReport { + /// This function provides a recorded response using SW_HARDENING_NEEDED for + /// the INTEL-SA-00334 (LVI) advisory + fn get_334_report() -> VerificationReport { VerificationReport { sig: VerificationSignature::from(vec![164u8, 105, 80, 134, 234, 173, 20, 233, 176, 192, 25, 170, 37, 122, 173, 94, 120, 55, 98, 212, 183, 187, 59, 31, 240, 29, 174, 87, 172, 54, 130, 3, 13, 59, 86, 196, 184, 158, 92, 217, 70, 198, 227, 246, 144, 228, 146, 81, 119, 241, 39, 69, 6, 15, 100, 53, 62, 28, 53, 194, 127, 121, 234, 167, 234, 97, 45, 195, 138, 118, 4, 207, 165, 114, 78, 22, 85, 167, 77, 74, 135, 25, 115, 81, 97, 222, 27, 227, 110, 0, 210, 66, 161, 3, 166, 188, 114, 73, 50, 201, 9, 138, 41, 27, 144, 163, 91, 255, 221, 42, 194, 86, 198, 103, 130, 155, 90, 64, 61, 249, 48, 106, 69, 205, 196, 118, 35, 153, 243, 197, 124, 204, 79, 205, 125, 181, 12, 190, 13, 25, 192, 30, 53, 190, 149, 11, 230, 63, 116, 15, 55, 231, 226, 169, 242, 126, 181, 8, 81, 98, 140, 166, 26, 138, 66, 4, 170, 178, 111, 158, 129, 140, 217, 171, 157, 212, 23, 225, 191, 137, 187, 254, 127, 111, 138, 209, 39, 250, 26, 250, 96, 217, 48, 113, 99, 175, 107, 179, 17, 213, 139, 116, 98, 193, 149, 89, 202, 239, 248, 42, 155, 39, 67, 173, 142, 59, 191, 54, 26, 196, 19, 67, 25, 159, 210, 199, 112, 156, 218, 117, 76, 1, 30, 251, 240, 15, 57, 141, 41, 242, 70, 42, 134, 68, 224, 117, 137, 47, 152, 246, 220, 192, 32, 201, 242, 58]), chain: vec![ @@ -403,6 +405,8 @@ mod test { } } + // FIXME: Add 334+615 exemplar + /// Ensure a verifier without any status verifiers can pass. #[test] fn no_status_ok() { @@ -413,7 +417,7 @@ mod test { &IasNonce::from_hex("ca1bb26d4a756cabf422206fc1953e4b") .expect("Could not parse nonce hex"), ) - .verify(&get_ias_report()) + .verify(&get_334_report()) .expect("Could not verify IAS report"); } @@ -424,19 +428,19 @@ mod test { 69, 251, 36, 34, 76, 54, 51, 236, 141, 181, 29, 9, 11, 241, 29, 228, 222, 118, 194, 134, 108, 6, 1, 2, 49, 80, 32, 217, 151, 134, 184, 44, ])); - mr_enclave1.allow_hardening_advisory("INTEL-SA-00334"); + mr_enclave1.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); let mut mr_enclave2 = MrEnclaveVerifier::new(MrEnclave::from([ 209, 31, 70, 153, 191, 224, 183, 181, 71, 206, 99, 225, 136, 46, 1, 238, 208, 198, 84, 121, 40, 171, 120, 154, 49, 90, 135, 137, 143, 44, 83, 77, ])); - mr_enclave2.allow_hardening_advisory("INTEL-SA-00334"); + mr_enclave2.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); Verifier::new(TEST_ANCHORS) .expect("Could not initialize new verifier") - .mr_enclave(mr_enclave1) - .mr_enclave(mr_enclave2) - .verify(&get_ias_report()) + .mr_enclave(mr_enclave1.clone()) + .mr_enclave(mr_enclave2.clone()) + .verify(&get_334_report()) .expect("Could not verify IAS report"); } @@ -452,7 +456,7 @@ mod test { 10, 10, ); - mr_signer1.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer1.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); let mut mr_signer2 = MrSignerVerifier::new( MrSigner::from([ 209, 31, 70, 153, 191, 224, 183, 181, 71, 206, 99, 225, 136, 46, 1, 238, 208, 198, @@ -461,14 +465,14 @@ mod test { 1, 1, ); - mr_signer2.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer2.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); Verifier::new(TEST_ANCHORS) .expect("Could not initialize new verifier") - .mr_signer(mr_signer1) - .mr_signer(mr_signer2) + .mr_signer(mr_signer1.clone()) + .mr_signer(mr_signer2.clone()) .debug(true) - .verify(&get_ias_report()) + .verify(&get_334_report()) .expect("Could not verify IAS report"); } } diff --git a/attest/verifier/src/status.rs b/attest/verifier/src/status.rs index c3a5070ae4..9c65a266db 100644 --- a/attest/verifier/src/status.rs +++ b/attest/verifier/src/status.rs @@ -34,7 +34,7 @@ fn check_ids(quote_status: &IasQuoteResult, config_ids: &[String], sw_ids: &[Str } Err(IasQuoteError::ConfigurationAndSwHardeningNeeded { advisory_ids, .. }) => advisory_ids .iter() - .all(|id| config_ids.contains(id) || sw_ids.contains(id)), + .all(|id| config_ids.contains(id) && sw_ids.contains(id)), Err(_) => false, } } @@ -256,10 +256,25 @@ mod test { use mc_attest_core::VerificationReport; use mc_sgx_types::sgx_measurement_t; + /// Report with OK status const IAS_OK: &str = include_str!("../data/test/ias_ok.json"); + + /// Report with "CONFIGURATION_NEEDED" status const IAS_CONFIG: &str = include_str!("../data/test/ias_config.json"); + + /// Report with "SW_HARDENING_NEEDED" status const IAS_SW: &str = include_str!("../data/test/ias_sw.json"); + + /// Report with "SW_HARDENING_NEEDED" and both 334 and 615 advisories. + const IAS_SW_334_615: &str = include_str!("../data/test/ias_sw_334_615.json"); + + /// Report with "CONFIGURATION_AND_SW_HARDENING_NEEDED" status const IAS_CONFIG_SW: &str = include_str!("../data/test/ias_config_sw.json"); + + /// Report with "CONFIGURATION_AND_SW_HARDENING_NEEDED" status, and both 334 + /// and 615 advisories. + const IAS_CONFIG_SW_334_615: &str = include_str!("../data/test/ias_config_sw_334_615.json"); + const MR_ENCLAVE: sgx_measurement_t = sgx_measurement_t { m: [ 247, 180, 107, 31, 41, 201, 41, 41, 32, 42, 25, 79, 7, 29, 232, 138, 9, 180, 143, 195, @@ -371,6 +386,26 @@ mod test { assert!(verifier.verify(&data)) } + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE and + /// advisories passes. + #[test] + fn mrenclave_multi_sw_pass() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(verifier.verify(&data)) + } + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but /// unexpected advisory fails. #[test] @@ -391,14 +426,74 @@ mod test { assert!(!verifier.verify(&data)) } + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but + /// unexpected advisory fails. + #[test] + fn mrenclave_sw_empty_fail() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but + /// unexpected advisory fails. + #[test] + fn mrenclave_multi_sw_empty_fail() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but + /// unexpected advisory fails. + #[test] + fn mrenclave_multi_sw_short_fail() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and config advisory passes. + /// MRENCLAVE and advisory passes when the advisory is given for both. #[test] - fn mrenclave_config_sw_pass_config() { + fn mrenclave_config_sw_pass() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00239".to_owned()], - sw_ids: vec!["INTEL-SA-00123".to_owned()], + sw_ids: vec!["INTEL-SA-00239".to_owned()], }; let report = VerificationReport { @@ -412,9 +507,128 @@ mod test { } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and hardening advisory passes. + /// MRENCLAVE and advisory passes when the advisory is given for both. + #[test] + fn mrenclave_multi_config_sw_pass() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and config advisory fails. + #[test] + fn mrenclave_config_sw_fail_config() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00239".to_owned()], + sw_ids: vec!["INTEL-SA-00123".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and sw-only advisory allow-listing fails. + #[test] + fn mrenclave_multi_config_sw_fail_no_config() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and sw-only advisory allow-listing fails. + #[test] + fn mrenclave_multi_config_sw_fail_no_sw() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and insufficient sw advisory allow-listing fails. + #[test] + fn mrenclave_multi_config_sw_fail_short_sw() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and insufficient config advisory allow-listing fails. + #[test] + fn mrenclave_multi_config_sw_fail_short_config() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and hardening advisory fails. #[test] - fn mrenclave_config_sw_pass_sw() { + fn mrenclave_config_sw_fail_sw() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00123".to_owned()], @@ -428,13 +642,13 @@ mod test { }; let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(verifier.verify(&data)) + assert!(!verifier.verify(&data)) } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected /// MRENCLAVE but an unexpected advisory fails. #[test] - fn mrenclave_config_sw_fail() { + fn mrenclave_config_sw_fail_neither() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00123".to_owned()], @@ -451,6 +665,26 @@ mod test { assert!(!verifier.verify(&data)) } + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE but an unexpected advisory fails. + #[test] + fn mrenclave_multi_config_sw_fail_short() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + /// Ensure an OK result with the expected MRSIGNER, product, and minimum /// version passes. #[test] @@ -604,16 +838,39 @@ mod test { assert!(verifier.verify(&data)) } - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version passes, as long as the - /// advisory is accounted for. + /// Ensure a SW_HARDENING_NEEDED result with the expected MRSIGNER, + /// product, and minimum version passes, as long as all advisories are + /// accounted for #[test] - fn mrsigner_pass_sw_config_via_sw() { + fn mrsigner_pass_multi_sw() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, minimum_svn: 0, config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version succeds if all advisories are + /// accounted for as both config and sw. + #[test] + fn mrsigner_pass_config_sw() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00239".to_owned()], sw_ids: vec!["INTEL-SA-00239".to_owned()], }; @@ -628,10 +885,33 @@ mod test { } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version passes, as long as the - /// advisory is accounted for. + /// MRSIGNER, product, and minimum version fails if the advisory isn't + /// accounted for as both config and sw. + #[test] + fn mrsigner_fail_config_sw_no_sw() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00239".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails, if the advisory isn't + /// accounted for in both config and sw. #[test] - fn mrsigner_pass_sw_config_via_config() { + fn mrsigner_fail_config_sw_no_config() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, @@ -647,19 +927,111 @@ mod test { }; let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(verifier.verify(&data)) + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails if the advisory isn't + /// accounted for as both config and sw. + #[test] + fn mrsigner_fail_multi_config_sw_no_sw() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails if the advisory isn't + /// accounted for in both config and sw. + #[test] + fn mrsigner_fail_multi_config_sw_short_sw() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00615".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails, if the advisory isn't + /// accounted for in both config and sw. + #[test] + fn mrsigner_fail_multi_config_sw_no_config() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails, if the advisory isn't + /// accounted for in both config and sw. + #[test] + fn mrsigner_fail_multi_config_sw_short_config() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00334".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected /// MRSIGNER, and minimum version, but the wrong product fails, even if /// the advisory is accounted for. #[test] - fn mrsigner_fail_sw_config_for_product() { + fn mrsigner_fail_sw_config_sw_for_product() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 1, minimum_svn: 0, - config_ids: vec![], + config_ids: vec!["INTEL-SA-00239".to_owned()], sw_ids: vec!["INTEL-SA-00239".to_owned()], }; @@ -674,15 +1046,38 @@ mod test { } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER and product, but an earlier version, fails, even if the - /// advisory is accounted for. + /// MRSIGNER, and minimum version, but the wrong product fails, even if + /// all advisories are accounted for. + #[test] + fn mrsigner_fail_multi_sw_config_sw_for_product() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 1, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER and product, but an earlier version, fails, even if all + /// advisories are accounted for. #[test] - fn mrsigner_fail_sw_config_for_version() { + fn mrsigner_fail_config_sw_for_version() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, minimum_svn: 1, - config_ids: vec![], + config_ids: vec!["INTEL-SA-00239".to_owned()], sw_ids: vec!["INTEL-SA-00239".to_owned()], }; @@ -695,4 +1090,27 @@ mod test { let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); assert!(!verifier.verify(&data)) } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER and product, but an earlier version, fails, even if the + /// advisory is accounted for. + #[test] + fn mrsigner_fail_multi_config_sw_for_version() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 1, + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } } diff --git a/consensus/enclave/build.rs b/consensus/enclave/build.rs index 052b7f7881..06f7cf9e95 100644 --- a/consensus/enclave/build.rs +++ b/consensus/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/consensus/enclave/edl/enclave.edl b/consensus/enclave/edl/enclave.edl index 182c5a0a82..15410507f8 100644 --- a/consensus/enclave/edl/enclave.edl +++ b/consensus/enclave/edl/enclave.edl @@ -11,10 +11,10 @@ enclave { */ public sgx_status_t mobileenclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [user_check] uint8_t *outbuf, + [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, - [user_check] size_t* outbuf_used, - [user_check] uint64_t* outbuf_retry_id); + [out] size_t* outbuf_used, + [out] uint64_t* outbuf_retry_id); }; }; diff --git a/consensus/enclave/measurement/build.rs b/consensus/enclave/measurement/build.rs index 41279130fd..fba109e9db 100644 --- a/consensus/enclave/measurement/build.rs +++ b/consensus/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; const CONSENSUS_ENCLAVE_PRODUCT_ID: u16 = 1; const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 4; diff --git a/consensus/enclave/measurement/src/lib.rs b/consensus/enclave/measurement/src/lib.rs index b698c7e438..46c4b1f947 100644 --- a/consensus/enclave/measurement/src/lib.rs +++ b/consensus/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/consensus/enclave/trusted/build.rs b/consensus/enclave/trusted/build.rs index 2ff60613e9..c130d2d1e6 100644 --- a/consensus/enclave/trusted/build.rs +++ b/consensus/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/consensus/enclave/trusted/src/lib.rs b/consensus/enclave/trusted/src/lib.rs index ab9c333d41..9c4fef6e0e 100644 --- a/consensus/enclave/trusted/src/lib.rs +++ b/consensus/enclave/trusted/src/lib.rs @@ -100,16 +100,16 @@ pub extern "C" fn mobileenclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } != 1 + } == 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } != 1 + } == 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/consensus/service/BUILD.md b/consensus/service/BUILD.md index 81555f92e8..28df38409b 100644 --- a/consensus/service/BUILD.md +++ b/consensus/service/BUILD.md @@ -97,8 +97,8 @@ Recommended SDK and package installation: ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -112,8 +112,8 @@ chmod +x ./sgx_linux_x64_driver_2.11.054c9c4c.bin ./sgx_linux_x64_driver_2.11.054c9c4c.bin # Install the SDK to /opt/intel/sgxsdk -chmod +x ./sgx_linux_x64_sdk_2.16.100.4.bin -./sgx_linux_x64_sdk_2.16.100.4.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.17.100.3.bin +./sgx_linux_x64_sdk_2.17.100.3.bin --prefix=/opt/intel apt install libsgx-uae-service sgx-aesm-service diff --git a/crypto/ake/enclave/src/lib.rs b/crypto/ake/enclave/src/lib.rs index fe62c17d1f..1c2600daa3 100644 --- a/crypto/ake/enclave/src/lib.rs +++ b/crypto/ake/enclave/src/lib.rs @@ -133,7 +133,11 @@ impl AkeEnclaveState { let mut mr_enclave_verifier = MrEnclaveVerifier::new(report_body.mr_enclave()); // INTEL-SA-00334: LVI hardening is handled via rustc arguments set in // mc-util-build-enclave - mr_enclave_verifier.allow_hardening_advisory("INTEL-SA-00334"); + // + // INTEL-SA-00615: MMIO Stale Data is handled by using [out] parameters + // in our ECALL/OCALL definitions (EDLs), and only performing direct + // writes aligned to quadword (8B) boundaries (e.g. in ORAMStorage) + mr_enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); verifier .mr_enclave(mr_enclave_verifier) diff --git a/docker/Dockerfile-version b/docker/Dockerfile-version index 0678f6effd..6c565411ce 100644 --- a/docker/Dockerfile-version +++ b/docker/Dockerfile-version @@ -1 +1 @@ -1_28 +1_29 diff --git a/docker/install_sgx.sh b/docker/install_sgx.sh index 7f39665521..3960fe81f8 100644 --- a/docker/install_sgx.sh +++ b/docker/install_sgx.sh @@ -24,7 +24,7 @@ cd /tmp ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -59,8 +59,8 @@ apt-get install -yq --no-install-recommends \ # Install *after* pkg-config so that they get registered correctly. # pkg-config gets pulled in transitively via build-essential -chmod +x ./sgx_linux_x64_sdk_2.16.100.4.bin -./sgx_linux_x64_sdk_2.16.100.4.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.17.100.3.bin +./sgx_linux_x64_sdk_2.17.100.3.bin --prefix=/opt/intel # Update .bashrc to source sgxsdk echo 'source /opt/intel/sgxsdk/environment' >> /root/.bashrc diff --git a/fog/distribution/src/config.rs b/fog/distribution/src/config.rs index 806374e7e4..20505e1379 100644 --- a/fog/distribution/src/config.rs +++ b/fog/distribution/src/config.rs @@ -99,7 +99,8 @@ impl Config { ) -> ConnectionResult>>> { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/fog/ingest/enclave/build.rs b/fog/ingest/enclave/build.rs index 26c06202d7..85b5ffa7c3 100644 --- a/fog/ingest/enclave/build.rs +++ b/fog/ingest/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/ingest/enclave/edl/enclave.edl b/fog/ingest/enclave/edl/enclave.edl index a6b9108ad2..3c743fbe17 100644 --- a/fog/ingest/enclave/edl/enclave.edl +++ b/fog/ingest/enclave/edl/enclave.edl @@ -13,10 +13,10 @@ enclave { */ public sgx_status_t ingest_enclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [user_check] uint8_t *outbuf, + [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, - [user_check] size_t* outbuf_used, - [user_check] uint64_t* outbuf_retry_id); + [out] size_t* outbuf_used, + [out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/ingest/enclave/measurement/build.rs b/fog/ingest/enclave/measurement/build.rs index c978fc67e9..c9410dbcfd 100644 --- a/fog/ingest/enclave/measurement/build.rs +++ b/fog/ingest/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; const INGEST_ENCLAVE_PRODUCT_ID: u16 = 4; const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 3; diff --git a/fog/ingest/enclave/measurement/src/lib.rs b/fog/ingest/enclave/measurement/src/lib.rs index 22b991df1d..5f0064d12a 100644 --- a/fog/ingest/enclave/measurement/src/lib.rs +++ b/fog/ingest/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/ingest/enclave/trusted/build.rs b/fog/ingest/enclave/trusted/build.rs index 2622ad4ec6..1b47cb1d60 100644 --- a/fog/ingest/enclave/trusted/build.rs +++ b/fog/ingest/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/ingest/enclave/trusted/src/lib.rs b/fog/ingest/enclave/trusted/src/lib.rs index 81d0d0c144..7414c5ad47 100644 --- a/fog/ingest/enclave/trusted/src/lib.rs +++ b/fog/ingest/enclave/trusted/src/lib.rs @@ -84,16 +84,16 @@ pub extern "C" fn ingest_enclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } != 1 + } == 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } != 1 + } == 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/fog/ledger/enclave/build.rs b/fog/ledger/enclave/build.rs index 004600e660..8dc6e68629 100644 --- a/fog/ledger/enclave/build.rs +++ b/fog/ledger/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/edl/enclave.edl b/fog/ledger/enclave/edl/enclave.edl index e7ad6a58cb..2dc096c074 100644 --- a/fog/ledger/enclave/edl/enclave.edl +++ b/fog/ledger/enclave/edl/enclave.edl @@ -13,10 +13,10 @@ enclave { */ public sgx_status_t ledger_enclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [user_check] uint8_t *outbuf, + [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, - [user_check] size_t* outbuf_used, - [user_check] uint64_t* outbuf_retry_id); + [out] size_t* outbuf_used, + [out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/ledger/enclave/measurement/build.rs b/fog/ledger/enclave/measurement/build.rs index 46f7402fc0..8f23a1fbd5 100644 --- a/fog/ledger/enclave/measurement/build.rs +++ b/fog/ledger/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; const LEDGER_ENCLAVE_PRODUCT_ID: u16 = 2; const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 3; diff --git a/fog/ledger/enclave/measurement/src/lib.rs b/fog/ledger/enclave/measurement/src/lib.rs index 6bd930d62d..7bf42f751b 100644 --- a/fog/ledger/enclave/measurement/src/lib.rs +++ b/fog/ledger/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/ledger/enclave/trusted/build.rs b/fog/ledger/enclave/trusted/build.rs index 8509981de6..d71761f769 100644 --- a/fog/ledger/enclave/trusted/build.rs +++ b/fog/ledger/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/trusted/src/lib.rs b/fog/ledger/enclave/trusted/src/lib.rs index 58041ca64b..18f1009a9f 100644 --- a/fog/ledger/enclave/trusted/src/lib.rs +++ b/fog/ledger/enclave/trusted/src/lib.rs @@ -82,16 +82,16 @@ pub extern "C" fn ledger_enclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } != 1 + } == 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } != 1 + } == 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/fog/ledger/server/tests/connection.rs b/fog/ledger/server/tests/connection.rs index fce0305954..53c601e275 100644 --- a/fog/ledger/server/tests/connection.rs +++ b/fog/ledger/server/tests/connection.rs @@ -160,7 +160,9 @@ fn fog_ledger_merkle_proofs_test(logger: Logger) { // Make ledger enclave client let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_ledger_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier.allow_hardening_advisories( + mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, + ); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); @@ -352,7 +354,9 @@ fn fog_ledger_key_images_test(logger: Logger) { // Make ledger enclave client let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_ledger_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier.allow_hardening_advisories( + mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, + ); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/fog/sample-paykit/src/client_builder.rs b/fog/sample-paykit/src/client_builder.rs index cd6ce3fa1f..cf531c23ff 100644 --- a/fog/sample-paykit/src/client_builder.rs +++ b/fog/sample-paykit/src/client_builder.rs @@ -255,7 +255,8 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); mr_signer_verifier } else { mc_consensus_enclave_measurement::get_mr_signer_verifier(None) @@ -274,7 +275,9 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier.allow_hardening_advisories( + mc_fog_ingest_enclave_measurement::HARDENING_ADVISORIES, + ); mr_signer_verifier } else { mc_fog_ingest_enclave_measurement::get_mr_signer_verifier(None) @@ -293,7 +296,9 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier.allow_hardening_advisories( + mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, + ); mr_signer_verifier } else { mc_fog_ledger_enclave_measurement::get_mr_signer_verifier(None) @@ -312,7 +317,8 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier + .allow_hardening_advisories(mc_fog_view_enclave_measurement::HARDENING_ADVISORIES); mr_signer_verifier } else { mc_fog_view_enclave_measurement::get_mr_signer_verifier(None) diff --git a/fog/view/enclave/build.rs b/fog/view/enclave/build.rs index 04748228e8..0df4b8bb9a 100644 --- a/fog/view/enclave/build.rs +++ b/fog/view/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/edl/enclave.edl b/fog/view/enclave/edl/enclave.edl index 80eac0dfa0..66a0486f47 100644 --- a/fog/view/enclave/edl/enclave.edl +++ b/fog/view/enclave/edl/enclave.edl @@ -15,10 +15,10 @@ enclave { */ public sgx_status_t viewenclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [user_check] uint8_t *outbuf, + [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, - [user_check] size_t* outbuf_used, - [user_check] uint64_t* outbuf_retry_id); + [out] size_t* outbuf_used, + [out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/view/enclave/measurement/build.rs b/fog/view/enclave/measurement/build.rs index 0ce0f08c21..80368b5d9c 100644 --- a/fog/view/enclave/measurement/build.rs +++ b/fog/view/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; const VIEW_ENCLAVE_PRODUCT_ID: u16 = 3; const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 3; diff --git a/fog/view/enclave/measurement/src/lib.rs b/fog/view/enclave/measurement/src/lib.rs index 3f1221e82c..94bb6d37fc 100644 --- a/fog/view/enclave/measurement/src/lib.rs +++ b/fog/view/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/view/enclave/trusted/build.rs b/fog/view/enclave/trusted/build.rs index b03145862c..ad2076eca5 100644 --- a/fog/view/enclave/trusted/build.rs +++ b/fog/view/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/trusted/src/lib.rs b/fog/view/enclave/trusted/src/lib.rs index 6710366cc8..2607fb4e28 100644 --- a/fog/view/enclave/trusted/src/lib.rs +++ b/fog/view/enclave/trusted/src/lib.rs @@ -37,14 +37,14 @@ pub extern "C" fn viewenclave_call( if inbuf.is_null() || outbuf.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 { eprintln!("inbuf or outbuf was out of bounds!"); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } if unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } != 1 + } == 1 { eprintln!("outbuf_used was out of bounds! {:?}", outbuf_used); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; @@ -55,7 +55,7 @@ pub extern "C" fn viewenclave_call( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } != 1 + } == 1 { eprintln!("outbuf_retry_id was out of bounds! {:?}", outbuf_retry_id); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; diff --git a/fog/view/server/tests/smoke_tests.rs b/fog/view/server/tests/smoke_tests.rs index 25d02f3109..8b32dc2043 100644 --- a/fog/view/server/tests/smoke_tests.rs +++ b/fog/view/server/tests/smoke_tests.rs @@ -104,7 +104,8 @@ fn get_test_environment( let grpcio_env = Arc::new(grpcio::EnvBuilder::new().build()); let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_view_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier + .allow_hardening_advisories(mc_fog_view_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/jenkins/build-pod.yaml b/jenkins/build-pod.yaml index 9883127c08..0f56bcd0ec 100644 --- a/jenkins/build-pod.yaml +++ b/jenkins/build-pod.yaml @@ -20,7 +20,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: rust-builder-default - image: gcr.io/mobilenode-211420/builder-install:1_28 + image: gcr.io/mobilenode-211420/builder-install:1_29 env: - name: PATH value: "/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64" diff --git a/ledger/sync/src/test_app/main.rs b/ledger/sync/src/test_app/main.rs index e74f502119..b3ffbae81a 100644 --- a/ledger/sync/src/test_app/main.rs +++ b/ledger/sync/src/test_app/main.rs @@ -97,7 +97,8 @@ fn main() { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/mobilecoind/src/bin/main.rs b/mobilecoind/src/bin/main.rs index 3a4f5721af..346d8e4e29 100644 --- a/mobilecoind/src/bin/main.rs +++ b/mobilecoind/src/bin/main.rs @@ -41,7 +41,8 @@ fn main() { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/mobilecoind/src/config.rs b/mobilecoind/src/config.rs index 015cc8065e..fcdfb58889 100644 --- a/mobilecoind/src/config.rs +++ b/mobilecoind/src/config.rs @@ -176,7 +176,8 @@ impl Config { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier + .allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); mr_signer_verifier }; diff --git a/ops/Dockerfile-consensus b/ops/Dockerfile-consensus index 3035f4e70a..601bf23abd 100644 --- a/ops/Dockerfile-consensus +++ b/ops/Dockerfile-consensus @@ -19,9 +19,9 @@ RUN apt-get update -q -q && \ # Install SGX Ubuntu/Debian Repo RUN source /etc/os-release && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" && \ + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" && \ + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" && \ echo "deb [arch=amd64 signed-by=/usr/local/share/apt-keyrings/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list RUN mkdir -p /usr/local/share/apt-keyrings && \ From 300614575f7e0153dd2f42e667ba39d6b8bae4f8 Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 17 Jun 2022 14:55:13 -0700 Subject: [PATCH 41/77] Make outbuf_retry_id an in,out parameter, fix init-twice crash. (#2170) --- consensus/enclave/edl/enclave.edl | 2 +- fog/ingest/enclave/edl/enclave.edl | 2 +- fog/ledger/enclave/edl/enclave.edl | 2 +- fog/view/enclave/edl/enclave.edl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/consensus/enclave/edl/enclave.edl b/consensus/enclave/edl/enclave.edl index 15410507f8..150e9e2467 100644 --- a/consensus/enclave/edl/enclave.edl +++ b/consensus/enclave/edl/enclave.edl @@ -14,7 +14,7 @@ enclave { [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, [out] size_t* outbuf_used, - [out] uint64_t* outbuf_retry_id); + [in, out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/ingest/enclave/edl/enclave.edl b/fog/ingest/enclave/edl/enclave.edl index 3c743fbe17..a7b2b96fd0 100644 --- a/fog/ingest/enclave/edl/enclave.edl +++ b/fog/ingest/enclave/edl/enclave.edl @@ -16,7 +16,7 @@ enclave { [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, [out] size_t* outbuf_used, - [out] uint64_t* outbuf_retry_id); + [in, out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/ledger/enclave/edl/enclave.edl b/fog/ledger/enclave/edl/enclave.edl index 2dc096c074..f61625a82b 100644 --- a/fog/ledger/enclave/edl/enclave.edl +++ b/fog/ledger/enclave/edl/enclave.edl @@ -16,7 +16,7 @@ enclave { [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, [out] size_t* outbuf_used, - [out] uint64_t* outbuf_retry_id); + [in, out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/view/enclave/edl/enclave.edl b/fog/view/enclave/edl/enclave.edl index 66a0486f47..f6349c2354 100644 --- a/fog/view/enclave/edl/enclave.edl +++ b/fog/view/enclave/edl/enclave.edl @@ -18,7 +18,7 @@ enclave { [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, [out] size_t* outbuf_used, - [out] uint64_t* outbuf_retry_id); + [in, out] uint64_t* outbuf_retry_id); }; }; From 06e09b3e0ffac7f8b6845c9e09bfe992f72a5f59 Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 27 Jun 2022 18:03:17 -0700 Subject: [PATCH 42/77] Revert SGX 2.17 Changes (#2202) * Revert SGX 2.17 changes. This reverts commit 300614575f7e0153dd2f42e667ba39d6b8bae4f8. * Revert "SGX 2.17 in 1.2.2 (#2164)" This reverts commit 344bc424307a21b7ad523676b3bbb9c4561e2ea6. --- .circleci/config.yml | 2 +- .github/workflows/mobilecoin-dev-cd.yaml | 2 +- .internal-ci/docker/Dockerfile.runtime-base | 5 +- CHANGELOG.md | 6 +- attest/verifier/README.md | 3 +- .../data/test/ias_config_sw_334_615.json | 1 - attest/verifier/data/test/ias_sw_334_615.json | 1 - attest/verifier/src/lib.rs | 28 +- attest/verifier/src/status.rs | 462 +----------------- consensus/enclave/build.rs | 2 +- consensus/enclave/edl/enclave.edl | 6 +- consensus/enclave/measurement/build.rs | 2 +- consensus/enclave/measurement/src/lib.rs | 2 +- consensus/enclave/trusted/build.rs | 2 +- consensus/enclave/trusted/src/lib.rs | 6 +- consensus/service/BUILD.md | 8 +- crypto/ake/enclave/src/lib.rs | 6 +- docker/Dockerfile-version | 2 +- docker/install_sgx.sh | 6 +- fog/distribution/src/config.rs | 3 +- fog/ingest/enclave/build.rs | 2 +- fog/ingest/enclave/edl/enclave.edl | 6 +- fog/ingest/enclave/measurement/build.rs | 2 +- fog/ingest/enclave/measurement/src/lib.rs | 2 +- fog/ingest/enclave/trusted/build.rs | 2 +- fog/ingest/enclave/trusted/src/lib.rs | 6 +- fog/ledger/enclave/build.rs | 2 +- fog/ledger/enclave/edl/enclave.edl | 6 +- fog/ledger/enclave/measurement/build.rs | 2 +- fog/ledger/enclave/measurement/src/lib.rs | 2 +- fog/ledger/enclave/trusted/build.rs | 2 +- fog/ledger/enclave/trusted/src/lib.rs | 6 +- fog/ledger/server/tests/connection.rs | 8 +- fog/sample-paykit/src/client_builder.rs | 14 +- fog/view/enclave/build.rs | 2 +- fog/view/enclave/edl/enclave.edl | 6 +- fog/view/enclave/measurement/build.rs | 2 +- fog/view/enclave/measurement/src/lib.rs | 2 +- fog/view/enclave/trusted/build.rs | 2 +- fog/view/enclave/trusted/src/lib.rs | 6 +- fog/view/server/tests/smoke_tests.rs | 3 +- jenkins/build-pod.yaml | 2 +- ledger/sync/src/test_app/main.rs | 3 +- mobilecoind/src/bin/main.rs | 3 +- mobilecoind/src/config.rs | 3 +- ops/Dockerfile-consensus | 4 +- 46 files changed, 103 insertions(+), 552 deletions(-) delete mode 100644 attest/verifier/data/test/ias_config_sw_334_615.json delete mode 100644 attest/verifier/data/test/ias_sw_334_615.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 670bde1f90..7cc3a88c30 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ version: 2.1 defaults: - builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_29 + builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_28 android-bindings-builder: &android-bindings-builder gcr.io/mobilenode-211420/android-bindings-builder:1_4 default-xcode-version: &default-xcode-version "12.0.0" diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 88565104e9..aaeebcf99a 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -60,7 +60,7 @@ jobs: build-rust-hardware-projects: runs-on: [self-hosted, Linux, large] container: - image: mobilecoin/rust-sgx-base@sha256:1be28a65be74022072feb929bb9b900cf303de3cd8d3a1af49d583407b0c002b + image: mobilecoin/rust-sgx-base@sha256:6e9ec00ee70045392599cc3c25e74184e072e3d5a5d7abdd713c25207043afda env: ENCLAVE_SIGNING_KEY_PATH: ${{ github.workspace }}/.tmp/enclave_signing.pem MINTING_TRUST_ROOT_PUBLIC_KEY_PEM: ${{ github.workspace }}/.tmp/minting_trust_root.public.pem diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base index 887d27cd9b..ea56da8fce 100644 --- a/.internal-ci/docker/Dockerfile.runtime-base +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -35,10 +35,9 @@ ENV LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" # libsgx-enclave-common libsgx-epid libsgx-launch libsgx-pce-logic libsgx-urts # sgx-aesm-service # Use `apt show -a sgx-aesm-service` to find version -ENV AESM_VERSION=2.17.100.3-focal1 +ENV AESM_VERSION=2.16.100.4-focal1 # Use `apt show -a libsgx-pce-logic` to find the version thats compatible with aesm. -ENV PCE_LOGIC_VERSION=1.14.100.3-focal1 - +ENV PCE_LOGIC_VERSION=1.13.100.4-focal1 # Install packages RUN apt-get update \ diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cebb8297f..dc4761032d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The crates in this repository do not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) at this time. -## [1.2.2] - 2022-06-17 +## [1.2.2] - 2022-06-09 ### Changed - Update CI deployments to use zerossl instead of letsencrypt -### Security - -- Bump SGX to 2.17, mitigate INTEL-SA-00615 - ## [1.2.1] - YANKED diff --git a/attest/verifier/README.md b/attest/verifier/README.md index e21919cffa..8a9b5daaff 100644 --- a/attest/verifier/README.md +++ b/attest/verifier/README.md @@ -14,8 +14,7 @@ use mc_util_encodings::FromHex; // Create a new status verifier for a MRENCLAVE measurement value let mut enclave_verifier = MrEnclaveVerifier::new(MrEnclave::from_hex("BEEFCAFEDEADBEEFCAFEBEEF")); // Whitelist the LVI hardening advisory (assume the BEEF... enclave is hardened) -// Whitelist the MMIO hardening advisory (assume the enclave uses [out] and 8-byte aligned writes) -enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); +enclave_verifier.allow_hardening_advisory("INTEL-SA-00334"); // Construct a new verifier using hard-coded IAS signing certificates let mut verifier = Verifier::default(); diff --git a/attest/verifier/data/test/ias_config_sw_334_615.json b/attest/verifier/data/test/ias_config_sw_334_615.json deleted file mode 100644 index c85c879900..0000000000 --- a/attest/verifier/data/test/ias_config_sw_334_615.json +++ /dev/null @@ -1 +0,0 @@ -{"nonce":"b6cb5af2a11cfe2f9c19b944b32c3aac","id":"329097353241719791874006404947982878982","timestamp":"2019-06-19T22:11:17.616333","version":4,"isvEnclaveQuoteStatus":"CONFIGURATION_AND_SW_HARDENING_NEEDED","platformInfoBlob":"1502006504000900000606020401010000000000000000000008000009000000020000000000000B2E053D80C01A089F0FA1A633CC53611B1A0036EDB3F1F2BE80EC8EBFBE7068A89AB679C2AA72E244115A57E18CA3A6F7447E56FBECE241C99F8656F14398E5971C","isvEnclaveQuoteBody":"AgAAAC4LAAAIAAcAAAAAALaz7oQLP7WmorFMVCIaq2p5e9wQ7TqvPTsPR5QKGmaqBQYCBP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAPe0ax8pySkpICoZTwcd6IoJtI/DbvTF9fcVyj32vHzqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+5eKddGI/28b78UVL5vO7C4bBI2a3tHitEzU+RN6EEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvSKQevPwdZqe2xCUIrsL3mYyozfbRpMAB+FyQiHHNMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00615"],"advisoryURL":"https://wouldntyouliketobeapeppertoo.com/"} diff --git a/attest/verifier/data/test/ias_sw_334_615.json b/attest/verifier/data/test/ias_sw_334_615.json deleted file mode 100644 index c1b1437df4..0000000000 --- a/attest/verifier/data/test/ias_sw_334_615.json +++ /dev/null @@ -1 +0,0 @@ -{"nonce":"b6cb5af2a11cfe2f9c19b944b32c3aac","id":"329097353241719791874006404947982878982","timestamp":"2019-06-19T22:11:17.616333","version":4,"isvEnclaveQuoteStatus":"SW_HARDENING_NEEDED","platformInfoBlob":"1502006504000900000606020401010000000000000000000008000009000000020000000000000B2E053D80C01A089F0FA1A633CC53611B1A0036EDB3F1F2BE80EC8EBFBE7068A89AB679C2AA72E244115A57E18CA3A6F7447E56FBECE241C99F8656F14398E5971C","isvEnclaveQuoteBody":"AgAAAC4LAAAIAAcAAAAAALaz7oQLP7WmorFMVCIaq2p5e9wQ7TqvPTsPR5QKGmaqBQYCBP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAPe0ax8pySkpICoZTwcd6IoJtI/DbvTF9fcVyj32vHzqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+5eKddGI/28b78UVL5vO7C4bBI2a3tHitEzU+RN6EEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvSKQevPwdZqe2xCUIrsL3mYyozfbRpMAB+FyQiHHNMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00615"],"advisoryURL":"https://wouldntyouliketobeapeppertoo.com/"} diff --git a/attest/verifier/src/lib.rs b/attest/verifier/src/lib.rs index 9df93b3826..5cc818028f 100644 --- a/attest/verifier/src/lib.rs +++ b/attest/verifier/src/lib.rs @@ -392,9 +392,7 @@ mod test { "../data/Dev_AttestationReportSigningCACert.pem" )]; - /// This function provides a recorded response using SW_HARDENING_NEEDED for - /// the INTEL-SA-00334 (LVI) advisory - fn get_334_report() -> VerificationReport { + fn get_ias_report() -> VerificationReport { VerificationReport { sig: VerificationSignature::from(vec![164u8, 105, 80, 134, 234, 173, 20, 233, 176, 192, 25, 170, 37, 122, 173, 94, 120, 55, 98, 212, 183, 187, 59, 31, 240, 29, 174, 87, 172, 54, 130, 3, 13, 59, 86, 196, 184, 158, 92, 217, 70, 198, 227, 246, 144, 228, 146, 81, 119, 241, 39, 69, 6, 15, 100, 53, 62, 28, 53, 194, 127, 121, 234, 167, 234, 97, 45, 195, 138, 118, 4, 207, 165, 114, 78, 22, 85, 167, 77, 74, 135, 25, 115, 81, 97, 222, 27, 227, 110, 0, 210, 66, 161, 3, 166, 188, 114, 73, 50, 201, 9, 138, 41, 27, 144, 163, 91, 255, 221, 42, 194, 86, 198, 103, 130, 155, 90, 64, 61, 249, 48, 106, 69, 205, 196, 118, 35, 153, 243, 197, 124, 204, 79, 205, 125, 181, 12, 190, 13, 25, 192, 30, 53, 190, 149, 11, 230, 63, 116, 15, 55, 231, 226, 169, 242, 126, 181, 8, 81, 98, 140, 166, 26, 138, 66, 4, 170, 178, 111, 158, 129, 140, 217, 171, 157, 212, 23, 225, 191, 137, 187, 254, 127, 111, 138, 209, 39, 250, 26, 250, 96, 217, 48, 113, 99, 175, 107, 179, 17, 213, 139, 116, 98, 193, 149, 89, 202, 239, 248, 42, 155, 39, 67, 173, 142, 59, 191, 54, 26, 196, 19, 67, 25, 159, 210, 199, 112, 156, 218, 117, 76, 1, 30, 251, 240, 15, 57, 141, 41, 242, 70, 42, 134, 68, 224, 117, 137, 47, 152, 246, 220, 192, 32, 201, 242, 58]), chain: vec![ @@ -405,8 +403,6 @@ mod test { } } - // FIXME: Add 334+615 exemplar - /// Ensure a verifier without any status verifiers can pass. #[test] fn no_status_ok() { @@ -417,7 +413,7 @@ mod test { &IasNonce::from_hex("ca1bb26d4a756cabf422206fc1953e4b") .expect("Could not parse nonce hex"), ) - .verify(&get_334_report()) + .verify(&get_ias_report()) .expect("Could not verify IAS report"); } @@ -428,19 +424,19 @@ mod test { 69, 251, 36, 34, 76, 54, 51, 236, 141, 181, 29, 9, 11, 241, 29, 228, 222, 118, 194, 134, 108, 6, 1, 2, 49, 80, 32, 217, 151, 134, 184, 44, ])); - mr_enclave1.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); + mr_enclave1.allow_hardening_advisory("INTEL-SA-00334"); let mut mr_enclave2 = MrEnclaveVerifier::new(MrEnclave::from([ 209, 31, 70, 153, 191, 224, 183, 181, 71, 206, 99, 225, 136, 46, 1, 238, 208, 198, 84, 121, 40, 171, 120, 154, 49, 90, 135, 137, 143, 44, 83, 77, ])); - mr_enclave2.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); + mr_enclave2.allow_hardening_advisory("INTEL-SA-00334"); Verifier::new(TEST_ANCHORS) .expect("Could not initialize new verifier") - .mr_enclave(mr_enclave1.clone()) - .mr_enclave(mr_enclave2.clone()) - .verify(&get_334_report()) + .mr_enclave(mr_enclave1) + .mr_enclave(mr_enclave2) + .verify(&get_ias_report()) .expect("Could not verify IAS report"); } @@ -456,7 +452,7 @@ mod test { 10, 10, ); - mr_signer1.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); + mr_signer1.allow_hardening_advisory("INTEL-SA-00334"); let mut mr_signer2 = MrSignerVerifier::new( MrSigner::from([ 209, 31, 70, 153, 191, 224, 183, 181, 71, 206, 99, 225, 136, 46, 1, 238, 208, 198, @@ -465,14 +461,14 @@ mod test { 1, 1, ); - mr_signer2.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); + mr_signer2.allow_hardening_advisory("INTEL-SA-00334"); Verifier::new(TEST_ANCHORS) .expect("Could not initialize new verifier") - .mr_signer(mr_signer1.clone()) - .mr_signer(mr_signer2.clone()) + .mr_signer(mr_signer1) + .mr_signer(mr_signer2) .debug(true) - .verify(&get_334_report()) + .verify(&get_ias_report()) .expect("Could not verify IAS report"); } } diff --git a/attest/verifier/src/status.rs b/attest/verifier/src/status.rs index 9c65a266db..c3a5070ae4 100644 --- a/attest/verifier/src/status.rs +++ b/attest/verifier/src/status.rs @@ -34,7 +34,7 @@ fn check_ids(quote_status: &IasQuoteResult, config_ids: &[String], sw_ids: &[Str } Err(IasQuoteError::ConfigurationAndSwHardeningNeeded { advisory_ids, .. }) => advisory_ids .iter() - .all(|id| config_ids.contains(id) && sw_ids.contains(id)), + .all(|id| config_ids.contains(id) || sw_ids.contains(id)), Err(_) => false, } } @@ -256,25 +256,10 @@ mod test { use mc_attest_core::VerificationReport; use mc_sgx_types::sgx_measurement_t; - /// Report with OK status const IAS_OK: &str = include_str!("../data/test/ias_ok.json"); - - /// Report with "CONFIGURATION_NEEDED" status const IAS_CONFIG: &str = include_str!("../data/test/ias_config.json"); - - /// Report with "SW_HARDENING_NEEDED" status const IAS_SW: &str = include_str!("../data/test/ias_sw.json"); - - /// Report with "SW_HARDENING_NEEDED" and both 334 and 615 advisories. - const IAS_SW_334_615: &str = include_str!("../data/test/ias_sw_334_615.json"); - - /// Report with "CONFIGURATION_AND_SW_HARDENING_NEEDED" status const IAS_CONFIG_SW: &str = include_str!("../data/test/ias_config_sw.json"); - - /// Report with "CONFIGURATION_AND_SW_HARDENING_NEEDED" status, and both 334 - /// and 615 advisories. - const IAS_CONFIG_SW_334_615: &str = include_str!("../data/test/ias_config_sw_334_615.json"); - const MR_ENCLAVE: sgx_measurement_t = sgx_measurement_t { m: [ 247, 180, 107, 31, 41, 201, 41, 41, 32, 42, 25, 79, 7, 29, 232, 138, 9, 180, 143, 195, @@ -386,26 +371,6 @@ mod test { assert!(verifier.verify(&data)) } - /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE and - /// advisories passes. - #[test] - fn mrenclave_multi_sw_pass() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec![], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(verifier.verify(&data)) - } - /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but /// unexpected advisory fails. #[test] @@ -426,110 +391,10 @@ mod test { assert!(!verifier.verify(&data)) } - /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but - /// unexpected advisory fails. - #[test] - fn mrenclave_sw_empty_fail() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec!["INTEL-SA-00334".to_owned()], - sw_ids: vec![], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_SW.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but - /// unexpected advisory fails. - #[test] - fn mrenclave_multi_sw_empty_fail() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec!["INTEL-SA-00334".to_owned()], - sw_ids: vec![], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but - /// unexpected advisory fails. - #[test] - fn mrenclave_multi_sw_short_fail() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec![], - sw_ids: vec!["INTEL-SA-00334".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and advisory passes when the advisory is given for both. - #[test] - fn mrenclave_config_sw_pass() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec!["INTEL-SA-00239".to_owned()], - sw_ids: vec!["INTEL-SA-00239".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and advisory passes when the advisory is given for both. - #[test] - fn mrenclave_multi_config_sw_pass() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(verifier.verify(&data)) - } - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and config advisory fails. + /// MRENCLAVE and config advisory passes. #[test] - fn mrenclave_config_sw_fail_config() { + fn mrenclave_config_sw_pass_config() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00239".to_owned()], @@ -543,92 +408,13 @@ mod test { }; let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and sw-only advisory allow-listing fails. - #[test] - fn mrenclave_multi_config_sw_fail_no_config() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec![], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and sw-only advisory allow-listing fails. - #[test] - fn mrenclave_multi_config_sw_fail_no_sw() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - sw_ids: vec![], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and insufficient sw advisory allow-listing fails. - #[test] - fn mrenclave_multi_config_sw_fail_short_sw() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - sw_ids: vec!["INTEL-SA-00334".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) + assert!(verifier.verify(&data)) } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and insufficient config advisory allow-listing fails. - #[test] - fn mrenclave_multi_config_sw_fail_short_config() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec!["INTEL-SA-00615".to_owned()], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and hardening advisory fails. + /// MRENCLAVE and hardening advisory passes. #[test] - fn mrenclave_config_sw_fail_sw() { + fn mrenclave_config_sw_pass_sw() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00123".to_owned()], @@ -642,13 +428,13 @@ mod test { }; let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) + assert!(verifier.verify(&data)) } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected /// MRENCLAVE but an unexpected advisory fails. #[test] - fn mrenclave_config_sw_fail_neither() { + fn mrenclave_config_sw_fail() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00123".to_owned()], @@ -665,26 +451,6 @@ mod test { assert!(!verifier.verify(&data)) } - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE but an unexpected advisory fails. - #[test] - fn mrenclave_multi_config_sw_fail_short() { - let verifier = MrEnclaveVerifier { - mr_enclave: MrEnclave::from(&MR_ENCLAVE), - config_ids: vec!["INTEL-SA-00334".to_owned()], - sw_ids: vec!["INTEL-SA-00334".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - /// Ensure an OK result with the expected MRSIGNER, product, and minimum /// version passes. #[test] @@ -838,39 +604,16 @@ mod test { assert!(verifier.verify(&data)) } - /// Ensure a SW_HARDENING_NEEDED result with the expected MRSIGNER, - /// product, and minimum version passes, as long as all advisories are - /// accounted for - #[test] - fn mrsigner_pass_multi_sw() { - let verifier = MrSignerVerifier { - mr_signer: MrSigner::from(&MR_SIGNER), - product_id: 0, - minimum_svn: 0, - config_ids: vec![], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(verifier.verify(&data)) - } - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version succeds if all advisories are - /// accounted for as both config and sw. + /// MRSIGNER, product, and minimum version passes, as long as the + /// advisory is accounted for. #[test] - fn mrsigner_pass_config_sw() { + fn mrsigner_pass_sw_config_via_sw() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, minimum_svn: 0, - config_ids: vec!["INTEL-SA-00239".to_owned()], + config_ids: vec![], sw_ids: vec!["INTEL-SA-00239".to_owned()], }; @@ -885,33 +628,10 @@ mod test { } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version fails if the advisory isn't - /// accounted for as both config and sw. - #[test] - fn mrsigner_fail_config_sw_no_sw() { - let verifier = MrSignerVerifier { - mr_signer: MrSigner::from(&MR_SIGNER), - product_id: 0, - minimum_svn: 0, - config_ids: vec!["INTEL-SA-00239".to_owned()], - sw_ids: vec![], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version fails, if the advisory isn't - /// accounted for in both config and sw. + /// MRSIGNER, product, and minimum version passes, as long as the + /// advisory is accounted for. #[test] - fn mrsigner_fail_config_sw_no_config() { + fn mrsigner_pass_sw_config_via_config() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, @@ -927,157 +647,19 @@ mod test { }; let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version fails if the advisory isn't - /// accounted for as both config and sw. - #[test] - fn mrsigner_fail_multi_config_sw_no_sw() { - let verifier = MrSignerVerifier { - mr_signer: MrSigner::from(&MR_SIGNER), - product_id: 0, - minimum_svn: 0, - config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - sw_ids: vec![], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version fails if the advisory isn't - /// accounted for in both config and sw. - #[test] - fn mrsigner_fail_multi_config_sw_short_sw() { - let verifier = MrSignerVerifier { - mr_signer: MrSigner::from(&MR_SIGNER), - product_id: 0, - minimum_svn: 0, - config_ids: vec!["INTEL-SA-00615".to_owned()], - sw_ids: vec![], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version fails, if the advisory isn't - /// accounted for in both config and sw. - #[test] - fn mrsigner_fail_multi_config_sw_no_config() { - let verifier = MrSignerVerifier { - mr_signer: MrSigner::from(&MR_SIGNER), - product_id: 0, - minimum_svn: 0, - config_ids: vec![], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version fails, if the advisory isn't - /// accounted for in both config and sw. - #[test] - fn mrsigner_fail_multi_config_sw_short_config() { - let verifier = MrSignerVerifier { - mr_signer: MrSigner::from(&MR_SIGNER), - product_id: 0, - minimum_svn: 0, - config_ids: vec!["INTEL-SA-00334".to_owned()], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) + assert!(verifier.verify(&data)) } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected /// MRSIGNER, and minimum version, but the wrong product fails, even if /// the advisory is accounted for. #[test] - fn mrsigner_fail_sw_config_sw_for_product() { + fn mrsigner_fail_sw_config_for_product() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 1, minimum_svn: 0, - config_ids: vec!["INTEL-SA-00239".to_owned()], - sw_ids: vec!["INTEL-SA-00239".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, and minimum version, but the wrong product fails, even if - /// all advisories are accounted for. - #[test] - fn mrsigner_fail_multi_sw_config_sw_for_product() { - let verifier = MrSignerVerifier { - mr_signer: MrSigner::from(&MR_SIGNER), - product_id: 1, - minimum_svn: 0, - config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - }; - - let report = VerificationReport { - sig: Default::default(), - chain: vec![], - http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), - }; - - let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(!verifier.verify(&data)) - } - - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER and product, but an earlier version, fails, even if all - /// advisories are accounted for. - #[test] - fn mrsigner_fail_config_sw_for_version() { - let verifier = MrSignerVerifier { - mr_signer: MrSigner::from(&MR_SIGNER), - product_id: 0, - minimum_svn: 1, - config_ids: vec!["INTEL-SA-00239".to_owned()], + config_ids: vec![], sw_ids: vec!["INTEL-SA-00239".to_owned()], }; @@ -1095,19 +677,19 @@ mod test { /// MRSIGNER and product, but an earlier version, fails, even if the /// advisory is accounted for. #[test] - fn mrsigner_fail_multi_config_sw_for_version() { + fn mrsigner_fail_sw_config_for_version() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, minimum_svn: 1, - config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], - sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00239".to_owned()], }; let report = VerificationReport { sig: Default::default(), chain: vec![], - http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + http_body: IAS_CONFIG_SW.trim().to_owned(), }; let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); diff --git a/consensus/enclave/build.rs b/consensus/enclave/build.rs index 06f7cf9e95..052b7f7881 100644 --- a/consensus/enclave/build.rs +++ b/consensus/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/consensus/enclave/edl/enclave.edl b/consensus/enclave/edl/enclave.edl index 150e9e2467..182c5a0a82 100644 --- a/consensus/enclave/edl/enclave.edl +++ b/consensus/enclave/edl/enclave.edl @@ -11,10 +11,10 @@ enclave { */ public sgx_status_t mobileenclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [out, size=outbuf_len] uint8_t *outbuf, + [user_check] uint8_t *outbuf, size_t outbuf_len, - [out] size_t* outbuf_used, - [in, out] uint64_t* outbuf_retry_id); + [user_check] size_t* outbuf_used, + [user_check] uint64_t* outbuf_retry_id); }; }; diff --git a/consensus/enclave/measurement/build.rs b/consensus/enclave/measurement/build.rs index fba109e9db..41279130fd 100644 --- a/consensus/enclave/measurement/build.rs +++ b/consensus/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; const CONSENSUS_ENCLAVE_PRODUCT_ID: u16 = 1; const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 4; diff --git a/consensus/enclave/measurement/src/lib.rs b/consensus/enclave/measurement/src/lib.rs index 46c4b1f947..b698c7e438 100644 --- a/consensus/enclave/measurement/src/lib.rs +++ b/consensus/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/consensus/enclave/trusted/build.rs b/consensus/enclave/trusted/build.rs index c130d2d1e6..2ff60613e9 100644 --- a/consensus/enclave/trusted/build.rs +++ b/consensus/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/consensus/enclave/trusted/src/lib.rs b/consensus/enclave/trusted/src/lib.rs index 9c4fef6e0e..ab9c333d41 100644 --- a/consensus/enclave/trusted/src/lib.rs +++ b/consensus/enclave/trusted/src/lib.rs @@ -100,16 +100,16 @@ pub extern "C" fn mobileenclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } == 1 + } != 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } == 1 + } != 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/consensus/service/BUILD.md b/consensus/service/BUILD.md index 28df38409b..81555f92e8 100644 --- a/consensus/service/BUILD.md +++ b/consensus/service/BUILD.md @@ -97,8 +97,8 @@ Recommended SDK and package installation: ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" - wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -112,8 +112,8 @@ chmod +x ./sgx_linux_x64_driver_2.11.054c9c4c.bin ./sgx_linux_x64_driver_2.11.054c9c4c.bin # Install the SDK to /opt/intel/sgxsdk -chmod +x ./sgx_linux_x64_sdk_2.17.100.3.bin -./sgx_linux_x64_sdk_2.17.100.3.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.16.100.4.bin +./sgx_linux_x64_sdk_2.16.100.4.bin --prefix=/opt/intel apt install libsgx-uae-service sgx-aesm-service diff --git a/crypto/ake/enclave/src/lib.rs b/crypto/ake/enclave/src/lib.rs index 1c2600daa3..fe62c17d1f 100644 --- a/crypto/ake/enclave/src/lib.rs +++ b/crypto/ake/enclave/src/lib.rs @@ -133,11 +133,7 @@ impl AkeEnclaveState { let mut mr_enclave_verifier = MrEnclaveVerifier::new(report_body.mr_enclave()); // INTEL-SA-00334: LVI hardening is handled via rustc arguments set in // mc-util-build-enclave - // - // INTEL-SA-00615: MMIO Stale Data is handled by using [out] parameters - // in our ECALL/OCALL definitions (EDLs), and only performing direct - // writes aligned to quadword (8B) boundaries (e.g. in ORAMStorage) - mr_enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); + mr_enclave_verifier.allow_hardening_advisory("INTEL-SA-00334"); verifier .mr_enclave(mr_enclave_verifier) diff --git a/docker/Dockerfile-version b/docker/Dockerfile-version index 6c565411ce..0678f6effd 100644 --- a/docker/Dockerfile-version +++ b/docker/Dockerfile-version @@ -1 +1 @@ -1_29 +1_28 diff --git a/docker/install_sgx.sh b/docker/install_sgx.sh index 3960fe81f8..7f39665521 100644 --- a/docker/install_sgx.sh +++ b/docker/install_sgx.sh @@ -24,7 +24,7 @@ cd /tmp ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -59,8 +59,8 @@ apt-get install -yq --no-install-recommends \ # Install *after* pkg-config so that they get registered correctly. # pkg-config gets pulled in transitively via build-essential -chmod +x ./sgx_linux_x64_sdk_2.17.100.3.bin -./sgx_linux_x64_sdk_2.17.100.3.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.16.100.4.bin +./sgx_linux_x64_sdk_2.16.100.4.bin --prefix=/opt/intel # Update .bashrc to source sgxsdk echo 'source /opt/intel/sgxsdk/environment' >> /root/.bashrc diff --git a/fog/distribution/src/config.rs b/fog/distribution/src/config.rs index 20505e1379..806374e7e4 100644 --- a/fog/distribution/src/config.rs +++ b/fog/distribution/src/config.rs @@ -99,8 +99,7 @@ impl Config { ) -> ConnectionResult>>> { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier - .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/fog/ingest/enclave/build.rs b/fog/ingest/enclave/build.rs index 85b5ffa7c3..26c06202d7 100644 --- a/fog/ingest/enclave/build.rs +++ b/fog/ingest/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/ingest/enclave/edl/enclave.edl b/fog/ingest/enclave/edl/enclave.edl index a7b2b96fd0..a6b9108ad2 100644 --- a/fog/ingest/enclave/edl/enclave.edl +++ b/fog/ingest/enclave/edl/enclave.edl @@ -13,10 +13,10 @@ enclave { */ public sgx_status_t ingest_enclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [out, size=outbuf_len] uint8_t *outbuf, + [user_check] uint8_t *outbuf, size_t outbuf_len, - [out] size_t* outbuf_used, - [in, out] uint64_t* outbuf_retry_id); + [user_check] size_t* outbuf_used, + [user_check] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/ingest/enclave/measurement/build.rs b/fog/ingest/enclave/measurement/build.rs index c9410dbcfd..c978fc67e9 100644 --- a/fog/ingest/enclave/measurement/build.rs +++ b/fog/ingest/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; const INGEST_ENCLAVE_PRODUCT_ID: u16 = 4; const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 3; diff --git a/fog/ingest/enclave/measurement/src/lib.rs b/fog/ingest/enclave/measurement/src/lib.rs index 5f0064d12a..22b991df1d 100644 --- a/fog/ingest/enclave/measurement/src/lib.rs +++ b/fog/ingest/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/ingest/enclave/trusted/build.rs b/fog/ingest/enclave/trusted/build.rs index 1b47cb1d60..2622ad4ec6 100644 --- a/fog/ingest/enclave/trusted/build.rs +++ b/fog/ingest/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/ingest/enclave/trusted/src/lib.rs b/fog/ingest/enclave/trusted/src/lib.rs index 7414c5ad47..81d0d0c144 100644 --- a/fog/ingest/enclave/trusted/src/lib.rs +++ b/fog/ingest/enclave/trusted/src/lib.rs @@ -84,16 +84,16 @@ pub extern "C" fn ingest_enclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } == 1 + } != 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } == 1 + } != 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/fog/ledger/enclave/build.rs b/fog/ledger/enclave/build.rs index 8dc6e68629..004600e660 100644 --- a/fog/ledger/enclave/build.rs +++ b/fog/ledger/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/edl/enclave.edl b/fog/ledger/enclave/edl/enclave.edl index f61625a82b..e7ad6a58cb 100644 --- a/fog/ledger/enclave/edl/enclave.edl +++ b/fog/ledger/enclave/edl/enclave.edl @@ -13,10 +13,10 @@ enclave { */ public sgx_status_t ledger_enclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [out, size=outbuf_len] uint8_t *outbuf, + [user_check] uint8_t *outbuf, size_t outbuf_len, - [out] size_t* outbuf_used, - [in, out] uint64_t* outbuf_retry_id); + [user_check] size_t* outbuf_used, + [user_check] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/ledger/enclave/measurement/build.rs b/fog/ledger/enclave/measurement/build.rs index 8f23a1fbd5..46f7402fc0 100644 --- a/fog/ledger/enclave/measurement/build.rs +++ b/fog/ledger/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; const LEDGER_ENCLAVE_PRODUCT_ID: u16 = 2; const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 3; diff --git a/fog/ledger/enclave/measurement/src/lib.rs b/fog/ledger/enclave/measurement/src/lib.rs index 7bf42f751b..6bd930d62d 100644 --- a/fog/ledger/enclave/measurement/src/lib.rs +++ b/fog/ledger/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/ledger/enclave/trusted/build.rs b/fog/ledger/enclave/trusted/build.rs index d71761f769..8509981de6 100644 --- a/fog/ledger/enclave/trusted/build.rs +++ b/fog/ledger/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/trusted/src/lib.rs b/fog/ledger/enclave/trusted/src/lib.rs index 18f1009a9f..58041ca64b 100644 --- a/fog/ledger/enclave/trusted/src/lib.rs +++ b/fog/ledger/enclave/trusted/src/lib.rs @@ -82,16 +82,16 @@ pub extern "C" fn ledger_enclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } == 1 + } != 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } == 1 + } != 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/fog/ledger/server/tests/connection.rs b/fog/ledger/server/tests/connection.rs index 53c601e275..fce0305954 100644 --- a/fog/ledger/server/tests/connection.rs +++ b/fog/ledger/server/tests/connection.rs @@ -160,9 +160,7 @@ fn fog_ledger_merkle_proofs_test(logger: Logger) { // Make ledger enclave client let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_ledger_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisories( - mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, - ); + mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); @@ -354,9 +352,7 @@ fn fog_ledger_key_images_test(logger: Logger) { // Make ledger enclave client let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_ledger_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisories( - mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, - ); + mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/fog/sample-paykit/src/client_builder.rs b/fog/sample-paykit/src/client_builder.rs index cf531c23ff..cd6ce3fa1f 100644 --- a/fog/sample-paykit/src/client_builder.rs +++ b/fog/sample-paykit/src/client_builder.rs @@ -255,8 +255,7 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier - .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); mr_signer_verifier } else { mc_consensus_enclave_measurement::get_mr_signer_verifier(None) @@ -275,9 +274,7 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories( - mc_fog_ingest_enclave_measurement::HARDENING_ADVISORIES, - ); + mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); mr_signer_verifier } else { mc_fog_ingest_enclave_measurement::get_mr_signer_verifier(None) @@ -296,9 +293,7 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories( - mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, - ); + mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); mr_signer_verifier } else { mc_fog_ledger_enclave_measurement::get_mr_signer_verifier(None) @@ -317,8 +312,7 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier - .allow_hardening_advisories(mc_fog_view_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); mr_signer_verifier } else { mc_fog_view_enclave_measurement::get_mr_signer_verifier(None) diff --git a/fog/view/enclave/build.rs b/fog/view/enclave/build.rs index 0df4b8bb9a..04748228e8 100644 --- a/fog/view/enclave/build.rs +++ b/fog/view/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/edl/enclave.edl b/fog/view/enclave/edl/enclave.edl index f6349c2354..80eac0dfa0 100644 --- a/fog/view/enclave/edl/enclave.edl +++ b/fog/view/enclave/edl/enclave.edl @@ -15,10 +15,10 @@ enclave { */ public sgx_status_t viewenclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [out, size=outbuf_len] uint8_t *outbuf, + [user_check] uint8_t *outbuf, size_t outbuf_len, - [out] size_t* outbuf_used, - [in, out] uint64_t* outbuf_retry_id); + [user_check] size_t* outbuf_used, + [user_check] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/view/enclave/measurement/build.rs b/fog/view/enclave/measurement/build.rs index 80368b5d9c..0ce0f08c21 100644 --- a/fog/view/enclave/measurement/build.rs +++ b/fog/view/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; const VIEW_ENCLAVE_PRODUCT_ID: u16 = 3; const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 3; diff --git a/fog/view/enclave/measurement/src/lib.rs b/fog/view/enclave/measurement/src/lib.rs index 94bb6d37fc..3f1221e82c 100644 --- a/fog/view/enclave/measurement/src/lib.rs +++ b/fog/view/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/view/enclave/trusted/build.rs b/fog/view/enclave/trusted/build.rs index ad2076eca5..b03145862c 100644 --- a/fog/view/enclave/trusted/build.rs +++ b/fog/view/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.16.100.4"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/trusted/src/lib.rs b/fog/view/enclave/trusted/src/lib.rs index 2607fb4e28..6710366cc8 100644 --- a/fog/view/enclave/trusted/src/lib.rs +++ b/fog/view/enclave/trusted/src/lib.rs @@ -37,14 +37,14 @@ pub extern "C" fn viewenclave_call( if inbuf.is_null() || outbuf.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 { eprintln!("inbuf or outbuf was out of bounds!"); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } if unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } == 1 + } != 1 { eprintln!("outbuf_used was out of bounds! {:?}", outbuf_used); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; @@ -55,7 +55,7 @@ pub extern "C" fn viewenclave_call( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } == 1 + } != 1 { eprintln!("outbuf_retry_id was out of bounds! {:?}", outbuf_retry_id); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; diff --git a/fog/view/server/tests/smoke_tests.rs b/fog/view/server/tests/smoke_tests.rs index 8b32dc2043..25d02f3109 100644 --- a/fog/view/server/tests/smoke_tests.rs +++ b/fog/view/server/tests/smoke_tests.rs @@ -104,8 +104,7 @@ fn get_test_environment( let grpcio_env = Arc::new(grpcio::EnvBuilder::new().build()); let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_view_enclave_measurement::sigstruct()); - mr_signer_verifier - .allow_hardening_advisories(mc_fog_view_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/jenkins/build-pod.yaml b/jenkins/build-pod.yaml index 0f56bcd0ec..9883127c08 100644 --- a/jenkins/build-pod.yaml +++ b/jenkins/build-pod.yaml @@ -20,7 +20,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: rust-builder-default - image: gcr.io/mobilenode-211420/builder-install:1_29 + image: gcr.io/mobilenode-211420/builder-install:1_28 env: - name: PATH value: "/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64" diff --git a/ledger/sync/src/test_app/main.rs b/ledger/sync/src/test_app/main.rs index b3ffbae81a..e74f502119 100644 --- a/ledger/sync/src/test_app/main.rs +++ b/ledger/sync/src/test_app/main.rs @@ -97,8 +97,7 @@ fn main() { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier - .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/mobilecoind/src/bin/main.rs b/mobilecoind/src/bin/main.rs index 346d8e4e29..3a4f5721af 100644 --- a/mobilecoind/src/bin/main.rs +++ b/mobilecoind/src/bin/main.rs @@ -41,8 +41,7 @@ fn main() { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier - .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/mobilecoind/src/config.rs b/mobilecoind/src/config.rs index fcdfb58889..015cc8065e 100644 --- a/mobilecoind/src/config.rs +++ b/mobilecoind/src/config.rs @@ -176,8 +176,7 @@ impl Config { signature.product_id(), signature.version(), ); - mr_signer_verifier - .allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); + mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); mr_signer_verifier }; diff --git a/ops/Dockerfile-consensus b/ops/Dockerfile-consensus index 601bf23abd..3035f4e70a 100644 --- a/ops/Dockerfile-consensus +++ b/ops/Dockerfile-consensus @@ -19,9 +19,9 @@ RUN apt-get update -q -q && \ # Install SGX Ubuntu/Debian Repo RUN source /etc/os-release && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" && \ + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" && \ + wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" && \ echo "deb [arch=amd64 signed-by=/usr/local/share/apt-keyrings/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list RUN mkdir -p /usr/local/share/apt-keyrings && \ From e3f96a51307fb04818b231eb6835e143dbc5504a Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 20 Jul 2022 11:27:51 -0700 Subject: [PATCH 43/77] Watcher, standalone node_hw operational fixes. (#2266) (#2279) * add .edl and .cargo/config to cache list * fix syntax and image/tag for watcher chart * fix logging and switch from filebeat to logstash for better opensearch support * add flags and options to manual script * remove consensus nodes between upgrades - new chart has topology constraints that can confilct with volume constraints * clean up some node_hw container comments * Update .internal-ci/util/manual_republish_existing_build.sh * change CD trigger to release/v* Co-authored-by: Jason Greathouse Co-authored-by: Remoun Metyas --- .../action.yaml | 6 +- .github/workflows/mobilecoin-dev-cd.yaml | 2 +- .../mobilecoin-workflow-dev-deploy.yaml | 25 ++ .internal-ci/docker/Dockerfile.node_hw | 12 +- .internal-ci/docker/Dockerfile.runtime-base | 5 - .internal-ci/docker/entrypoints/node_hw.sh | 4 +- .../docker/support/node_hw/logstash.conf | 21 ++ .../node_hw/supervisor/conf.d/logstash.conf | 15 + .../watcher/templates/watcher-deployment.yaml | 10 +- .internal-ci/helm/watcher/values.yaml | 6 +- .../util/manual_republish_existing_build.sh | 268 +++++++++++++----- 11 files changed, 279 insertions(+), 95 deletions(-) create mode 100644 .internal-ci/docker/support/node_hw/logstash.conf create mode 100644 .internal-ci/docker/support/node_hw/supervisor/conf.d/logstash.conf diff --git a/.github/actions/mobilecoin-cache-rust-binaries/action.yaml b/.github/actions/mobilecoin-cache-rust-binaries/action.yaml index 59faba9bf5..80ae2891b7 100644 --- a/.github/actions/mobilecoin-cache-rust-binaries/action.yaml +++ b/.github/actions/mobilecoin-cache-rust-binaries/action.yaml @@ -10,10 +10,6 @@ inputs: required: false default: | rust_build_artifacts - # hash_files: - # description: "list of files/globs to hash" - # required: false - # default: "'**/*.rs', '**/*.proto', '**/Cargo.toml'" outputs: cache-hit: @@ -30,4 +26,4 @@ runs: path: ${{ inputs.path }} # Key is a hash of all the .rs, .proto and Cargo.toml files. # if code changes, invalidate cache and rebuild - key: ${{ inputs.cache_buster }}-${{ runner.os }}-${{ hashFiles('**/*.rs', '**/*.proto', '**/Cargo.toml') }}-rust-build-artifacts + key: ${{ inputs.cache_buster }}-${{ runner.os }}-${{ hashFiles('**/*.rs', '**/*.proto', '**/Cargo.toml', '**/*.edl', '.cargo/config') }}-rust-build-artifacts diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index aaeebcf99a..9719a3ca7f 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -12,7 +12,7 @@ env: on: push: branches: - - release/v[0-9]+.[0-9]+.[0-9]+ + - release/v* - feature/* - develop diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml index 1544788456..1ea88adbfc 100644 --- a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -125,8 +125,33 @@ jobs: run: | .internal-ci/util/print_details.sh + # Reset consensus nodes between releases - if there's existing data, we'll + # restore from S3. + reset-releases: + runs-on: [self-hosted, Linux, small] + strategy: + matrix: + chart: + - consensus-node-1 + - consensus-node-2 + - consensus-node-3 + - consensus-node-4 + - consensus-node-5 + steps: + - name: Delete release + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-release-delete + namespace: ${{ inputs.namespace }} + release_name: ${{ matrix.chart }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + setup-environment: runs-on: [self-hosted, Linux, small] + needs: + - reset-releases steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.internal-ci/docker/Dockerfile.node_hw b/.internal-ci/docker/Dockerfile.node_hw index 31e155fc53..f024d180d1 100644 --- a/.internal-ci/docker/Dockerfile.node_hw +++ b/.internal-ci/docker/Dockerfile.node_hw @@ -7,6 +7,14 @@ ARG REPO_ORG=mobilecoin FROM ${REPO_ORG}/runtime-base:latest +# Install logstash to ship logs when used as a standalone container. +ARG LOGSTASH_VERSION=7.16.3 +ARG LOGSTASH_URL=https://artifacts.opensearch.org/logstash/logstash-oss-with-opensearch-output-plugin-${LOGSTASH_VERSION}-linux-x64.tar.gz + +RUN mkdir -p /opt/logstash \ + && curl --retry 5 -sSfL ${LOGSTASH_URL} \ + | tar --strip-components 1 -xvz -C /opt/logstash + # Copy binaries ARG RUST_BIN_PATH=target/release COPY ${RUST_BIN_PATH}/consensus-service /usr/bin/ @@ -29,7 +37,9 @@ COPY ${ORIGIN_DATA_DIR}/ledger /var/lib/mobilecoin/origin_data # Supervisord COPY .internal-ci/docker/support/node_hw/supervisor/conf.d /etc/supervisor/conf.d -COPY .internal-ci/docker/support/node_hw/filebeat.yml /etc/filebeat/filebeat.yml + +# Logstash config +COPY .internal-ci/docker/support/node_hw/logstash.conf /opt/logstash/config/ # Wrapper scripts COPY .internal-ci/docker/support/node_hw/bin /usr/local/bin diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base index ea56da8fce..aba0b51dbd 100644 --- a/.internal-ci/docker/Dockerfile.runtime-base +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -18,10 +18,6 @@ RUN apt-get update \ libpq5 \ jq -# Install Filebeat repo -RUN curl --retry 5 -fL https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add - \ - && echo "deb https://artifacts.elastic.co/packages/oss-8.x/apt stable main" > /etc/apt/sources.list.d/elastic-8.x.list - # Install SGX AESM repo COPY .internal-ci/docker/support/intel-sgx-archive-keyring.gpg /etc/apt/trusted.gpg.d/ RUN echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ focal main" > /etc/apt/sources.list.d/intel-sgx.list @@ -42,7 +38,6 @@ ENV PCE_LOGIC_VERSION=1.13.100.4-focal1 # Install packages RUN apt-get update \ && apt-get install -y \ - filebeat \ sgx-aesm-service=${AESM_VERSION} \ libsgx-epid=${AESM_VERSION} \ libsgx-ae-epid=${AESM_VERSION} \ diff --git a/.internal-ci/docker/entrypoints/node_hw.sh b/.internal-ci/docker/entrypoints/node_hw.sh index 0bddb814d2..c82767ef73 100755 --- a/.internal-ci/docker/entrypoints/node_hw.sh +++ b/.internal-ci/docker/entrypoints/node_hw.sh @@ -124,8 +124,8 @@ then export ES_INDEX=${ES_INDEX:-"filebeat"} export MC_LOG_UDP_JSON=127.0.0.1:16666 - # enable filebeat in supervisord - sed -i '' 's/numprocs=0/numprocs=1/g' /etc/supervisor/conf.d/filebeat.conf + # enable logstash in supervisord + sed -i -e 's/numprocs=0/numprocs=1/g' /etc/supervisor/conf.d/logstash.conf fi # Ledger diff --git a/.internal-ci/docker/support/node_hw/logstash.conf b/.internal-ci/docker/support/node_hw/logstash.conf new file mode 100644 index 0000000000..93d1c63f7b --- /dev/null +++ b/.internal-ci/docker/support/node_hw/logstash.conf @@ -0,0 +1,21 @@ +input { + udp { + host => "127.0.0.1" + port => "16666" + codec => "json" + add_field => { + "mc.network" => "${MC_BRANCH}" + "mc.local_node_id" => "${MC_CLIENT_RESPONDER_ID}" + } + } +} + +output { + opensearch { + hosts => ["${ES_HOST}:${ES_PORT}"] + user => "${ES_USERNAME}" + password => "${ES_PASSWORD}" + index => "${ES_INDEX:logstash}-%{+yyyy.MM.dd}" + action => "create" + } +} diff --git a/.internal-ci/docker/support/node_hw/supervisor/conf.d/logstash.conf b/.internal-ci/docker/support/node_hw/supervisor/conf.d/logstash.conf new file mode 100644 index 0000000000..ab73f34586 --- /dev/null +++ b/.internal-ci/docker/support/node_hw/supervisor/conf.d/logstash.conf @@ -0,0 +1,15 @@ +; Copyright (c) 2018-2022 The MobileCoin Foundation +[program:logstash] +priority=10 +; if we don't start in 60 seconds go to fatal +startsecs=60 +; don't start by default, entrypoint will sed 1 if ES vars are set +numprocs=0 +command=/opt/logstash/bin/logstash + -f /opt/logstash/config/logstash.conf + +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/fd/2 +stderr_logfile_maxbytes=0 +autorestart=true diff --git a/.internal-ci/helm/watcher/templates/watcher-deployment.yaml b/.internal-ci/helm/watcher/templates/watcher-deployment.yaml index 992e313d30..89bd5b700e 100644 --- a/.internal-ci/helm/watcher/templates/watcher-deployment.yaml +++ b/.internal-ci/helm/watcher/templates/watcher-deployment.yaml @@ -20,7 +20,7 @@ spec: template: metadata: annotations: - {{- toYaml .Values.watcher.podAnnotations | nindent 8 }} + {{- toYaml $.Values.watcher.podAnnotations | nindent 8 }} labels: app: watcher instance: {{ .watchername }} @@ -34,7 +34,7 @@ spec: initContainers: - name: watcherdb-restore image: "amazon/aws-cli:2.0.19" - imagePullPolicy: IfNotPresent + imagePullPolicy: Always command: [ "/bin/bash" ] env: {{- if .s3EndpointUrl }} @@ -76,8 +76,8 @@ spec: {{- end}} containers: - name: watcher - image: mobilecoin/watcher:{{ $.Values.images.tag }} - imagePullPolicy: IfNotPresent + image: '{{ $.Values.image.org | default $.Values.image.org }}/{{ $.Values.image.name }}:{{ $.Values.image.tag | default $.Chart.AppVersion }}' + imagePullPolicy: Always command: ["/usr/bin/mc-watcher", "--watcher-db", "/watcher", "--sources-path", "/config/sources.toml", "--store-block-data"] ports: - name: watcher-mgmt @@ -95,7 +95,7 @@ spec: {{- if eq $.Values.watcher.backupEnabled true }} - name: watcherdb-backup image: "amazon/aws-cli:2.0.19" - imagePullPolicy: IfNotPresent + imagePullPolicy: Always command: [ "/bin/bash" ] env: {{- if .s3EndpointUrl }} diff --git a/.internal-ci/helm/watcher/values.yaml b/.internal-ci/helm/watcher/values.yaml index f947fc8e5c..832fc9f83f 100644 --- a/.internal-ci/helm/watcher/values.yaml +++ b/.internal-ci/helm/watcher/values.yaml @@ -1,5 +1,7 @@ # Copyright (c) 2018-2022 The MobileCoin Foundation -images: +image: + org: mobilecoin + name: watcher tag: "" consensusPeers: [] @@ -34,4 +36,4 @@ watcher: podAnnotations: fluentbit.io/include: 'true' # collect logs with fluentbit -watcherNodeSelector: {} \ No newline at end of file +watcherNodeSelector: {} diff --git a/.internal-ci/util/manual_republish_existing_build.sh b/.internal-ci/util/manual_republish_existing_build.sh index ab6d064759..79b6bbd439 100755 --- a/.internal-ci/util/manual_republish_existing_build.sh +++ b/.internal-ci/util/manual_republish_existing_build.sh @@ -6,90 +6,210 @@ # Use with caution. set -e -set -x -echo "no foot-guns, check the tag vars and remove this exit 0 to use!" -exit 0 +usage() +{ +cat << USAGE +Usage: +${0} [--pull] [--push] [--images|--image IMG] [--charts|--chart CHART] --source-tag v1.2.2-dev --target-tag v1.2.3-some-tag + --pull - pull down binaries from source-tag images + --images - build images + --charts - build charts + --push - push images and or charts + --source-tag - source tag to pull binaries from + --target-tag - target tag to build images/charts as + --image "node_hw" - build a specific image + --chart "consensus" - build a specific chart -source_org=mobilecoin -source_tag=v1.2.1-dev +example: pull images and extract binaries + ${0} --source-tag v1.2.2-dev --target-tag v1.2.3-some-tag --pull -push_org=mobilecoin -push_tag=v1.2.2-dev +example: build images for local usage (no push) + ${0} --source-tag v1.2.2-dev --target-tag v1.2.3-some-tag --images -images=(bootstrap-tools fogingest fog-ledger fogreport fogview go-grpc-gateway mobilecoind node_hw fog-test-client) +example: build images and push to image repo + ${0} --source-tag v1.2.2-dev --target-tag v1.2.3-some-tag --images --push -charts=(consensus-node consensus-node-config fog-ingest fog-ingest-config fog-services fog-services-config mc-core-common-config mc-core-dev-env-setup mobilecoind) +example: build charts for local usage (no push) + ${0} --source-tag v1.2.2-dev --target-tag v1.2.3-some-tag --charts -for i in "${images[@]}" -do - docker rm "${i}" || true - docker pull "${source_org}/${i}:${source_tag}" - docker create --name "${i}" "${source_org}/${i}:${source_tag}" -done +example: build charts and push to harbor for local + ${0} --source-tag v1.2.2-dev --target-tag v1.2.3-some-tag --charts --push -mkdir -p target/release -pushd target/release || exit 1 -docker cp "bootstrap-tools:/usr/local/bin/fog-sql-recovery-db-migrations" ./ -docker cp "bootstrap-tools:/usr/local/bin/generate-sample-ledger" ./ -docker cp "bootstrap-tools:/usr/local/bin/sample-keys" ./ -docker cp "bootstrap-tools:/usr/local/bin/fog-distribution" ./ -docker cp "bootstrap-tools:/usr/local/bin/fog_ingest_client" ./ -docker cp "bootstrap-tools:/usr/local/bin/mc-consensus-mint-client" ./ -docker cp "bootstrap-tools:/usr/local/bin/mc-util-seeded-ed25519-key-gen" ./ -docker cp "bootstrap-tools:/usr/local/bin/fog-report-cli" ./ -docker cp "bootstrap-tools:/usr/local/bin/read-pubfile" ./ -docker cp "bootstrap-tools:/usr/local/bin/mc-util-grpc-token-generator" ./ -docker cp "bootstrap-tools:/usr/local/bin/test_client" ./ -docker cp "mobilecoind:/usr/bin/mc-mint-auditor" ./ -docker cp "mobilecoind:/usr/bin/mobilecoind-json" ./ -docker cp "mobilecoind:/enclaves/libingest-enclave.css" ./ -docker cp "fog-ledger:/usr/bin/libledger-enclave.signed.so" ./ -docker cp "fog-ledger:/usr/bin/ledger_server" ./ -docker cp "fog-ledger:/usr/bin/mobilecoind" ./ -docker cp "fog-ledger:/usr/bin/mc-admin-http-gateway" ./ -docker cp "fog-ledger:/usr/bin/mc-ledger-migration" ./ -docker cp "fog-ledger:/usr/bin/mc-util-grpc-admin-tool" ./ -docker cp "fogingest:/usr/bin/libingest-enclave.signed.so" ./ -docker cp "fogingest:/usr/bin/fog_ingest_server" ./ -docker cp "fogreport:/usr/bin/report_server" ./ -docker cp "fogview:/usr/bin/libview-enclave.signed.so" ./ -docker cp "fogview:/usr/bin/fog_view_server" ./ -docker cp "go-grpc-gateway:/usr/bin/go-grpc-gateway" ./grpc-proxy -docker cp "node_hw:/usr/bin/consensus-service" ./ -docker cp "node_hw:/usr/bin/ledger-distribution" ./ -docker cp "node_hw:/usr/bin/ledger-from-archive" ./ -docker cp "node_hw:/usr/bin/libconsensus-enclave.signed.so" ./ -popd || exit 1 - -for i in "${images[@]}" -do - docker build -t "${push_org}/${i}:${push_tag}" \ - --build-arg="GO_BIN_PATH=target/release" \ - --build-arg="REPO_ORG=${push_org}" \ - -f ".internal-ci/docker/Dockerfile.${i}" \ - . -done +example: do it all pull, build, push + ${0} --source-tag v1.2.2-dev --target-tag v1.2.3-some-tag --pull --images --charts --push +USAGE +} -for i in "${images[@]}" +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) do - docker push "${push_org}/${i}:${push_tag}" + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --source-tag ) + source_tag="${2}" + shift 2 + ;; + --target-tag ) + target_tag="${2}" + shift 2 + ;; + --pull) + pull=1 + shift + ;; + --push) + push=1 + shift + ;; + --images) + img=all + shift + ;; + --charts) + chrt=all + shift + ;; + --chart) + chrt="${2}" + shift 2 + ;; + --image) + img="${2}" + shift 2 + ;; + *) + echo "ERROR: unknown option" + usage + exit 1 + ;; + esac done -mkdir -p ".tmp/charts" +is_set source_tag +is_set target_tag -for c in "${charts[@]}" -do - helm dependency update ".internal-ci/helm/${c}" - helm package ".internal-ci/helm/${c}" \ - -d ".tmp/charts" \ - --app-version="${push_tag}" \ - --version="${push_tag}" -done +source_org=mobilecoin -for c in "${charts[@]}" -do - # helm repo add mcf-public --username \ - # https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public - helm cm-push --force ".tmp/charts/${c}-${push_tag}.tgz" mcf-public -done +push_org=mobilecoin +push_tag="${target_tag}" + +images=(bootstrap-tools fogingest fog-ledger fogreport fogview go-grpc-gateway mobilecoind node_hw fog-test-client watcher) + +charts=(consensus-node consensus-node-config fog-ingest fog-ingest-config fog-services fog-services-config mc-core-common-config mc-core-dev-env-setup mobilecoind watcher) + +if [[ -n "${pull}" ]] +then + for i in "${images[@]}" + do + docker rm "${i}" || true + docker pull "${source_org}/${i}:${source_tag}" + docker create --name "${i}" "${source_org}/${i}:${source_tag}" + done + + mkdir -p target/release + pushd target/release || exit 1 + docker cp "bootstrap-tools:/usr/local/bin/fog-sql-recovery-db-migrations" ./ + docker cp "bootstrap-tools:/usr/local/bin/generate-sample-ledger" ./ + docker cp "bootstrap-tools:/usr/local/bin/sample-keys" ./ + docker cp "bootstrap-tools:/usr/local/bin/fog-distribution" ./ + docker cp "bootstrap-tools:/usr/local/bin/fog_ingest_client" ./ + docker cp "bootstrap-tools:/usr/local/bin/mc-consensus-mint-client" ./ + docker cp "bootstrap-tools:/usr/local/bin/mc-util-seeded-ed25519-key-gen" ./ + docker cp "bootstrap-tools:/usr/local/bin/fog-report-cli" ./ + docker cp "bootstrap-tools:/usr/local/bin/read-pubfile" ./ + docker cp "bootstrap-tools:/usr/local/bin/mc-util-grpc-token-generator" ./ + docker cp "bootstrap-tools:/usr/local/bin/test_client" ./ + docker cp "mobilecoind:/usr/bin/mc-mint-auditor" ./ + docker cp "mobilecoind:/usr/bin/mobilecoind-json" ./ + docker cp "mobilecoind:/enclaves/libingest-enclave.css" ./ + docker cp "fog-ledger:/usr/bin/libledger-enclave.signed.so" ./ + docker cp "fog-ledger:/usr/bin/ledger_server" ./ + docker cp "fog-ledger:/usr/bin/mobilecoind" ./ + docker cp "fog-ledger:/usr/bin/mc-admin-http-gateway" ./ + docker cp "fog-ledger:/usr/bin/mc-ledger-migration" ./ + docker cp "fog-ledger:/usr/bin/mc-util-grpc-admin-tool" ./ + docker cp "fogingest:/usr/bin/libingest-enclave.signed.so" ./ + docker cp "fogingest:/usr/bin/fog_ingest_server" ./ + docker cp "fogreport:/usr/bin/report_server" ./ + docker cp "fogview:/usr/bin/libview-enclave.signed.so" ./ + docker cp "fogview:/usr/bin/fog_view_server" ./ + docker cp "go-grpc-gateway:/usr/bin/go-grpc-gateway" ./grpc-proxy + docker cp "node_hw:/usr/bin/consensus-service" ./ + docker cp "node_hw:/usr/bin/ledger-distribution" ./ + docker cp "node_hw:/usr/bin/ledger-from-archive" ./ + docker cp "node_hw:/usr/bin/libconsensus-enclave.signed.so" ./ + docker cp "watcher:/usr/bin/mc-watcher" ./ + popd || exit 1 +fi + +if [[ "${img}" != "all" ]] +then + images=(${img}) +fi + +if [[ -n "${img}" ]] +then + for i in "${images[@]}" + do + echo "-- Building Image ${i}" + docker build -t "${push_org}/${i}:${push_tag}" \ + --build-arg="GO_BIN_PATH=target/release" \ + --build-arg="REPO_ORG=${push_org}" \ + -f ".internal-ci/docker/Dockerfile.${i}" \ + . + done + + if [[ -n "${push}" ]] + then + for i in "${images[@]}" + do + echo "-- Pushing Image ${i}" + docker push "${push_org}/${i}:${push_tag}" + done + fi +fi + +if [[ "${chrt}" != "all" ]] +then + charts=(${chrt}) +fi + +if [[ -n "${chrt}" ]] +then + mkdir -p ".tmp/charts" + + for c in "${charts[@]}" + do + echo "-- Building Chart ${c}" + helm dependency update ".internal-ci/helm/${c}" + helm package ".internal-ci/helm/${c}" \ + -d ".tmp/charts" \ + --app-version="${push_tag}" \ + --version="${push_tag}" + done + + if [[ -n "${push}" ]] + then + for c in "${charts[@]}" + do + echo "-- Pushing Chart ${c}" + # helm repo add mcf-public --username \ + # https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + helm cm-push --force ".tmp/charts/${c}-${push_tag}.tgz" mcf-public + done + fi +fi From f04e009fe769adebad83491f5bf7a3635f8d8ccf Mon Sep 17 00:00:00 2001 From: James Cape Date: Thu, 21 Jul 2022 14:43:21 -0700 Subject: [PATCH 44/77] More changes from 1.2.3 (#2289) * Watcher, standalone node_hw operational fixes. (#2266) * add .edl and .cargo/config to cache list * fix syntax and image/tag for watcher chart * fix logging and switch from filebeat to logstash for better opensearch support * add flags and options to manual script * remove consensus nodes between upgrades - new chart has topology constraints that can confilct with volume constraints * clean up some node_hw container comments * Update .internal-ci/util/manual_republish_existing_build.sh * change CD trigger to release/v* Co-authored-by: Remoun Metyas * Feature/fix var prefixs test client (#2278) * Add MC_ prefix to test_client entrypoint and dockerfile * test_client var changes * test_client add jaeger tracing and fix admin endpoint * test_client add jaeger tracing and fix admin endpoint * fix MC_ vars * Make fog sample paykit support (at least, scan) historical change subaddress (#2281) This should fix a bunch of warnings appearing in the test client when running on testnet, because we ran it for months before the change subaddres was changed from 1 to u64::MAX - 1. * fix build (#2282) Co-authored-by: Chris Beck Co-authored-by: Jason Greathouse Co-authored-by: Remoun Metyas Co-authored-by: Chris Beck --- .../docker/Dockerfile.fog-test-client | 32 ++++++------- .../docker/entrypoints/fog-test-client.sh | 14 +++--- .../templates/fog-test-client-deployment.yaml | 48 ++++++++++++++++--- .internal-ci/helm/fog-test-client/values.yaml | 7 ++- fog/sample-paykit/src/cached_tx_data/mod.rs | 14 ++++-- fog/sample-paykit/src/error.rs | 2 +- 6 files changed, 81 insertions(+), 36 deletions(-) diff --git a/.internal-ci/docker/Dockerfile.fog-test-client b/.internal-ci/docker/Dockerfile.fog-test-client index 6d3ec21d43..06e1e05354 100644 --- a/.internal-ci/docker/Dockerfile.fog-test-client +++ b/.internal-ci/docker/Dockerfile.fog-test-client @@ -28,24 +28,24 @@ COPY ${RUST_BIN_PATH}/mc-util-grpc-token-generator /usr/local/bin/ # Entrypoint COPY .internal-ci/docker/entrypoints/fog-test-client.sh /usr/local/bin/entrypoint.sh -ENV KEY_DIR /keys -ENV CONSENSUS_ENCLAVE_CSS /measurements/consensus-enclave.css -ENV INGEST_ENCLAVE_CSS /measurements/ingest-enclave.css -ENV LEDGER_ENCLAVE_CSS /measurements/ledger-enclave.css -ENV VIEW_ENCLAVE_CSS /measurements/view-enclave.css -ENV ADMIN_LISTEN_URI insecure-mca://0.0.0.0:8001/ -ENV TRANSFER_AMOUNT 100000000000 -ENV CONTINUOUS true -ENV TRANSFER_PERIOD 60 -ENV CONSENSUS_WAIT 15 -ENV NUM_CLIENTS 4 -ENV NO_MEMOS true +ENV MC_KEY_DIR /keys +ENV MC_CONSENSUS_ENCLAVE_CSS /measurements/consensus-enclave.css +ENV MC_INGEST_ENCLAVE_CSS /measurements/ingest-enclave.css +ENV MC_LEDGER_ENCLAVE_CSS /measurements/ledger-enclave.css +ENV MC_VIEW_ENCLAVE_CSS /measurements/view-enclave.css +ENV MC_ADMIN_LISTEN_URI insecure-mca://0.0.0.0:8001/ +ENV MC_TRANSFER_AMOUNT 100000000000 +ENV MC_CONTINUOUS true +ENV MC_TRANSFER_PERIOD 60 +ENV MC_CONSENSUS_WAIT 15 +ENV MC_NUM_CLIENTS 4 +ENV MC_NO_MEMOS true # Required Environment Variables -# CONSENSUS_VALIDATORS - comma separated list of consensus urls. -# FOG_VIEW - fog view url. -# FOG_LEDGER - fog ledger url. -# CLIENT_AUTH_TOKEN_SECRET - if running against a Signal fog instance. +# MC_CONSENSUS - comma separated list of consensus urls. +# MC_FOG_VIEW - fog view url. +# MC_FOG_LEDGER - fog ledger url. +# MC_CLIENT_AUTH_TOKEN_SECRET - if running against a Signal fog instance. # Share key files in /keys VOLUME /keys diff --git a/.internal-ci/docker/entrypoints/fog-test-client.sh b/.internal-ci/docker/entrypoints/fog-test-client.sh index f5b2d735cc..2c401c9f0a 100755 --- a/.internal-ci/docker/entrypoints/fog-test-client.sh +++ b/.internal-ci/docker/entrypoints/fog-test-client.sh @@ -34,9 +34,9 @@ function is_set() fi } -is_set FOG_LEDGER -is_set FOG_VIEW -is_set CONSENSUS_VALIDATORS +is_set MC_FOG_LEDGER +is_set MC_FOG_VIEW +is_set MC_CONSENSUS if [ -n "${CLIENT_AUTH_TOKEN_SECRET}" ] then @@ -45,12 +45,12 @@ then pw=$(mc-util-grpc-token-generator --shared-secret "${CLIENT_AUTH_TOKEN_SECRET}" --username user1 | grep Password: | awk '{print $2}') echo "Re-exporting FOG_LEDGER with user/token" - parse_url "${FOG_LEDGER}" - export FOG_LEDGER="${proto}${us}:${pw}@${host}:${port}/${path}" + parse_url "${MC_FOG_LEDGER}" + export MC_FOG_LEDGER="${proto}${us}:${pw}@${host}:${port}/${path}" echo "Re-exporting FOG_VIEW with user/token" - parse_url "${FOG_VIEW}" - export FOG_VIEW="${proto}${us}:${pw}@${host}:${port}/${path}" + parse_url "${MC_FOG_VIEW}" + export MC_FOG_VIEW="${proto}${us}:${pw}@${host}:${port}/${path}" fi exec "$@" diff --git a/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml b/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml index 8adcc8081f..9bdb3da71d 100644 --- a/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml +++ b/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml @@ -27,7 +27,7 @@ spec: runAsGroup: 1000 containers: - name: fog-test-client - image: "{{ .Values.fogTestClient.image.repository }}:{{ .Values.fogTestClient.image.tag }}" + image: '{{ .Values.fogTestClient.image.repository }}:{{ .Values.fogTestClient.image.tag | default .Chart.AppVersion }}' imagePullPolicy: Always securityContext: capabilities: @@ -35,27 +35,27 @@ spec: - all readOnlyRootFilesystem: true env: - - name: FOG_VIEW + - name: MC_FOG_VIEW valueFrom: configMapKeyRef: name: {{ .Values.fogTestClientConfig.configMap.name }} key: FOG_VIEW - - name: FOG_LEDGER + - name: MC_FOG_LEDGER valueFrom: configMapKeyRef: name: {{ .Values.fogTestClientConfig.configMap.name }} key: FOG_LEDGER - - name: CONSENSUS_VALIDATORS + - name: MC_CONSENSUS valueFrom: configMapKeyRef: name: {{ .Values.fogTestClientConfig.configMap.name }} key: CONSENSUS_VALIDATORS - - name: CONSENSUS_WAIT + - name: MC_CONSENSUS_WAIT valueFrom: configMapKeyRef: name: {{ .Values.fogTestClientConfig.configMap.name }} key: CONSENSUS_WAIT - - name: TRANSFER_AMOUNT + - name: MC_TRANSFER_AMOUNT value: "100000000000" {{- if.Values.fogTestClientConfig.fogClientAuthTokenSecret.enabled }} - name: CLIENT_AUTH_TOKEN_SECRET @@ -86,7 +86,7 @@ spec: resources: {{- toYaml .Values.fogTestClient.resources | nindent 12 }} - name: admin-gateway - image: "{{ .Values.fogTestClient.image.repository }}:{{ .Values.fogTestClient.image.tag }}" + image: '{{ .Values.fogTestClient.image.repository }}:{{ .Values.fogTestClient.image.tag | default .Chart.AppVersion }}' imagePullPolicy: Always securityContext: capabilities: @@ -117,6 +117,40 @@ spec: port: 9090 initialDelaySeconds: 20 periodSeconds: 20 + - name: jaeger-agent + image: jaegertracing/jaeger-agent:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5775 + name: zk-compact-trft + protocol: UDP + - containerPort: 5778 + name: config-rest + protocol: TCP + - containerPort: 6831 + name: jg-compact-trft + protocol: UDP + - containerPort: 6832 + name: jg-binary-trft + protocol: UDP + - containerPort: 14271 + name: admin-http + protocol: TCP + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + args: + - --reporter.grpc.host-port={{ .Values.jaegerTracing.collector }} + - --reporter.type=grpc + - --agent.tags=cluster=undefined,container.name=fog-test-client,deployment.name={{ include "chart.fullname" . }},host.ip=${HOST_IP:},pod.name=${POD_NAME:},pod.namespace={{ .Release.Namespace }} nodeSelector: {{- toYaml .Values.fogTestClient.nodeSelector | nindent 8 }} affinity: diff --git a/.internal-ci/helm/fog-test-client/values.yaml b/.internal-ci/helm/fog-test-client/values.yaml index f3b2c131fb..2aa62413e8 100644 --- a/.internal-ci/helm/fog-test-client/values.yaml +++ b/.internal-ci/helm/fog-test-client/values.yaml @@ -63,10 +63,13 @@ mobileCoinNetwork: configMap: external: true name: mobilecoin-network - # test, prod, alpha... + # test, prod, alpha... network: "" # mc, mcww, signal... partner: "" serviceMonitor: - enabled: true \ No newline at end of file + enabled: true + +jaegerTracing: + collector: 'dns:///jaeger-collector:14250' diff --git a/fog/sample-paykit/src/cached_tx_data/mod.rs b/fog/sample-paykit/src/cached_tx_data/mod.rs index 836ef1c076..8afc2cf3bc 100644 --- a/fog/sample-paykit/src/cached_tx_data/mod.rs +++ b/fog/sample-paykit/src/cached_tx_data/mod.rs @@ -9,7 +9,7 @@ use core::{ }; use displaydoc::Display; use mc_account_keys::{ - AccountKey, PublicAddress, CHANGE_SUBADDRESS_INDEX, DEFAULT_SUBADDRESS_INDEX, + AccountKey, PublicAddress, CHANGE_SUBADDRESS_INDEX, INVALID_SUBADDRESS_INDEX, }; use mc_common::logger::{log, Logger}; @@ -66,7 +66,15 @@ const TELEMETRY_NUM_TXOS_KEY: Key = telemetry_static_key!("num-txos"); /// returned, and the client will not spend this TxOut, and the balance of this /// account will not reflect such TxOut's. This has to cover at least the /// default and change subaddress indexes. -const SUBADDRESS_LOW_RANGE: RangeInclusive = 0..=DEFAULT_SUBADDRESS_INDEX; +/// +/// Note: We also put the historical change subaddress of 1 in this range. +/// This is because we ran the test client as a canary for several months using 1 +/// as the change subaddress, so those accounts now have many subaddress index 1 TxOuts. +/// Adding this to the searched range means that they don't lose all this money, +/// and also silences the warnings when they get TxOuts from fog on "unexpected" +/// subaddresses. +const HISTORICAL_CHANGE_SUBADDRESS_INDEX: u64 = 1; +const SUBADDRESS_LOW_RANGE: RangeInclusive = 0..=HISTORICAL_CHANGE_SUBADDRESS_INDEX; const SUBADDRESS_HIGH_RANGE: Range = CHANGE_SUBADDRESS_INDEX..INVALID_SUBADDRESS_INDEX; /// This object keeps track of all TxOut's that are known to be ours, and which @@ -498,7 +506,7 @@ impl CachedTxData { // Note: this could be caused by a griefing attack, but isn't normally expected log::warn!( self.logger, - "View key scanning failed, fog gave us a TXO that wasn't ours: {}", + "View key scanning failed, fog gave us a TXO that we couldn't establish ownership of: {}", err ); } diff --git a/fog/sample-paykit/src/error.rs b/fog/sample-paykit/src/error.rs index b648222d05..5ca7866f64 100644 --- a/fog/sample-paykit/src/error.rs +++ b/fog/sample-paykit/src/error.rs @@ -33,7 +33,7 @@ pub enum TxOutMatchingError { /// Error decompressing FogTxOut: {0} FogTxOut(FogTxOutError), - /// Subaddress not found + /// Subaddress not found, the TxOut belongs to an unsupported subaddress SubaddressNotFound, } From f38fb217a4251ba30e6fdc37ac617254b2eb13cc Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Mon, 25 Jul 2022 20:01:35 -0500 Subject: [PATCH 45/77] Fix metadata script for new release branch patterns (#2298) --- .github/workflows/mobilecoin-dev-cd.yaml | 10 +- .internal-ci/util/metadata.sh | 151 ++++++++++++++--------- CHANGELOG.md | 7 ++ 3 files changed, 104 insertions(+), 64 deletions(-) diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 9719a3ca7f..e2262a9895 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -12,9 +12,10 @@ env: on: push: branches: - - release/v* - feature/* - - develop + - release/* + tags: + - v[0-9]+* # don't run more than one at a time for a branch/tag concurrency: mobilecoin-dev-cd-${{ github.ref }} @@ -27,7 +28,6 @@ jobs: name: 👾 Environment Info 👾 runs-on: [self-hosted, Linux, small] outputs: - branch: ${{ steps.meta.outputs.branch }} namespace: ${{ steps.meta.outputs.namespace }} tag: ${{ steps.meta.outputs.tag }} docker_tag: ${{ steps.meta.outputs.docker_tag }} @@ -330,8 +330,8 @@ jobs: REPO_ORG=${{ env.DOCKER_ORG }} RUST_BIN_PATH=rust_build_artifacts GO_BIN_PATH=go_build_artifacts - cache-from: type=registry,ref=${{ env.DOCKER_ORG }}/${{ matrix.image }}:buildcache-${{ needs.generate-metadata.outputs.branch }} - cache-to: type=registry,ref=${{ env.DOCKER_ORG }}/${{ matrix.image }}:buildcache-${{ needs.generate-metadata.outputs.branch }} + cache-from: type=registry,ref=${{ env.DOCKER_ORG }}/${{ matrix.image }}:buildcache-${{ needs.generate-metadata.outputs.namespace }} + cache-to: type=registry,ref=${{ env.DOCKER_ORG }}/${{ matrix.image }}:buildcache-${{ needs.generate-metadata.outputs.namespace }} context: . file: .internal-ci/docker/Dockerfile.${{ matrix.image }} labels: ${{ steps.docker_meta.outputs.labels }} diff --git a/.internal-ci/util/metadata.sh b/.internal-ci/util/metadata.sh index 8e89ef6395..624a2dde8b 100755 --- a/.internal-ci/util/metadata.sh +++ b/.internal-ci/util/metadata.sh @@ -8,14 +8,6 @@ set -e export TMPDIR=".tmp" -error_exit() -{ - msg="${1}" - - echo "${msg}" 1>&2 - exit 1 -} - is_set() { var_name="${1}" @@ -25,66 +17,107 @@ is_set() fi } +normalize_ref_name() +{ + name="${1}" + + echo "${name}" | sed -E 's/(feature|release)\///' | sed -e 's/[._/]/-/g' +} + # check for github reference variables. is_set GITHUB_REF_NAME is_set GITHUB_REF_TYPE is_set GITHUB_RUN_NUMBER is_set GITHUB_SHA -if [[ "${GITHUB_REF_TYPE}" != "branch" ]] -then - echo "not a 'branch' reference type - ${GITHUB_REF_TYPE}" - exit 1 -fi - -# Remove leading branch designator. -branch=$(echo "${GITHUB_REF_NAME}" | sed -E 's/(feature|deploy|release)\///') - -if [[ "${GITHUB_REF_NAME}" =~ ^release/ ]] -then - echo "Release Branch detected: ${GITHUB_REF_NAME}" - version="${branch}" - # check to see if remaining version is basic semver - if [[ ! "${version}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] - then - echo "release/ not basic semver: ${version}" - echo "branch name invalid" +# Make sure prefix is less that 18 characters or k8s limits. +namespace_prefix="mc" +branch="${GITHUB_REF_NAME}" +sha="sha-${GITHUB_SHA:0:8}" + +case "${GITHUB_REF_TYPE}" in + tag) + # check for valid tag and set outputs + version="${GITHUB_REF_NAME}" + if [[ ! "${version}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+.* ]] + then + echo "GitHub Tag ${version} is not valid semver." + exit 1 + fi + + if [[ "${version}" =~ - ]] + then + echo "Found pre-release tag." + # set artifact tag + tag="${version}" + docker_tag="type=raw,value=${version},priority=20%0Atype=raw,value=${version}.${GITHUB_RUN_NUMBER}.${sha},priority=10" + else + echo "Found release tag." + # set artifact tag + tag="${version}-dev" + #set docker metadata action compatible tag. Short tag + metadata tag. + docker_tag="type=raw,value=${version}-dev,priority=20%0Atype=raw,value=${version}-dev.${GITHUB_RUN_NUMBER}.${sha},priority=10" + fi + + normalized_tag=$(normalize_ref_name "${tag}") + + namespace="${namespace_prefix}-${normalized_tag}" + + # just make sure we have these set to avoid weird edge cases. + is_set tag + is_set docker_tag + ;; + branch) + # Check for valid branches. Using case if we want add more or split branch types later. + case "${branch}" in + release/*|feature/*) + # All branch builds will just have a "dummy" tag. + version="v0" + + echo "Clean up branch. Remove feature|deploy|release prefix and replace ._/ with -" + normalized_branch="$(normalize_ref_name "${branch}")" + + # Check and truncate branch name if total tag length exceeds the 63 character K8s label value limit. + label_limit=63 + version_len=${#version} + sha_len=${#sha} + run_number_len=${#GITHUB_RUN_NUMBER} + # number of separators in tag + dots=3 + + cutoff=$((label_limit - version_len - sha_len - run_number_len - dots)) + + if [[ ${#normalized_branch} -gt ${cutoff} ]] + then + cut_branch=$(echo "${normalized_branch}" | cut -c -${cutoff}) + echo "Your branch name ${normalized_branch} + metadata exceeds the maximum length for K8s identifiers, truncating to ${cut_branch}" + normalized_branch="${cut_branch}" + fi + + echo "Before: '${branch}'" + echo "After: '${normalized_branch}'" + + # Set artifact tag + tag="${version}-${normalized_branch}.${GITHUB_RUN_NUMBER}.${sha}" + # Set docker metadata action compatible tag + docker_tag="type=raw,value=${tag}" + # Set namespace from normalized branch value + namespace="${namespace_prefix}-${normalized_branch}" + ;; + *) + echo "Branch: ${branch} is not a release/ or feature/ branch" + exit 1 + ;; + esac + ;; + *) + echo "${GITHUB_REF_TYPE} is an unknown GitHub Reference Type" exit 1 - fi -else - version="v0.0.0" - echo "Not a release branch, set default version of v0.0.0" -fi - -echo "Clean up branch. Remove feature|deploy|release prefix and replace ._/ with - '${branch}'" -branch=$(echo "${branch}" | sed -e 's/[._/]/-/g') -sha="${GITHUB_SHA:0:8}" - -# Set tag/docker_tag -tag="${version}-${branch}.${GITHUB_RUN_NUMBER}.sha-${sha}" -docker_tag="type=raw,value=${tag}" - -# override tag/docker_tag for release -if [[ "${GITHUB_REF_NAME}" =~ ^release/ ]] -then - docker_tag="type=raw,value=${version}-dev,priority=20%0Atype=raw,value=${version}-${GITHUB_RUN_NUMBER}.sha-${sha},priority=10" - tag=${version}-dev -fi - -# Get commit flags -if [ -f "${GITHUB_EVENT_PATH}" ] -then - # override tag if commit message has [tag="tag"] - msg=$(jq -r '.head_commit.message' < "${GITHUB_EVENT_PATH}") - if [[ "${msg}" =~ /\[tag=.*\]/ ]] - then - tag=$(echo "${msg}" | sed -r 's/.*\[use=(.*)\].*/\1/') - fi -fi + ;; +esac echo "::set-output name=version::${version}" -echo "::set-output name=branch::${branch}" -echo "::set-output name=namespace::mc-${branch}" +echo "::set-output name=namespace::${namespace}" echo "::set-output name=sha::${sha}" echo "::set-output name=tag::${tag}" echo "::set-output name=docker_tag::${docker_tag}" diff --git a/CHANGELOG.md b/CHANGELOG.md index dc4761032d..671919698b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The crates in this repository do not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) at this time. +## [unreleased] + +### Fixed + +#### CI/CD + +- Fix metadata script for new release branch patterns. ([#2298]) ## [1.2.2] - 2022-06-09 From 5ccb18921aac5e329e1b9db8c32431d7ec18eb77 Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 25 Jul 2022 18:15:40 -0700 Subject: [PATCH 46/77] Branch and prep 2.0.0 release (#2275) * Revert "Revert SGX 2.17 Changes (#2202)" This reverts commit 06e09b3e0ffac7f8b6845c9e09bfe992f72a5f59. * Update CHANGELOG.md * Bump version to 2.0.0, make deps parsimonious. * Bump enclave SVNs * Make install_sgx.sh executable. * Watcher, standalone node_hw operational fixes. (#2266) * add .edl and .cargo/config to cache list * fix syntax and image/tag for watcher chart * fix logging and switch from filebeat to logstash for better opensearch support * add flags and options to manual script * remove consensus nodes between upgrades - new chart has topology constraints that can confilct with volume constraints * clean up some node_hw container comments * Update .internal-ci/util/manual_republish_existing_build.sh * change CD trigger to release/v* Co-authored-by: Remoun Metyas * Switch the CD docker image to 0.0.14 * Update mob/mobconf to handle dockerhub. * Apply suggestions from code review Co-authored-by: Nick Santana * Update gradle package version to 2.0.0 Co-authored-by: Jason Greathouse Co-authored-by: Remoun Metyas Co-authored-by: Nick Santana --- .circleci/config.yml | 2 +- .github/workflows/mobilecoin-dev-cd.yaml | 2 +- .internal-ci/docker/Dockerfile.runtime-base | 5 +- .mobconf | 4 +- CHANGELOG.md | 17 +- Cargo.lock | 324 ++++++------ account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- .../android-bindings/publish.gradle | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- attest/verifier/README.md | 3 +- .../data/test/ias_config_sw_334_615.json | 1 + attest/verifier/data/test/ias_sw_334_615.json | 1 + attest/verifier/src/lib.rs | 28 +- attest/verifier/src/status.rs | 463 +++++++++++++++++- common/Cargo.toml | 9 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/build.rs | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/edl/enclave.edl | 6 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/measurement/build.rs | 4 +- consensus/enclave/measurement/src/lib.rs | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 ++-- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/enclave/trusted/build.rs | 2 +- consensus/enclave/trusted/src/lib.rs | 6 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/BUILD.md | 8 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/ake/enclave/src/lib.rs | 6 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- docker/Dockerfile-version | 2 +- docker/install_sgx.sh | 6 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/distribution/src/config.rs | 3 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/build.rs | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/edl/enclave.edl | 6 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/measurement/build.rs | 4 +- fog/ingest/enclave/measurement/src/lib.rs | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 ++-- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/enclave/trusted/build.rs | 2 +- fog/ingest/enclave/trusted/src/lib.rs | 6 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/build.rs | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/edl/enclave.edl | 6 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/measurement/build.rs | 4 +- fog/ledger/enclave/measurement/src/lib.rs | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 ++-- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/enclave/trusted/build.rs | 2 +- fog/ledger/enclave/trusted/src/lib.rs | 6 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/server/tests/connection.rs | 8 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sample-paykit/src/client_builder.rs | 14 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/build.rs | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/edl/enclave.edl | 6 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/measurement/build.rs | 4 +- fog/view/enclave/measurement/src/lib.rs | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 ++-- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/enclave/trusted/build.rs | 2 +- fog/view/enclave/trusted/src/lib.rs | 6 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- fog/view/server/tests/smoke_tests.rs | 3 +- jenkins/build-pod.yaml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- ledger/sync/src/test_app/main.rs | 3 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 2 +- mob | 50 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- mobilecoind/src/bin/main.rs | 3 +- mobilecoind/src/config.rs | 3 +- ops/Dockerfile-consensus | 4 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 9 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/cli/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 226 files changed, 1100 insertions(+), 709 deletions(-) create mode 100644 attest/verifier/data/test/ias_config_sw_334_615.json create mode 100644 attest/verifier/data/test/ias_sw_334_615.json mode change 100644 => 100755 docker/install_sgx.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 7cc3a88c30..670bde1f90 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ version: 2.1 defaults: - builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_28 + builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_29 android-bindings-builder: &android-bindings-builder gcr.io/mobilenode-211420/android-bindings-builder:1_4 default-xcode-version: &default-xcode-version "12.0.0" diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index e2262a9895..02dd9fae45 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -60,7 +60,7 @@ jobs: build-rust-hardware-projects: runs-on: [self-hosted, Linux, large] container: - image: mobilecoin/rust-sgx-base@sha256:6e9ec00ee70045392599cc3c25e74184e072e3d5a5d7abdd713c25207043afda + image: mobilecoin/rust-sgx-base@v0.0.14 env: ENCLAVE_SIGNING_KEY_PATH: ${{ github.workspace }}/.tmp/enclave_signing.pem MINTING_TRUST_ROOT_PUBLIC_KEY_PEM: ${{ github.workspace }}/.tmp/minting_trust_root.public.pem diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base index aba0b51dbd..8fff105b34 100644 --- a/.internal-ci/docker/Dockerfile.runtime-base +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -31,9 +31,10 @@ ENV LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" # libsgx-enclave-common libsgx-epid libsgx-launch libsgx-pce-logic libsgx-urts # sgx-aesm-service # Use `apt show -a sgx-aesm-service` to find version -ENV AESM_VERSION=2.16.100.4-focal1 +ENV AESM_VERSION=2.17.100.3-focal1 # Use `apt show -a libsgx-pce-logic` to find the version thats compatible with aesm. -ENV PCE_LOGIC_VERSION=1.13.100.4-focal1 +ENV PCE_LOGIC_VERSION=1.14.100.3-focal1 + # Install packages RUN apt-get update \ diff --git a/.mobconf b/.mobconf index 1272ffc339..27dde1b5ce 100644 --- a/.mobconf +++ b/.mobconf @@ -1,4 +1,4 @@ [image] -dockerfile = docker/Dockerfile +dockerfile-version = v0.0.14 target = builder-install -repository = gcr.io/mobilenode-211420/ +repository = mobilecoin diff --git a/CHANGELOG.md b/CHANGELOG.md index 671919698b..b392391818 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The crates in this repository do not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) at this time. -## [unreleased] +## [2.0.0] - 2022-07-25 ### Fixed @@ -13,16 +13,19 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem - Fix metadata script for new release branch patterns. ([#2298]) -## [1.2.2] - 2022-06-09 +### Security + +- Bump SGX to 2.17, mitigate INTEL-SA-00615 + + +## [1.2.2] - 2022-06-17 ### Changed - Update CI deployments to use zerossl instead of letsencrypt -## [1.2.1] - YANKED - -[This was never released] +## [1.2.1] - UNRELEASED ### Changed @@ -35,9 +38,7 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem - Fix panic when consensus service is configured for multiple tokens but still running in MOB-only block-version 0 mode. -## [1.2.0] - YANKED - -[This was never released] +## [1.2.0] - UNRELEASED ### Added diff --git a/Cargo.lock b/Cargo.lock index deb8ba5745..1efa844487 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2015,7 +2015,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "cbindgen", @@ -2197,7 +2197,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "criterion", "curve25519-dalek", @@ -2225,7 +2225,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "1.2.2" +version = "2.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2241,7 +2241,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -2256,7 +2256,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "anyhow", @@ -2294,7 +2294,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "bs58", "cargo-emit", @@ -2330,7 +2330,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "aes-gcm", @@ -2355,7 +2355,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "cargo-emit", @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "bincode", @@ -2405,7 +2405,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2418,7 +2418,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2438,7 +2438,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -2449,7 +2449,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2459,7 +2459,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2484,7 +2484,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.2" +version = "2.0.0" dependencies = [ "backtrace", "binascii", @@ -2521,7 +2521,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "cookie", @@ -2550,7 +2550,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2561,7 +2561,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "futures", @@ -2582,7 +2582,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "hex", @@ -2628,7 +2628,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2636,7 +2636,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "hex", @@ -2672,7 +2672,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2685,7 +2685,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2707,7 +2707,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2736,7 +2736,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "1.2.2" +version = "2.0.0" dependencies = [ "crossbeam-channel", "maplit", @@ -2759,7 +2759,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "mc-common", @@ -2771,7 +2771,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "chrono", @@ -2833,7 +2833,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "clap 3.1.18", @@ -2858,7 +2858,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2878,7 +2878,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "digest 0.10.3", @@ -2894,7 +2894,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2907,7 +2907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.2" +version = "2.0.0" dependencies = [ "proc-macro2", "quote", @@ -2916,7 +2916,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2924,7 +2924,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2933,7 +2933,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2941,7 +2941,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "blake2", "digest 0.10.3", @@ -2950,7 +2950,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -2983,7 +2983,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "displaydoc", @@ -2997,7 +2997,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3011,7 +3011,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "aes-gcm", @@ -3032,7 +3032,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3043,7 +3043,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3056,7 +3056,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3068,7 +3068,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3079,7 +3079,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3090,7 +3090,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -3122,7 +3122,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3154,7 +3154,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "cookie", @@ -3178,7 +3178,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "1.2.2" +version = "2.0.0" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3217,7 +3217,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "criterion", @@ -3252,7 +3252,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3269,7 +3269,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3277,7 +3277,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3310,7 +3310,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3323,7 +3323,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "dirs", @@ -3380,7 +3380,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.2" +version = "2.0.0" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3396,7 +3396,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "grpcio", @@ -3417,7 +3417,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3446,7 +3446,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3464,7 +3464,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3472,7 +3472,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3495,7 +3495,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3508,7 +3508,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3561,7 +3561,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3577,7 +3577,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -3606,14 +3606,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3624,7 +3624,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "aligned-cmov", @@ -3641,7 +3641,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "lazy_static", "mc-common", @@ -3649,7 +3649,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3687,7 +3687,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3701,7 +3701,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "futures", @@ -3720,7 +3720,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-util-serial", "prost", @@ -3729,7 +3729,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "binascii", @@ -3751,7 +3751,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "grpcio", @@ -3768,7 +3768,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3804,7 +3804,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3814,7 +3814,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3832,7 +3832,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3840,7 +3840,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3886,7 +3886,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3907,7 +3907,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3918,7 +3918,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3933,7 +3933,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "1.2.2" +version = "2.0.0" dependencies = [ "chrono", "clap 3.1.18", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3997,7 +3997,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4028,7 +4028,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.2" +version = "2.0.0" dependencies = [ "crc", "displaydoc", @@ -4048,7 +4048,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-common", "mc-util-uri", @@ -4056,7 +4056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "1.2.2" +version = "2.0.0" dependencies = [ "grpcio", "mc-attest-core", @@ -4076,7 +4076,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "criterion", @@ -4111,7 +4111,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4129,7 +4129,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4137,7 +4137,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4159,7 +4159,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4172,7 +4172,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4191,7 +4191,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -4214,7 +4214,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4264,7 +4264,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "lazy_static", @@ -4290,7 +4290,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "dirs", @@ -4312,7 +4312,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "mc-api", @@ -4323,7 +4323,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4336,7 +4336,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "1.2.2" +version = "2.0.0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4367,7 +4367,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4400,7 +4400,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "futures", @@ -4414,7 +4414,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4478,7 +4478,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "futures", @@ -4496,7 +4496,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4571,7 +4571,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "1.2.2" +version = "2.0.0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4603,7 +4603,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "1.2.2" +version = "2.0.0" dependencies = [ "grpcio", "hex", @@ -4626,7 +4626,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cc", "lazy_static", @@ -4636,7 +4636,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4644,7 +4644,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4653,7 +4653,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4661,7 +4661,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4670,21 +4670,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4695,7 +4695,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4711,7 +4711,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4721,18 +4721,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-urts" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-common", "mc-sgx-build", @@ -4743,7 +4743,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "hex", "mc-account-keys", @@ -4755,7 +4755,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-account-keys", "mc-api", @@ -4765,7 +4765,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-util-test-vector", "serde", @@ -4774,7 +4774,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "1.2.2" +version = "2.0.0" dependencies = [ "hex", "mc-account-keys", @@ -4789,7 +4789,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "1.2.2" +version = "2.0.0" dependencies = [ "hex", "mc-account-keys", @@ -4811,7 +4811,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -4853,7 +4853,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4870,7 +4870,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "1.2.2" +version = "2.0.0" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4897,7 +4897,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "hex", @@ -4906,7 +4906,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4922,7 +4922,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4930,7 +4930,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "json", @@ -4938,7 +4938,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -4949,7 +4949,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cc", @@ -4960,7 +4960,7 @@ dependencies = [ [[package]] name = "mc-util-cli" -version = "0.1.0" +version = "2.0.0" dependencies = [ "clap 3.1.18", "mc-util-build-info", @@ -4968,7 +4968,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "binascii", @@ -4980,18 +4980,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-util-from-random" -version = "1.2.2" +version = "2.0.0" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "hex", @@ -5010,7 +5010,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "clap 3.1.18", @@ -5044,7 +5044,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -5055,7 +5055,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "hex", @@ -5066,11 +5066,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-util-keyfile" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "clap 3.1.18", @@ -5098,7 +5098,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5108,7 +5108,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "1.2.2" +version = "2.0.0" dependencies = [ "proc-macro2", "quote", @@ -5117,7 +5117,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "1.2.2" +version = "2.0.0" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5125,7 +5125,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "1.2.2" +version = "2.0.0" dependencies = [ "chrono", "grpcio", @@ -5138,7 +5138,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "1.2.2" +version = "2.0.0" dependencies = [ "itertools", "mc-sgx-css", @@ -5146,7 +5146,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "generic-array", "prost", @@ -5156,7 +5156,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "hex", @@ -5169,7 +5169,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.2" +version = "2.0.0" dependencies = [ "prost", "serde", @@ -5178,7 +5178,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5189,7 +5189,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "itertools", @@ -5203,7 +5203,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "1.2.2" +version = "2.0.0" dependencies = [ "serde", "serde_json", @@ -5211,7 +5211,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "1.2.2" +version = "2.0.0" dependencies = [ "proc-macro2", "quote", @@ -5220,7 +5220,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "displaydoc", @@ -5238,7 +5238,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "1.2.2" +version = "2.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5282,7 +5282,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 73c7e38a66..3de64701df 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index a084160496..ab5873d6b7 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index d198ecb56f..1a9ceb5937 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index 06e36ae11a..19cfd1da82 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/android-bindings/lib-wrapper/android-bindings/publish.gradle b/android-bindings/lib-wrapper/android-bindings/publish.gradle index 0be9afcde8..c08f8f86a6 100644 --- a/android-bindings/lib-wrapper/android-bindings/publish.gradle +++ b/android-bindings/lib-wrapper/android-bindings/publish.gradle @@ -1,6 +1,6 @@ apply plugin: 'maven-publish' -version '1.2.2' +version '2.0.0' group 'com.mobilecoin' Properties properties = new Properties() diff --git a/api/Cargo.toml b/api/Cargo.toml index 533acb6d12..bfad2571fa 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index d0f1799f18..5c36d80913 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index fa62084037..b00c716a99 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index 8d7cb8bb5e..33f1f65eeb 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index 1d6fa33784..31e9fad637 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index 840aaa3fd8..6b27d45e77 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index 5066410106..fa47333b4c 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index 6b444b9486..d9156cb4b8 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index 347f1048ec..8366237bad 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/verifier/README.md b/attest/verifier/README.md index 8a9b5daaff..e21919cffa 100644 --- a/attest/verifier/README.md +++ b/attest/verifier/README.md @@ -14,7 +14,8 @@ use mc_util_encodings::FromHex; // Create a new status verifier for a MRENCLAVE measurement value let mut enclave_verifier = MrEnclaveVerifier::new(MrEnclave::from_hex("BEEFCAFEDEADBEEFCAFEBEEF")); // Whitelist the LVI hardening advisory (assume the BEEF... enclave is hardened) -enclave_verifier.allow_hardening_advisory("INTEL-SA-00334"); +// Whitelist the MMIO hardening advisory (assume the enclave uses [out] and 8-byte aligned writes) +enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); // Construct a new verifier using hard-coded IAS signing certificates let mut verifier = Verifier::default(); diff --git a/attest/verifier/data/test/ias_config_sw_334_615.json b/attest/verifier/data/test/ias_config_sw_334_615.json new file mode 100644 index 0000000000..c85c879900 --- /dev/null +++ b/attest/verifier/data/test/ias_config_sw_334_615.json @@ -0,0 +1 @@ +{"nonce":"b6cb5af2a11cfe2f9c19b944b32c3aac","id":"329097353241719791874006404947982878982","timestamp":"2019-06-19T22:11:17.616333","version":4,"isvEnclaveQuoteStatus":"CONFIGURATION_AND_SW_HARDENING_NEEDED","platformInfoBlob":"1502006504000900000606020401010000000000000000000008000009000000020000000000000B2E053D80C01A089F0FA1A633CC53611B1A0036EDB3F1F2BE80EC8EBFBE7068A89AB679C2AA72E244115A57E18CA3A6F7447E56FBECE241C99F8656F14398E5971C","isvEnclaveQuoteBody":"AgAAAC4LAAAIAAcAAAAAALaz7oQLP7WmorFMVCIaq2p5e9wQ7TqvPTsPR5QKGmaqBQYCBP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAPe0ax8pySkpICoZTwcd6IoJtI/DbvTF9fcVyj32vHzqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+5eKddGI/28b78UVL5vO7C4bBI2a3tHitEzU+RN6EEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvSKQevPwdZqe2xCUIrsL3mYyozfbRpMAB+FyQiHHNMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00615"],"advisoryURL":"https://wouldntyouliketobeapeppertoo.com/"} diff --git a/attest/verifier/data/test/ias_sw_334_615.json b/attest/verifier/data/test/ias_sw_334_615.json new file mode 100644 index 0000000000..c1b1437df4 --- /dev/null +++ b/attest/verifier/data/test/ias_sw_334_615.json @@ -0,0 +1 @@ +{"nonce":"b6cb5af2a11cfe2f9c19b944b32c3aac","id":"329097353241719791874006404947982878982","timestamp":"2019-06-19T22:11:17.616333","version":4,"isvEnclaveQuoteStatus":"SW_HARDENING_NEEDED","platformInfoBlob":"1502006504000900000606020401010000000000000000000008000009000000020000000000000B2E053D80C01A089F0FA1A633CC53611B1A0036EDB3F1F2BE80EC8EBFBE7068A89AB679C2AA72E244115A57E18CA3A6F7447E56FBECE241C99F8656F14398E5971C","isvEnclaveQuoteBody":"AgAAAC4LAAAIAAcAAAAAALaz7oQLP7WmorFMVCIaq2p5e9wQ7TqvPTsPR5QKGmaqBQYCBP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAPe0ax8pySkpICoZTwcd6IoJtI/DbvTF9fcVyj32vHzqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+5eKddGI/28b78UVL5vO7C4bBI2a3tHitEzU+RN6EEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvSKQevPwdZqe2xCUIrsL3mYyozfbRpMAB+FyQiHHNMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00615"],"advisoryURL":"https://wouldntyouliketobeapeppertoo.com/"} diff --git a/attest/verifier/src/lib.rs b/attest/verifier/src/lib.rs index 5cc818028f..9df93b3826 100644 --- a/attest/verifier/src/lib.rs +++ b/attest/verifier/src/lib.rs @@ -392,7 +392,9 @@ mod test { "../data/Dev_AttestationReportSigningCACert.pem" )]; - fn get_ias_report() -> VerificationReport { + /// This function provides a recorded response using SW_HARDENING_NEEDED for + /// the INTEL-SA-00334 (LVI) advisory + fn get_334_report() -> VerificationReport { VerificationReport { sig: VerificationSignature::from(vec![164u8, 105, 80, 134, 234, 173, 20, 233, 176, 192, 25, 170, 37, 122, 173, 94, 120, 55, 98, 212, 183, 187, 59, 31, 240, 29, 174, 87, 172, 54, 130, 3, 13, 59, 86, 196, 184, 158, 92, 217, 70, 198, 227, 246, 144, 228, 146, 81, 119, 241, 39, 69, 6, 15, 100, 53, 62, 28, 53, 194, 127, 121, 234, 167, 234, 97, 45, 195, 138, 118, 4, 207, 165, 114, 78, 22, 85, 167, 77, 74, 135, 25, 115, 81, 97, 222, 27, 227, 110, 0, 210, 66, 161, 3, 166, 188, 114, 73, 50, 201, 9, 138, 41, 27, 144, 163, 91, 255, 221, 42, 194, 86, 198, 103, 130, 155, 90, 64, 61, 249, 48, 106, 69, 205, 196, 118, 35, 153, 243, 197, 124, 204, 79, 205, 125, 181, 12, 190, 13, 25, 192, 30, 53, 190, 149, 11, 230, 63, 116, 15, 55, 231, 226, 169, 242, 126, 181, 8, 81, 98, 140, 166, 26, 138, 66, 4, 170, 178, 111, 158, 129, 140, 217, 171, 157, 212, 23, 225, 191, 137, 187, 254, 127, 111, 138, 209, 39, 250, 26, 250, 96, 217, 48, 113, 99, 175, 107, 179, 17, 213, 139, 116, 98, 193, 149, 89, 202, 239, 248, 42, 155, 39, 67, 173, 142, 59, 191, 54, 26, 196, 19, 67, 25, 159, 210, 199, 112, 156, 218, 117, 76, 1, 30, 251, 240, 15, 57, 141, 41, 242, 70, 42, 134, 68, 224, 117, 137, 47, 152, 246, 220, 192, 32, 201, 242, 58]), chain: vec![ @@ -403,6 +405,8 @@ mod test { } } + // FIXME: Add 334+615 exemplar + /// Ensure a verifier without any status verifiers can pass. #[test] fn no_status_ok() { @@ -413,7 +417,7 @@ mod test { &IasNonce::from_hex("ca1bb26d4a756cabf422206fc1953e4b") .expect("Could not parse nonce hex"), ) - .verify(&get_ias_report()) + .verify(&get_334_report()) .expect("Could not verify IAS report"); } @@ -424,19 +428,19 @@ mod test { 69, 251, 36, 34, 76, 54, 51, 236, 141, 181, 29, 9, 11, 241, 29, 228, 222, 118, 194, 134, 108, 6, 1, 2, 49, 80, 32, 217, 151, 134, 184, 44, ])); - mr_enclave1.allow_hardening_advisory("INTEL-SA-00334"); + mr_enclave1.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); let mut mr_enclave2 = MrEnclaveVerifier::new(MrEnclave::from([ 209, 31, 70, 153, 191, 224, 183, 181, 71, 206, 99, 225, 136, 46, 1, 238, 208, 198, 84, 121, 40, 171, 120, 154, 49, 90, 135, 137, 143, 44, 83, 77, ])); - mr_enclave2.allow_hardening_advisory("INTEL-SA-00334"); + mr_enclave2.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); Verifier::new(TEST_ANCHORS) .expect("Could not initialize new verifier") - .mr_enclave(mr_enclave1) - .mr_enclave(mr_enclave2) - .verify(&get_ias_report()) + .mr_enclave(mr_enclave1.clone()) + .mr_enclave(mr_enclave2.clone()) + .verify(&get_334_report()) .expect("Could not verify IAS report"); } @@ -452,7 +456,7 @@ mod test { 10, 10, ); - mr_signer1.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer1.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); let mut mr_signer2 = MrSignerVerifier::new( MrSigner::from([ 209, 31, 70, 153, 191, 224, 183, 181, 71, 206, 99, 225, 136, 46, 1, 238, 208, 198, @@ -461,14 +465,14 @@ mod test { 1, 1, ); - mr_signer2.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer2.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); Verifier::new(TEST_ANCHORS) .expect("Could not initialize new verifier") - .mr_signer(mr_signer1) - .mr_signer(mr_signer2) + .mr_signer(mr_signer1.clone()) + .mr_signer(mr_signer2.clone()) .debug(true) - .verify(&get_ias_report()) + .verify(&get_334_report()) .expect("Could not verify IAS report"); } } diff --git a/attest/verifier/src/status.rs b/attest/verifier/src/status.rs index c3a5070ae4..f498452100 100644 --- a/attest/verifier/src/status.rs +++ b/attest/verifier/src/status.rs @@ -34,7 +34,7 @@ fn check_ids(quote_status: &IasQuoteResult, config_ids: &[String], sw_ids: &[Str } Err(IasQuoteError::ConfigurationAndSwHardeningNeeded { advisory_ids, .. }) => advisory_ids .iter() - .all(|id| config_ids.contains(id) || sw_ids.contains(id)), + .all(|id| config_ids.contains(id) && sw_ids.contains(id)), Err(_) => false, } } @@ -256,10 +256,25 @@ mod test { use mc_attest_core::VerificationReport; use mc_sgx_types::sgx_measurement_t; + /// Report with OK status const IAS_OK: &str = include_str!("../data/test/ias_ok.json"); + + /// Report with "CONFIGURATION_NEEDED" status const IAS_CONFIG: &str = include_str!("../data/test/ias_config.json"); + + /// Report with "SW_HARDENING_NEEDED" status const IAS_SW: &str = include_str!("../data/test/ias_sw.json"); + + /// Report with "SW_HARDENING_NEEDED" and both 334 and 615 advisories. + const IAS_SW_334_615: &str = include_str!("../data/test/ias_sw_334_615.json"); + + /// Report with "CONFIGURATION_AND_SW_HARDENING_NEEDED" status const IAS_CONFIG_SW: &str = include_str!("../data/test/ias_config_sw.json"); + + /// Report with "CONFIGURATION_AND_SW_HARDENING_NEEDED" status, and both 334 + /// and 615 advisories. + const IAS_CONFIG_SW_334_615: &str = include_str!("../data/test/ias_config_sw_334_615.json"); + const MR_ENCLAVE: sgx_measurement_t = sgx_measurement_t { m: [ 247, 180, 107, 31, 41, 201, 41, 41, 32, 42, 25, 79, 7, 29, 232, 138, 9, 180, 143, 195, @@ -371,6 +386,26 @@ mod test { assert!(verifier.verify(&data)) } + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE and + /// advisories passes. + #[test] + fn mrenclave_multi_sw_pass() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(verifier.verify(&data)) + } + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but /// unexpected advisory fails. #[test] @@ -391,14 +426,74 @@ mod test { assert!(!verifier.verify(&data)) } + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but + /// unexpected advisory fails. + #[test] + fn mrenclave_sw_empty_fail() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but + /// unexpected advisory fails. + #[test] + fn mrenclave_multi_sw_empty_fail() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a SW_HARDENING_NEEDED result with the expected MRENCLAVE but + /// unexpected advisory fails. + #[test] + fn mrenclave_multi_sw_short_fail() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and config advisory passes. + /// MRENCLAVE and advisory passes when the advisory is given for both. #[test] - fn mrenclave_config_sw_pass_config() { + fn mrenclave_config_sw_pass() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00239".to_owned()], - sw_ids: vec!["INTEL-SA-00123".to_owned()], + sw_ids: vec!["INTEL-SA-00239".to_owned()], }; let report = VerificationReport { @@ -412,9 +507,128 @@ mod test { } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE and hardening advisory passes. + /// MRENCLAVE and advisory passes when the advisory is given for both. + #[test] + fn mrenclave_multi_config_sw_pass() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and config advisory fails. + #[test] + fn mrenclave_config_sw_fail_config() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00239".to_owned()], + sw_ids: vec!["INTEL-SA-00123".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and sw-only advisory allow-listing fails. #[test] - fn mrenclave_config_sw_pass_sw() { + fn mrenclave_multi_config_sw_fail_no_config() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and sw-only advisory allow-listing fails. + #[test] + fn mrenclave_multi_config_sw_fail_no_sw() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and insufficient sw advisory allow-listing fails. + #[test] + fn mrenclave_multi_config_sw_fail_short_sw() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and insufficient config advisory allow-listing fails. + #[test] + fn mrenclave_multi_config_sw_fail_short_config() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE and hardening advisory fails. + #[test] + fn mrenclave_config_sw_fail_sw() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00123".to_owned()], @@ -428,13 +642,13 @@ mod test { }; let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(verifier.verify(&data)) + assert!(!verifier.verify(&data)) } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected /// MRENCLAVE but an unexpected advisory fails. #[test] - fn mrenclave_config_sw_fail() { + fn mrenclave_config_sw_fail_neither() { let verifier = MrEnclaveVerifier { mr_enclave: MrEnclave::from(&MR_ENCLAVE), config_ids: vec!["INTEL-SA-00123".to_owned()], @@ -451,6 +665,27 @@ mod test { assert!(!verifier.verify(&data)) } + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRENCLAVE but an insufficient sw and config advisory allow-listing + /// fails. + #[test] + fn mrenclave_multi_config_sw_fail_short() { + let verifier = MrEnclaveVerifier { + mr_enclave: MrEnclave::from(&MR_ENCLAVE), + config_ids: vec!["INTEL-SA-00334".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + /// Ensure an OK result with the expected MRSIGNER, product, and minimum /// version passes. #[test] @@ -604,16 +839,39 @@ mod test { assert!(verifier.verify(&data)) } - /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version passes, as long as the - /// advisory is accounted for. + /// Ensure a SW_HARDENING_NEEDED result with the expected MRSIGNER, + /// product, and minimum version passes, as long as all advisories are + /// accounted for #[test] - fn mrsigner_pass_sw_config_via_sw() { + fn mrsigner_pass_multi_sw() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, minimum_svn: 0, config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version succeds if all advisories are + /// accounted for as both config and sw. + #[test] + fn mrsigner_pass_config_sw() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00239".to_owned()], sw_ids: vec!["INTEL-SA-00239".to_owned()], }; @@ -628,10 +886,33 @@ mod test { } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER, product, and minimum version passes, as long as the - /// advisory is accounted for. + /// MRSIGNER, product, and minimum version fails if the advisory isn't + /// accounted for as both config and sw. #[test] - fn mrsigner_pass_sw_config_via_config() { + fn mrsigner_fail_config_sw_no_sw() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00239".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails, if the advisory isn't + /// accounted for in both config and sw. + #[test] + fn mrsigner_fail_config_sw_no_config() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, @@ -647,19 +928,111 @@ mod test { }; let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); - assert!(verifier.verify(&data)) + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails if the advisory isn't + /// accounted for as both config and sw. + #[test] + fn mrsigner_fail_multi_config_sw_no_sw() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails if the advisory isn't + /// accounted for in both config and sw. + #[test] + fn mrsigner_fail_multi_config_sw_short_sw() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00615".to_owned()], + sw_ids: vec![], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails, if the advisory isn't + /// accounted for in both config and sw. + #[test] + fn mrsigner_fail_multi_config_sw_no_config() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec![], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER, product, and minimum version fails, if the advisory isn't + /// accounted for in both config and sw. + #[test] + fn mrsigner_fail_multi_config_sw_short_config() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00334".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected /// MRSIGNER, and minimum version, but the wrong product fails, even if /// the advisory is accounted for. #[test] - fn mrsigner_fail_sw_config_for_product() { + fn mrsigner_fail_sw_config_sw_for_product() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 1, minimum_svn: 0, - config_ids: vec![], + config_ids: vec!["INTEL-SA-00239".to_owned()], sw_ids: vec!["INTEL-SA-00239".to_owned()], }; @@ -674,15 +1047,38 @@ mod test { } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRSIGNER and product, but an earlier version, fails, even if the - /// advisory is accounted for. + /// MRSIGNER, and minimum version, but the wrong product fails, even if + /// all advisories are accounted for. + #[test] + fn mrsigner_fail_multi_sw_config_sw_for_product() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 1, + minimum_svn: 0, + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER and product, but an earlier version, fails, even if all + /// advisories are accounted for. #[test] - fn mrsigner_fail_sw_config_for_version() { + fn mrsigner_fail_config_sw_for_version() { let verifier = MrSignerVerifier { mr_signer: MrSigner::from(&MR_SIGNER), product_id: 0, minimum_svn: 1, - config_ids: vec![], + config_ids: vec!["INTEL-SA-00239".to_owned()], sw_ids: vec!["INTEL-SA-00239".to_owned()], }; @@ -695,4 +1091,27 @@ mod test { let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); assert!(!verifier.verify(&data)) } + + /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected + /// MRSIGNER and product, but an earlier version, fails, even if the + /// advisory is accounted for. + #[test] + fn mrsigner_fail_multi_config_sw_for_version() { + let verifier = MrSignerVerifier { + mr_signer: MrSigner::from(&MR_SIGNER), + product_id: 0, + minimum_svn: 1, + config_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + sw_ids: vec!["INTEL-SA-00334".to_owned(), "INTEL-SA-00615".to_owned()], + }; + + let report = VerificationReport { + sig: Default::default(), + chain: vec![], + http_body: IAS_CONFIG_SW_334_615.trim().to_owned(), + }; + + let data = VerificationReportData::try_from(&report).expect("Could not parse IAS result"); + assert!(!verifier.verify(&data)) + } } diff --git a/common/Cargo.toml b/common/Cargo.toml index 535f196dd9..bc1716fb48 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" @@ -72,9 +72,4 @@ slog-term = { version = "2.9", optional = true } [dev-dependencies] scoped_threadpool = "0.1.*" - -[dev-dependencies.proptest] -version = "1.0" # Only works for 0.9.1 or newer -default-features = false -# Enable all default features not known to break code coverage builds -features = ["default-code-coverage"] +proptest = { version = "1.0", default-features = false, features = ["default-code-coverage"] } diff --git a/connection/Cargo.toml b/connection/Cargo.toml index 3f65176f8a..be7ed1d7b8 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index de6cf3daec..6ce1cd342e 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index b4e883ae73..4fc7cb0145 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index 2b75394895..08c79c5822 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index d93dc80848..e70e778965 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/build.rs b/consensus/enclave/build.rs index 052b7f7881..06f7cf9e95 100644 --- a/consensus/enclave/build.rs +++ b/consensus/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index 2b61303028..18589a0fbf 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/edl/enclave.edl b/consensus/enclave/edl/enclave.edl index 182c5a0a82..150e9e2467 100644 --- a/consensus/enclave/edl/enclave.edl +++ b/consensus/enclave/edl/enclave.edl @@ -11,10 +11,10 @@ enclave { */ public sgx_status_t mobileenclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [user_check] uint8_t *outbuf, + [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, - [user_check] size_t* outbuf_used, - [user_check] uint64_t* outbuf_retry_id); + [out] size_t* outbuf_used, + [in, out] uint64_t* outbuf_retry_id); }; }; diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index cc76946aa3..225ed96e4f 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index 779feb61b4..979da3641f 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/measurement/build.rs b/consensus/enclave/measurement/build.rs index 41279130fd..46e6771889 100644 --- a/consensus/enclave/measurement/build.rs +++ b/consensus/enclave/measurement/build.rs @@ -10,10 +10,10 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; const CONSENSUS_ENCLAVE_PRODUCT_ID: u16 = 1; -const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 4; +const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 5; const CONSENSUS_ENCLAVE_NAME: &str = "consensus-enclave"; const CONSENSUS_ENCLAVE_DIR: &str = "../trusted"; diff --git a/consensus/enclave/measurement/src/lib.rs b/consensus/enclave/measurement/src/lib.rs index b698c7e438..46c4b1f947 100644 --- a/consensus/enclave/measurement/src/lib.rs +++ b/consensus/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index 4898d5688c..41128fcc59 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index 058eb2b2ef..5dce4c2203 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.2" +version = "2.0.0" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-build" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-enclave-id" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-transaction-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.2" +version = "2.0.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.2" +version = "2.0.0" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index 9131a73fff..40eb3279a3 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/enclave/trusted/build.rs b/consensus/enclave/trusted/build.rs index 2ff60613e9..c130d2d1e6 100644 --- a/consensus/enclave/trusted/build.rs +++ b/consensus/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/consensus/enclave/trusted/src/lib.rs b/consensus/enclave/trusted/src/lib.rs index ab9c333d41..9c4fef6e0e 100644 --- a/consensus/enclave/trusted/src/lib.rs +++ b/consensus/enclave/trusted/src/lib.rs @@ -100,16 +100,16 @@ pub extern "C" fn mobileenclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } != 1 + } == 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } != 1 + } == 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index 8b54e32524..801f318c85 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index b40a4a98dc..c85d6ce4f8 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index 0bfe5f345e..773d9984cc 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/BUILD.md b/consensus/service/BUILD.md index 81555f92e8..28df38409b 100644 --- a/consensus/service/BUILD.md +++ b/consensus/service/BUILD.md @@ -97,8 +97,8 @@ Recommended SDK and package installation: ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -112,8 +112,8 @@ chmod +x ./sgx_linux_x64_driver_2.11.054c9c4c.bin ./sgx_linux_x64_driver_2.11.054c9c4c.bin # Install the SDK to /opt/intel/sgxsdk -chmod +x ./sgx_linux_x64_sdk_2.16.100.4.bin -./sgx_linux_x64_sdk_2.16.100.4.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.17.100.3.bin +./sgx_linux_x64_sdk_2.17.100.3.bin --prefix=/opt/intel apt install libsgx-uae-service sgx-aesm-service diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index 75d4fbc265..d0e0ff0497 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index c9dc969351..3a4f4dfd4d 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index e13a484ff6..20d45a9de5 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/src/lib.rs b/crypto/ake/enclave/src/lib.rs index fe62c17d1f..1c2600daa3 100644 --- a/crypto/ake/enclave/src/lib.rs +++ b/crypto/ake/enclave/src/lib.rs @@ -133,7 +133,11 @@ impl AkeEnclaveState { let mut mr_enclave_verifier = MrEnclaveVerifier::new(report_body.mr_enclave()); // INTEL-SA-00334: LVI hardening is handled via rustc arguments set in // mc-util-build-enclave - mr_enclave_verifier.allow_hardening_advisory("INTEL-SA-00334"); + // + // INTEL-SA-00615: MMIO Stale Data is handled by using [out] parameters + // in our ECALL/OCALL definitions (EDLs), and only performing direct + // writes aligned to quadword (8B) boundaries (e.g. in ORAMStorage) + mr_enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); verifier .mr_enclave(mr_enclave_verifier) diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index 86073b1305..8a8b2baa4d 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index 7e1499b20b..0db97cf986 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index 2ec2dcbebb..cfc7e1b078 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index af3b2109e1..dce40ce870 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index 938bb2c30f..49e71e48c4 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index deb2de5243..c6f83267cc 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index 66b6da81e4..ce647f8e3e 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index 0fce90e375..526c75a53d 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index f3ae9938e1..ee113f1ba0 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index 7f198fd8ec..97421ed53a 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index ed02612fe0..16ee519524 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index 6d457c7897..30c8e318a5 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index d5b69416db..dea5231a1f 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 69b228e606..85d9a3239c 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index b3aa7177d0..8b35fbee25 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/docker/Dockerfile-version b/docker/Dockerfile-version index 0678f6effd..6c565411ce 100644 --- a/docker/Dockerfile-version +++ b/docker/Dockerfile-version @@ -1 +1 @@ -1_28 +1_29 diff --git a/docker/install_sgx.sh b/docker/install_sgx.sh old mode 100644 new mode 100755 index 7f39665521..3960fe81f8 --- a/docker/install_sgx.sh +++ b/docker/install_sgx.sh @@ -24,7 +24,7 @@ cd /tmp ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -59,8 +59,8 @@ apt-get install -yq --no-install-recommends \ # Install *after* pkg-config so that they get registered correctly. # pkg-config gets pulled in transitively via build-essential -chmod +x ./sgx_linux_x64_sdk_2.16.100.4.bin -./sgx_linux_x64_sdk_2.16.100.4.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.17.100.3.bin +./sgx_linux_x64_sdk_2.17.100.3.bin --prefix=/opt/intel # Update .bashrc to source sgxsdk echo 'source /opt/intel/sgxsdk/environment' >> /root/.bashrc diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index 1ef297e055..ac556945f0 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index bf3ef5dec4..006d7b5a64 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index 75924f0a3b..851150f2d8 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/src/config.rs b/fog/distribution/src/config.rs index 806374e7e4..20505e1379 100644 --- a/fog/distribution/src/config.rs +++ b/fog/distribution/src/config.rs @@ -99,7 +99,8 @@ impl Config { ) -> ConnectionResult>>> { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index 59d2d05f05..eb4ddca521 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 71cc2579a7..6b27ca7a4d 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index 14e925d56f..b36e8fa94b 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index 21a8546b17..44aff5e423 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/build.rs b/fog/ingest/enclave/build.rs index 26c06202d7..85b5ffa7c3 100644 --- a/fog/ingest/enclave/build.rs +++ b/fog/ingest/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index ed3b14191f..aa9f4e2824 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/edl/enclave.edl b/fog/ingest/enclave/edl/enclave.edl index a6b9108ad2..a7b2b96fd0 100644 --- a/fog/ingest/enclave/edl/enclave.edl +++ b/fog/ingest/enclave/edl/enclave.edl @@ -13,10 +13,10 @@ enclave { */ public sgx_status_t ingest_enclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [user_check] uint8_t *outbuf, + [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, - [user_check] size_t* outbuf_used, - [user_check] uint64_t* outbuf_retry_id); + [out] size_t* outbuf_used, + [in, out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index 645cfd74a9..4beff10247 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index 9554a1169c..94c845c4fd 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/measurement/build.rs b/fog/ingest/enclave/measurement/build.rs index c978fc67e9..67635f698e 100644 --- a/fog/ingest/enclave/measurement/build.rs +++ b/fog/ingest/enclave/measurement/build.rs @@ -10,10 +10,10 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; const INGEST_ENCLAVE_PRODUCT_ID: u16 = 4; -const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 3; +const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 4; const INGEST_ENCLAVE_NAME: &str = "ingest-enclave"; const INGEST_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/ingest/enclave/measurement/src/lib.rs b/fog/ingest/enclave/measurement/src/lib.rs index 22b991df1d..5f0064d12a 100644 --- a/fog/ingest/enclave/measurement/src/lib.rs +++ b/fog/ingest/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 6af26b86c2..79b84f0aab 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.2" +version = "2.0.0" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.2" +version = "2.0.0" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.2" +version = "2.0.0" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-build" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-transaction-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.2" +version = "2.0.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.2" +version = "2.0.0" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index 3067fba2b8..4c467d759b 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/enclave/trusted/build.rs b/fog/ingest/enclave/trusted/build.rs index 2622ad4ec6..1b47cb1d60 100644 --- a/fog/ingest/enclave/trusted/build.rs +++ b/fog/ingest/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/ingest/enclave/trusted/src/lib.rs b/fog/ingest/enclave/trusted/src/lib.rs index 81d0d0c144..7414c5ad47 100644 --- a/fog/ingest/enclave/trusted/src/lib.rs +++ b/fog/ingest/enclave/trusted/src/lib.rs @@ -84,16 +84,16 @@ pub extern "C" fn ingest_enclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } != 1 + } == 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } != 1 + } == 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index a849303fbd..a40190b105 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index 1069863976..771978e329 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "1.2.2" +version = "2.0.0" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index e4ec348e79..3c225487be 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index c83342d38b..8c58368893 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index 2383cfd452..5d5d3267c8 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/build.rs b/fog/ledger/enclave/build.rs index 004600e660..8dc6e68629 100644 --- a/fog/ledger/enclave/build.rs +++ b/fog/ledger/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index b1483ff48f..0c23932430 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/edl/enclave.edl b/fog/ledger/enclave/edl/enclave.edl index e7ad6a58cb..f61625a82b 100644 --- a/fog/ledger/enclave/edl/enclave.edl +++ b/fog/ledger/enclave/edl/enclave.edl @@ -13,10 +13,10 @@ enclave { */ public sgx_status_t ledger_enclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [user_check] uint8_t *outbuf, + [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, - [user_check] size_t* outbuf_used, - [user_check] uint64_t* outbuf_retry_id); + [out] size_t* outbuf_used, + [in, out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index 4652bc5442..704fc5579f 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index f17c0c81fb..6101ffe6c9 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/measurement/build.rs b/fog/ledger/enclave/measurement/build.rs index 46f7402fc0..7702a6b013 100644 --- a/fog/ledger/enclave/measurement/build.rs +++ b/fog/ledger/enclave/measurement/build.rs @@ -10,10 +10,10 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; const LEDGER_ENCLAVE_PRODUCT_ID: u16 = 2; -const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 3; +const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 4; const LEDGER_ENCLAVE_NAME: &str = "ledger-enclave"; const LEDGER_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/ledger/enclave/measurement/src/lib.rs b/fog/ledger/enclave/measurement/src/lib.rs index 6bd930d62d..7bf42f751b 100644 --- a/fog/ledger/enclave/measurement/src/lib.rs +++ b/fog/ledger/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 7a16a8b75c..8a3e7be53a 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.2" +version = "2.0.0" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.2" +version = "2.0.0" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.2" +version = "2.0.0" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-build" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-transaction-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.2" +version = "2.0.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.2" +version = "2.0.0" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index b37b82d026..bdd22a9d48 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/enclave/trusted/build.rs b/fog/ledger/enclave/trusted/build.rs index 8509981de6..d71761f769 100644 --- a/fog/ledger/enclave/trusted/build.rs +++ b/fog/ledger/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/trusted/src/lib.rs b/fog/ledger/enclave/trusted/src/lib.rs index 58041ca64b..18f1009a9f 100644 --- a/fog/ledger/enclave/trusted/src/lib.rs +++ b/fog/ledger/enclave/trusted/src/lib.rs @@ -82,16 +82,16 @@ pub extern "C" fn ledger_enclave_call( || outbuf_used.is_null() || outbuf_retry_id.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 || unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } != 1 + } == 1 || unsafe { sgx_is_outside_enclave( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } != 1 + } == 1 { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index a352a487c8..64a388ba31 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/server/tests/connection.rs b/fog/ledger/server/tests/connection.rs index fce0305954..53c601e275 100644 --- a/fog/ledger/server/tests/connection.rs +++ b/fog/ledger/server/tests/connection.rs @@ -160,7 +160,9 @@ fn fog_ledger_merkle_proofs_test(logger: Logger) { // Make ledger enclave client let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_ledger_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier.allow_hardening_advisories( + mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, + ); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); @@ -352,7 +354,9 @@ fn fog_ledger_key_images_test(logger: Logger) { // Make ledger enclave client let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_ledger_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier.allow_hardening_advisories( + mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, + ); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index 952d70d93b..56608d4407 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "1.2.2" +version = "2.0.0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index 5fe9212b61..48c33a1f35 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index 7baf1cd52a..75a0929ef8 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index 13b70f7436..1c48150acf 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index 14cfb2643b..8b0e0245db 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index 53ff25b33a..eb02c2a78e 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 012c850e60..f96f422a89 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index 12e759858c..bdd4935133 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index 0469931f46..9e22a2fcb3 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index 87e10343bf..e8907fb34f 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index 2fee842c60..6de1e31cba 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index fcadb82f44..020de3abff 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index 68b96271c2..386d4f8ef5 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index 067d132a2b..bd5cb5d7d7 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "1.2.2" +version = "2.0.0" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index 1539e654d4..a10409491e 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index e5c4522fb5..b5c0e4b4fc 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index 29acfc50fc..bff6c1bcbf 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sample-paykit/src/client_builder.rs b/fog/sample-paykit/src/client_builder.rs index cd6ce3fa1f..cf531c23ff 100644 --- a/fog/sample-paykit/src/client_builder.rs +++ b/fog/sample-paykit/src/client_builder.rs @@ -255,7 +255,8 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); mr_signer_verifier } else { mc_consensus_enclave_measurement::get_mr_signer_verifier(None) @@ -274,7 +275,9 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier.allow_hardening_advisories( + mc_fog_ingest_enclave_measurement::HARDENING_ADVISORIES, + ); mr_signer_verifier } else { mc_fog_ingest_enclave_measurement::get_mr_signer_verifier(None) @@ -293,7 +296,9 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier.allow_hardening_advisories( + mc_fog_ledger_enclave_measurement::HARDENING_ADVISORIES, + ); mr_signer_verifier } else { mc_fog_ledger_enclave_measurement::get_mr_signer_verifier(None) @@ -312,7 +317,8 @@ impl ClientBuilder { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier + .allow_hardening_advisories(mc_fog_view_enclave_measurement::HARDENING_ADVISORIES); mr_signer_verifier } else { mc_fog_view_enclave_measurement::get_mr_signer_verifier(None) diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index ac733c99d3..896accfe8d 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index ba5d7fb696..b94621e052 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index 4ea7c8b5cc..a0cecb6976 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index 823ad619b9..454f750bfb 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "1.2.2" +version = "2.0.0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 269b086aca..320401a057 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index 293b9cfef7..6b82965c62 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index c00cc10d89..a7c2ccfacb 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index 87353b5d02..26f7aae546 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index b8ecbd3378..f43d69e020 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index 21171e81f6..21f9e9daa6 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index 453014a099..a43ef15f4f 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/build.rs b/fog/view/enclave/build.rs index 04748228e8..0df4b8bb9a 100644 --- a/fog/view/enclave/build.rs +++ b/fog/view/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index f2b9874601..3a901d43bf 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/edl/enclave.edl b/fog/view/enclave/edl/enclave.edl index 80eac0dfa0..f6349c2354 100644 --- a/fog/view/enclave/edl/enclave.edl +++ b/fog/view/enclave/edl/enclave.edl @@ -15,10 +15,10 @@ enclave { */ public sgx_status_t viewenclave_call([in, size=inbuf_len] const uint8_t* inbuf, size_t inbuf_len, - [user_check] uint8_t *outbuf, + [out, size=outbuf_len] uint8_t *outbuf, size_t outbuf_len, - [user_check] size_t* outbuf_used, - [user_check] uint64_t* outbuf_retry_id); + [out] size_t* outbuf_used, + [in, out] uint64_t* outbuf_retry_id); }; }; diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index 097ba7edab..1b01547107 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index 277f6607b5..761f75ec65 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/measurement/build.rs b/fog/view/enclave/measurement/build.rs index 0ce0f08c21..77c9b28922 100644 --- a/fog/view/enclave/measurement/build.rs +++ b/fog/view/enclave/measurement/build.rs @@ -10,10 +10,10 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; const VIEW_ENCLAVE_PRODUCT_ID: u16 = 3; -const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 3; +const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 4; const VIEW_ENCLAVE_NAME: &str = "view-enclave"; const VIEW_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/view/enclave/measurement/src/lib.rs b/fog/view/enclave/measurement/src/lib.rs index 3f1221e82c..94bb6d37fc 100644 --- a/fog/view/enclave/measurement/src/lib.rs +++ b/fog/view/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index 79ef42c064..d67c31e9d8 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "1.2.2" +version = "2.0.0" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "1.2.2" +version = "2.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "1.2.2" +version = "2.0.0" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "1.2.2" +version = "2.0.0" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-build" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-debug-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-sgx-panic-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "1.2.2" +version = "2.0.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "1.2.2" +version = "2.0.0" [[package]] name = "mc-transaction-core" -version = "1.2.2" +version = "2.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "1.2.2" +version = "2.0.0" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "1.2.2" +version = "2.0.0" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "1.2.2" +version = "2.0.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "1.2.2" +version = "2.0.0" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "1.2.2" +version = "2.0.0" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "1.2.2" +version = "2.0.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index 6f06400592..d815127eec 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/enclave/trusted/build.rs b/fog/view/enclave/trusted/build.rs index b03145862c..ad2076eca5 100644 --- a/fog/view/enclave/trusted/build.rs +++ b/fog/view/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.16.100.4"; +const SGX_VERSION: &str = "2.17.100.3"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/trusted/src/lib.rs b/fog/view/enclave/trusted/src/lib.rs index 6710366cc8..2607fb4e28 100644 --- a/fog/view/enclave/trusted/src/lib.rs +++ b/fog/view/enclave/trusted/src/lib.rs @@ -37,14 +37,14 @@ pub extern "C" fn viewenclave_call( if inbuf.is_null() || outbuf.is_null() || unsafe { sgx_is_outside_enclave(inbuf as *const c_void, inbuf_len) } == 1 - || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } != 1 + || unsafe { sgx_is_outside_enclave(outbuf as *const c_void, outbuf_len) } == 1 { eprintln!("inbuf or outbuf was out of bounds!"); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; } if unsafe { sgx_is_outside_enclave(outbuf_used as *const c_void, core::mem::size_of::()) - } != 1 + } == 1 { eprintln!("outbuf_used was out of bounds! {:?}", outbuf_used); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; @@ -55,7 +55,7 @@ pub extern "C" fn viewenclave_call( outbuf_retry_id as *const c_void, core::mem::size_of::(), ) - } != 1 + } == 1 { eprintln!("outbuf_retry_id was out of bounds! {:?}", outbuf_retry_id); return sgx_status_t::SGX_ERROR_INVALID_PARAMETER; diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index 4cea093221..89e77204f8 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index 8fd9d6b503..86dc878757 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index ffb68e833e..6eb0d3a83f 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/server/tests/smoke_tests.rs b/fog/view/server/tests/smoke_tests.rs index 25d02f3109..8b32dc2043 100644 --- a/fog/view/server/tests/smoke_tests.rs +++ b/fog/view/server/tests/smoke_tests.rs @@ -104,7 +104,8 @@ fn get_test_environment( let grpcio_env = Arc::new(grpcio::EnvBuilder::new().build()); let mut mr_signer_verifier = MrSignerVerifier::from(mc_fog_view_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier + .allow_hardening_advisories(mc_fog_view_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/jenkins/build-pod.yaml b/jenkins/build-pod.yaml index 9883127c08..0f56bcd0ec 100644 --- a/jenkins/build-pod.yaml +++ b/jenkins/build-pod.yaml @@ -20,7 +20,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: rust-builder-default - image: gcr.io/mobilenode-211420/builder-install:1_28 + image: gcr.io/mobilenode-211420/builder-install:1_29 env: - name: PATH value: "/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index b65770134c..99efda1360 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index 6734c7969f..8b23c06940 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index a3875fad1b..37facd622d 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index acea3a820b..911b0ade79 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index 319600b401..c4c0580cae 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/src/test_app/main.rs b/ledger/sync/src/test_app/main.rs index e74f502119..b3ffbae81a 100644 --- a/ledger/sync/src/test_app/main.rs +++ b/ledger/sync/src/test_app/main.rs @@ -97,7 +97,8 @@ fn main() { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index debb090fdd..5c00668912 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index fe4c93e6fe..abad94d6d9 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index a1d02c1995..db3a49476a 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mob b/mob index 441321ba92..018f32e096 100755 --- a/mob +++ b/mob @@ -222,32 +222,16 @@ mobconf.read(".mobconf") verbose_chdir(top_level) # Get dockerfile-version data Find and parse dockerfile version file -if 'dockerfile' in mobconf['image']: - docker_dir = os.path.dirname(mobconf['image']['dockerfile']) - docker_ver_file = os.path.join(docker_dir, 'Dockerfile-version') - with open(os.path.join(top_level, docker_ver_file), 'r') as file: - version_data = file.read().strip() -elif 'Dockerfile-version' in mobconf['image']: +if 'Dockerfile-version' in mobconf['image']: docker_dir = None version_data = mobconf['image']['Dockerfile-version'] else: raise Exception("Neither 'dockerfile' nor 'Dockerfile-version' was found in .mobconf") -# Parse what version data we found -ver_segments = version_data.split('_') -if len(ver_segments) != 2: - raise Exception("Expected form A_B for Dockerfile-version, found '" + version_data + "' which parsed as: " + str(ver_segments)) -major_ver = ver_segments[0] -minor_ver = int(ver_segments[1]) -if minor_ver < 0: - raise Exception("Invalid minor ver: " + str(minor_ver)) - # Calculate default tag. repo = mobconf['image']['repository'] if 'repository' in mobconf['image'] else "" -default_tag = os.path.join(repo, mobconf['image']['target'] + ':' + major_ver + "_" + str(minor_ver)) +default_tag = os.path.join(repo, mobconf['image']['target'] + ':' + version_data) parent_tag = None -if minor_ver > 0: - parent_tag = os.path.join(repo, mobconf['image']['target'] + ':' + major_ver + "_" + str(minor_ver - 1)) if args.action == "default-tag": print(default_tag, end='') @@ -285,36 +269,6 @@ build_env = [ # Don't build the image if we already have it, unless # image action was specified (user requested the image) -# -# Note: IMO it should be okay to always rebuild the image as long as the farm is -# giving us a good cache source for it, but it seems that we always get a cache -# miss at `COPY rust-toolchain .`, and I'm not sure why. -# This `if` here is me giving up on trying to resolve those layer cache miss issues. -# I think that it comes down to, in cloudbuild the permissions (user / group) -# are slightly different from what they are locally, and I don't want to spend more time on it. -# It would be nice if the docker image itself were actually reproducible, i.e. counts -# as a cache hit for itself whether it were built locally or in farm... sigh -if args.action == "image" or not have_tag(tag): - # Get an up-to-date image, even if repository is messed up - # Invoke docker from directory of dockerfile - # This seems to fix docker's layer caching when we are building the image variously - # from pwd = / and pwd = /public/. - # Please don't factor out the chdir without testing that this caching is still working - verbose_chdir(docker_dir) - docker_build = ["docker", - "build", - # build context is dir of Dockerfile - ".", - "--target", mobconf['image']['target'], - "--tag", tag, - "--cache-from", tag, - "--cache-from", default_tag] - # N.B. --cache-from order on the line establishes priority: - # https://stackoverflow.com/questions/54574821/docker-build-not-using-cache-when-copying-gemfile-while-using-cache-from/56024061#56024061 - if parent_tag is not None: - docker_build.extend(["--cache-from", parent_tag]) - - maybe_run(docker_build) if args.action == "image": sys.exit(0) diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index 20763373b9..56ed769180 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index 6bca63f1e1..b76a9ee6bb 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index 1e5f57248d..05bb4ae36e 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mobilecoind/src/bin/main.rs b/mobilecoind/src/bin/main.rs index 3a4f5721af..346d8e4e29 100644 --- a/mobilecoind/src/bin/main.rs +++ b/mobilecoind/src/bin/main.rs @@ -41,7 +41,8 @@ fn main() { let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisory("INTEL-SA-00334"); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); diff --git a/mobilecoind/src/config.rs b/mobilecoind/src/config.rs index 015cc8065e..fcdfb58889 100644 --- a/mobilecoind/src/config.rs +++ b/mobilecoind/src/config.rs @@ -176,7 +176,8 @@ impl Config { signature.product_id(), signature.version(), ); - mr_signer_verifier.allow_hardening_advisories(&["INTEL-SA-00334"]); + mr_signer_verifier + .allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); mr_signer_verifier }; diff --git a/ops/Dockerfile-consensus b/ops/Dockerfile-consensus index 3035f4e70a..601bf23abd 100644 --- a/ops/Dockerfile-consensus +++ b/ops/Dockerfile-consensus @@ -19,9 +19,9 @@ RUN apt-get update -q -q && \ # Install SGX Ubuntu/Debian Repo RUN source /etc/os-release && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" && \ + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.16/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.16.100.4.bin" && \ + wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" && \ echo "deb [arch=amd64 signed-by=/usr/local/share/apt-keyrings/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list RUN mkdir -p /usr/local/share/apt-keyrings && \ diff --git a/peers/Cargo.toml b/peers/Cargo.toml index ce9c8cad99..0516593a68 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index 67e2b62c5b..5e32e419a5 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index afe5614414..cb43586f7a 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index 0803ea11fa..3cffacf195 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index 5aeb6b61bb..98c1f4059b 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index 5a4d948460..5603080798 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index 9a4f40e7d5..52b3d939c8 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index 35b0d61168..f4b483608b 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index 28243aef92..540075000d 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index 1705c274b7..45791c3f14 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index ac1bf54e41..ba68d02349 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index a36c57fdc1..2e9e01a707 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index 5af54ffb09..cf9f12fde2 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index 73ca4e2919..7650c1e425 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index 9bd5190d20..917939ec96 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index de58902c4f..66dee833b3 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index a28691fb8f..d1c13baf1d 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index d660933ba0..13c350881e 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index 0e6bb1db5b..67ca8ea187 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index c6e313b3b6..315e662db5 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "1.2.2" +version = "2.0.0" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index fef4dea234..6b337ddfc0 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index 0290789ad4..4ce4c1a241 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index 72c7b80205..c70370dab2 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index be343e1a3d..f067a8f064 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index e196f7a7f9..94e5abf61a 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index f76f6fb2ae..d2957ef308 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index ddb9c8d784..2ec32e8bc4 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" @@ -42,12 +42,6 @@ bulletproofs-og = { version = "3.0.0-pre.1", default-features = false } [target.'cfg(any(target_feature = "avx2", target_feature = "avx"))'.dependencies] curve25519-dalek = { version = "4.0.0-pre.2", default-features = false, features = ["simd_backend", "nightly"] } -[dev-dependencies.proptest] -version = "1.0" # Only works for 0.9.1 or newer -default-features = false -# Enable all default features not known to break code coverage builds -features = ["default-code-coverage"] - [target.'cfg(not(any(target_feature = "avx2", target_feature = "avx")))'.dependencies] curve25519-dalek = { version = "4.0.0-pre.2", default-features = false, features = ["nightly", "u64_backend"] } @@ -55,6 +49,7 @@ curve25519-dalek = { version = "4.0.0-pre.2", default-features = false, features rand = "0.8" rand_hc = "0.3" tempdir = "0.3" +proptest = { version = "1.0", default-features = false, features = ["default-code-coverage"] } mc-crypto-digestible-test-utils = { path = "../../crypto/digestible/test-utils" } mc-crypto-rand = { path = "../../crypto/rand" } diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 5ac8d15dd9..621137dd62 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index b5629af94f..e1c33e7e12 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index a2b8947164..ec30c7af01 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index 4e44b117ba..ac4af2acc7 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index ab6e6a95a4..d435bcad81 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index 2f2df6e477..e7a1b2b0cf 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index 219bf1da2d..144ca34e31 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index d42de57ede..7d8e07a37d 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/cli/Cargo.toml b/util/cli/Cargo.toml index 13a9289499..0d7792a283 100644 --- a/util/cli/Cargo.toml +++ b/util/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-cli" -version = "0.1.0" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index adebdea788..56e260d27b 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index 389044b84f..06d658a17f 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index afe8f28a57..e99aca3737 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index 81fd576ace..a26a812d57 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index 9cc121a758..b38ef16842 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index bb48defc8f..7a3c0592f2 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index 72a9d6122c..d7625aecb4 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 9a96489370..6904b9625b 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index 922bcf88b5..567168c080 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index b9e6f0bb64..efe1c35a23 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index 261a7b9171..253b5553b4 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index 79c4e5a5ee..85df47cd00 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index 7869f93ce3..d6086a57f5 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index 8baba5cf2c..e649efdfb2 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index 1cbafb045f..9457ddb95a 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index 8a7af302f6..ed936d832f 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index c068a93a39..6f9bf7057e 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index 30cf8d4d3b..c3c819eb3d 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index 491b0555f6..3b107043d3 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index d3c21d422d..defc3c1efb 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index 4b9e250427..b4d23e4edd 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index 91ea310279..7780893bd3 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index 9e22307b30..3fe1f0be2d 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index 83dfd023a0..897bcbf858 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "1.2.2" +version = "2.0.0" authors = ["MobileCoin"] edition = "2018" From 94dd3995dd14b6fabf63d989266c73dfa510e020 Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 25 Jul 2022 19:10:07 -0700 Subject: [PATCH 47/77] Fix rust-sgx-sdk image used. --- .github/workflows/mobilecoin-dev-cd.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 02dd9fae45..818cfd9a63 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -60,7 +60,7 @@ jobs: build-rust-hardware-projects: runs-on: [self-hosted, Linux, large] container: - image: mobilecoin/rust-sgx-base@v0.0.14 + image: mobilecoin/rust-sgx-base@0.0.14 env: ENCLAVE_SIGNING_KEY_PATH: ${{ github.workspace }}/.tmp/enclave_signing.pem MINTING_TRUST_ROOT_PUBLIC_KEY_PEM: ${{ github.workspace }}/.tmp/minting_trust_root.public.pem From 0f09862109fa8c3749012ffed355eb25eed775d6 Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 25 Jul 2022 19:17:40 -0700 Subject: [PATCH 48/77] Fix dockerhub ref again. --- .github/workflows/mobilecoin-dev-cd.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 818cfd9a63..7948b0e9d6 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -60,7 +60,7 @@ jobs: build-rust-hardware-projects: runs-on: [self-hosted, Linux, large] container: - image: mobilecoin/rust-sgx-base@0.0.14 + image: mobilecoin/rust-sgx-base:v0.0.14 env: ENCLAVE_SIGNING_KEY_PATH: ${{ github.workspace }}/.tmp/enclave_signing.pem MINTING_TRUST_ROOT_PUBLIC_KEY_PEM: ${{ github.workspace }}/.tmp/minting_trust_root.public.pem From 0285eb183771d191aa3eddf8dde688fb23a97c36 Mon Sep 17 00:00:00 2001 From: Adam Mork Date: Fri, 12 Aug 2022 13:40:14 -0700 Subject: [PATCH 49/77] Propagate BlockVersion creation error up through the FFI, if a user tries to pass in a blockversion GREATER than whats avail in the rust-lib it will throw an InvalidInput error. (#2366) Previously, an "invalid" (too new) BlockVersion would cause a rust panic due to the `.unwrap()` call in `mc_transaction_builder_create`. The correct way to deal with invalid BlockVersions is too propagate the error up through the FFI in the form of an `LibMcError:InvalidInput` --- libmobilecoin/include/transaction.h | 7 ++++++- libmobilecoin/src/error.rs | 8 +++++++- libmobilecoin/src/transaction.rs | 11 ++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libmobilecoin/include/transaction.h b/libmobilecoin/include/transaction.h index 47fe4e8ffa..ce351f470d 100644 --- a/libmobilecoin/include/transaction.h +++ b/libmobilecoin/include/transaction.h @@ -179,13 +179,18 @@ MC_ATTRIBUTE_NONNULL(1, 2, 3); /* ==== McTransactionBuilder ==== */ +/// +/// # Errors +/// +/// * `LibMcError::InvalidInput` McTransactionBuilder* MC_NULLABLE mc_transaction_builder_create( uint64_t fee, uint64_t token_id, uint64_t tombstone_block, const McFogResolver* MC_NULLABLE fog_resolver, McTxOutMemoBuilder* MC_NONNULL memo_builder, - uint32_t block_version + uint32_t block_version, + McError* MC_NULLABLE * MC_NULLABLE out_error ) MC_ATTRIBUTE_NONNULL(5); diff --git a/libmobilecoin/src/error.rs b/libmobilecoin/src/error.rs index 415daa4433..e30ccd030a 100644 --- a/libmobilecoin/src/error.rs +++ b/libmobilecoin/src/error.rs @@ -10,7 +10,7 @@ use mc_crypto_keys::KeyError; use mc_crypto_noise::CipherError; use mc_fog_kex_rng::Error as FogKexRngError; use mc_fog_report_validation::{ingest_report::Error as IngestReportError, FogPubkeyError}; -use mc_transaction_core::AmountError; +use mc_transaction_core::{AmountError, BlockVersionError}; use mc_transaction_std::TxBuilderError; use mc_util_serial::DecodeError; use protobuf::ProtobufError; @@ -124,6 +124,12 @@ impl From for LibMcError { } } +impl From for LibMcError { + fn from(err: BlockVersionError) -> Self { + LibMcError::InvalidInput(format!("{:?}", err)) + } +} + impl From for LibMcError { fn from(err: AttestAkeError) -> Self { if let AttestAkeError::ReportVerification(VerifierError::Verification(_)) = err { diff --git a/libmobilecoin/src/transaction.rs b/libmobilecoin/src/transaction.rs index e0f2e54386..a52c6e0771 100644 --- a/libmobilecoin/src/transaction.rs +++ b/libmobilecoin/src/transaction.rs @@ -369,6 +369,10 @@ pub extern "C" fn mc_transaction_builder_ring_add_element( pub type McTransactionBuilder = Option>; impl_into_ffi!(Option>); +/// +/// # Errors +/// +/// * `LibMcError::InvalidInput` #[no_mangle] pub extern "C" fn mc_transaction_builder_create( fee: u64, @@ -377,8 +381,9 @@ pub extern "C" fn mc_transaction_builder_create( fog_resolver: FfiOptRefPtr, memo_builder: FfiMutPtr, block_version: u32, + out_error: FfiOptMutPtr>, ) -> FfiOptOwnedPtr { - ffi_boundary(|| { + ffi_boundary_with_error(out_error, || { let fog_resolver = fog_resolver .as_ref() @@ -389,7 +394,7 @@ pub extern "C" fn mc_transaction_builder_create( FogResolver::new(fog_resolver.0.clone(), &fog_resolver.1) .expect("FogResolver could not be constructed from the provided materials") }); - let block_version = BlockVersion::try_from(block_version).unwrap(); + let block_version = BlockVersion::try_from(block_version)?; let memo_builder_box = memo_builder .into_mut() @@ -407,7 +412,7 @@ pub extern "C" fn mc_transaction_builder_create( .expect("failure not expected"); transaction_builder.set_tombstone_block(tombstone_block); - Some(transaction_builder) + Ok(Some(transaction_builder)) }) } From 23d657fdfb4a8c6c184e58cbe4f4603d657f452c Mon Sep 17 00:00:00 2001 From: "Cary A. Bakker" Date: Wed, 24 Aug 2022 16:45:57 -0400 Subject: [PATCH 50/77] libmobilecoin changes for MobileCoin-Swift SDK transaction idempotence (#2417) * libmobilecoin changes for MobileCoin-Swift SDK transaction idempotence * Updates after pairing with James * Add documentation to chacha20_rng.rs, add error out parameters to remaining functions * Update libmobilecoin_cbindgen.h * Update chacha20_rng.h and add error return to mc_chacha20_rng_free * Add documentation to chacha20_rng.h * func name consistency, update to return bool for funcs with erros, add correct header to artifacts * Update mc_chacha20_get_word_pos -> mc_chacha20_rng_get_word_pos, and regen cbindgen * cargo fmt * PR review comment updates * Removed McU128 * Updated variants to generics via Reymoun's suggestion, updated cbindgen * Added input checking to preempt expect() panics (there's likely a cleaner / more 'rusty' way to do this though) * PR review updates: * explicit use list * remove use TryInto * change from expect() to map_err() and get rid of redundant size checks * update cbindgen for libmobilecoin * Add back use TryInto for release/v2 branch only - not required for master branch * cargo fmt * Update to remove error param from free method for chacha20_rng * libmobilecoin cbindgen for release/v2 branch * cargo fmt * Make ptr nullable for free call as per Remoun's suggestion * Fix sorting of dependency updates in Cargo.toml * Update libmobilecoin/include/chacha20_rng.h update from returning bool to returning void Co-authored-by: Remoun Metyas Co-authored-by: Remoun Metyas --- Cargo.lock | 2 + libmobilecoin/Cargo.toml | 2 + libmobilecoin/include/chacha20_rng.h | 116 ++++++++++++++++++++ libmobilecoin/include/libmobilecoin.h | 1 + libmobilecoin/libmobilecoin_cbindgen.h | 106 +++++++++++++++++- libmobilecoin/src/chacha20_rng.rs | 145 +++++++++++++++++++++++++ libmobilecoin/src/common/buffer.rs | 52 +-------- libmobilecoin/src/error.rs | 13 ++- libmobilecoin/src/lib.rs | 1 + 9 files changed, 389 insertions(+), 49 deletions(-) create mode 100644 libmobilecoin/include/chacha20_rng.h create mode 100644 libmobilecoin/src/chacha20_rng.rs diff --git a/Cargo.lock b/Cargo.lock index 1efa844487..fe23ecffe9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2044,6 +2044,8 @@ dependencies = [ "mc-util-serial", "mc-util-uri", "protobuf", + "rand 0.8.5", + "rand_chacha 0.3.1", "rand_core 0.6.3", "sha2 0.10.2", "slip10_ed25519", diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index 5c00668912..b8d46595b4 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -16,6 +16,8 @@ displaydoc = "0.2" generic-array = { version = "0.14", features = ["serde", "more_lengths"] } libc = "0.2" protobuf = "2.27.1" +rand = { version = "0.8", default-features = false } +rand_chacha = { version = "0.3.1" } rand_core = { version = "0.6", features = ["std"] } sha2 = { version = "0.10", default-features = false } slip10_ed25519 = "0.1.3" diff --git a/libmobilecoin/include/chacha20_rng.h b/libmobilecoin/include/chacha20_rng.h new file mode 100644 index 0000000000..49135a42d9 --- /dev/null +++ b/libmobilecoin/include/chacha20_rng.h @@ -0,0 +1,116 @@ +// Copyright (c) 2018-2022 The MobileCoin Foundation + +#ifndef MC_CHACHA20_RNG_H_ +#define MC_CHACHA20_RNG_H_ + +#include "common.h" + +/* ==================== ChaCha20Rng ==================== */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _ChaCha20Rng ChaCha20Rng; + +/// Returns a new ChaCha20Rng instance initialized with the +/// seed value provided by the u64 long_val parameter +/// +/// # Arguments +/// +/// * `long_val` - an unsigned 64 bit value to use as the rng seed +/// +/// # Errors +/// +/// * `LibMcError::Poison` +ChaCha20Rng* MC_NULLABLE mc_chacha20_rng_create_with_long( + uint64_t value, + McError* MC_NULLABLE * MC_NULLABLE out_error +); + +/// Returns a new ChaCha20Rng instance initialized with the +/// seed value provided by the bytes data, which must be at +/// least 32 bytes (only the first 32 bytes will be used) +/// +/// # Arguments +/// +/// * `bytes` - 32 bytes of data to use as the rng seed +/// +/// # Errors +/// +/// * `LibMcError::Poison` +ChaCha20Rng* MC_NULLABLE mc_chacha20_rng_create_with_bytes( + const McBuffer* MC_NONNULL bytes, + McError* MC_NULLABLE * MC_NULLABLE out_error +) +MC_ATTRIBUTE_NONNULL(1); + +/// Returns the current word_pos of the ChaCha20Rng instance +/// +/// # Arguments +/// +/// * `chacha20_rng` - must be a valid ChaCha20Rng +/// * `out_word_pos` - pointer to buffer of 16 bytes where the current +/// chacha20_rng wordpos will be returned +/// +/// # Errors +/// +/// * `LibMcError::Poison` +bool mc_chacha20_rng_get_word_pos( + ChaCha20Rng* MC_NONNULL chacha20_rng, + const McBuffer* MC_NONNULL out_word_pos, + McError* MC_NULLABLE * MC_NULLABLE out_error +) +MC_ATTRIBUTE_NONNULL(1,2); + +/// Sets the current word_pos of the ChaCha20Rng instance +/// +/// /// # Arguments +/// +/// * `chacha20_rng` - must be a valid ChaCha20Rng +/// * `out_word_pos` - pointer to buffer of 128 bytes where the current +/// chacha20_rng wordpos will be returned +/// +/// # Errors +/// +/// * `LibMcError::Poison` +bool mc_chacha20_rng_set_word_pos( + ChaCha20Rng* MC_NONNULL chacha20_rng, + const McBuffer* MC_NONNULL bytes, + McError* MC_NULLABLE * MC_NULLABLE out_error +) +MC_ATTRIBUTE_NONNULL(1,2); + +/// Returns the next random u64 value from the ChaCha20Rng +/// +/// /// # Arguments +/// +/// * `chacha20_rng` - must be a valid ChaCha20Rng +/// +/// # Errors +/// +/// * `LibMcError::Poison` +uint64_t mc_chacha20_rng_next_long( + ChaCha20Rng* MC_NONNULL chacha20_rng, + McError* MC_NULLABLE * MC_NULLABLE out_error +) +MC_ATTRIBUTE_NONNULL(1); + +/// Frees the ChaCha20Rng +/// +/// # Preconditions +/// +/// * The ChaCha20Rng is no longer in use +/// +/// # Arguments +/// +/// * `chacha20_rng` - must be a valid ChaCha20Rng +void mc_chacha20_rng_free( + ChaCha20Rng* MC_NULLABLE chacha20_rng +); + +#ifdef __cplusplus +} +#endif + +#endif /* MC_CHACHA20_RNG_H_ */ diff --git a/libmobilecoin/include/libmobilecoin.h b/libmobilecoin/include/libmobilecoin.h index bb8cbcffb0..b24181c520 100644 --- a/libmobilecoin/include/libmobilecoin.h +++ b/libmobilecoin/include/libmobilecoin.h @@ -12,5 +12,6 @@ #include "transaction.h" #include "bip39.h" #include "slip10.h" +#include "chacha20_rng.h" #endif /* !LIBMOBILECOIN_H_ */ diff --git a/libmobilecoin/libmobilecoin_cbindgen.h b/libmobilecoin/libmobilecoin_cbindgen.h index 07e885b8fa..9773cf5d8e 100644 --- a/libmobilecoin/libmobilecoin_cbindgen.h +++ b/libmobilecoin/libmobilecoin_cbindgen.h @@ -10,6 +10,8 @@ #define LIB_MC_ERROR_CODE_PANIC -2 +#define LIB_MC_ERROR_CODE_POISON -3 + #define LIB_MC_ERROR_CODE_INVALID_INPUT 100 #define LIB_MC_ERROR_CODE_INVALID_OUTPUT 101 @@ -98,6 +100,8 @@ typedef struct McRngCallback { FfiOptMutPtr context; } McRngCallback; +typedef ChaCha20Rng McChaCha20Rng; + typedef FullyValidatedFogPubkey McFullyValidatedFogPubkey; typedef struct McPublicAddressFogInfo { @@ -392,6 +396,99 @@ ssize_t mc_bip39_entropy_from_mnemonic(FfiStr mnemonic, */ FfiOptOwnedStr mc_bip39_words_by_prefix(FfiStr prefix); +/** + * Returns a new ChaCha20Rng instance initialized with the + * seed value provided by the u64 long_val parameter + * + * # Arguments + * + * * `long_val` - an unsigned 64 bit value to use as the rng seed + * + * # Errors + * + * * `LibMcError::Poison` + */ +FfiOptOwnedPtr> mc_chacha20_rng_create_with_long(uint64_t long_val, + FfiOptMutPtr> out_error); + +/** + * Returns a new ChaCha20Rng instance initialized with the + * seed value provided by the bytes data, which must be at + * least 32 bytes (only the first 32 bytes will be used) + * + * # Arguments + * + * * `bytes` - 32 bytes of data to use as the rng seed + * + * # Errors + * + * * `LibMcError::InvalidInput` + * * `LibMcError::Poison` + */ +FfiOptOwnedPtr> mc_chacha20_rng_create_with_bytes(FfiRefPtr bytes, + FfiOptMutPtr> out_error); + +/** + * Returns the current word_pos of the ChaCha20Rng instance + * + * # Arguments + * + * * `chacha20_rng` - must be a valid ChaCha20Rng + * * `out_word_pos` - pointer to buffer of 16 bytes where the current + * chacha20_rng wordpos will be returned + * + * # Errors + * + * * `LibMcError::Poison` + */ +bool mc_chacha20_rng_get_word_pos(FfiMutPtr> chacha20_rng, + FfiMutPtr out_word_pos, + FfiOptMutPtr> out_error); + +/** + * Sets the current word_pos of the ChaCha20Rng instance + * + * /// # Arguments + * + * * `chacha20_rng` - must be a valid ChaCha20Rng + * * `out_word_pos` - pointer to buffer of 128 bytes where the current + * chacha20_rng wordpos will be returned + * + * # Errors + * + * * `LibMcError::Poison` + */ +bool mc_chacha20_rng_set_word_pos(FfiMutPtr> chacha20_rng, + FfiRefPtr bytes, + FfiOptMutPtr> out_error); + +/** + * Returns the next random u64 value from the ChaCha20Rng + * + * /// # Arguments + * + * * `chacha20_rng` - must be a valid ChaCha20Rng + * + * # Errors + * + * * `LibMcError::Poison` + */ +uint64_t mc_chacha20_rng_next_long(FfiMutPtr> chacha20_rng, + FfiOptMutPtr> out_error); + +/** + * frees the ChaCha20Rng + * + * # Preconditions + * + * * The ChaCha20Rng is no longer in use + * + * # Arguments + * + * * `chacha20_rng` - must be a valid ChaCha20Rng + */ +void mc_chacha20_rng_free(FfiOptOwnedPtr> chacha20_rng); + bool mc_ristretto_private_validate(FfiRefPtr ristretto_private, FfiMutPtr out_valid); @@ -760,12 +857,19 @@ bool mc_transaction_builder_ring_add_element(FfiMutPtr FfiRefPtr tx_out_proto_bytes, FfiRefPtr membership_proof_proto_bytes); +/** + * + * # Errors + * + * * `LibMcError::InvalidInput` + */ FfiOptOwnedPtr mc_transaction_builder_create(uint64_t fee, uint64_t token_id, uint64_t tombstone_block, FfiOptRefPtr fog_resolver, FfiMutPtr memo_builder, - uint32_t block_version); + uint32_t block_version, + FfiOptMutPtr> out_error); void mc_transaction_builder_free(FfiOptOwnedPtr transaction_builder); diff --git a/libmobilecoin/src/chacha20_rng.rs b/libmobilecoin/src/chacha20_rng.rs new file mode 100644 index 0000000000..a5ad26915c --- /dev/null +++ b/libmobilecoin/src/chacha20_rng.rs @@ -0,0 +1,145 @@ +use crate::{ + common::{ffi_boundary, ffi_boundary_with_error, McBuffer, McError, McMutableBuffer}, + LibMcError, +}; +use mc_util_ffi::{FfiMutPtr, FfiOptMutPtr, FfiOptOwnedPtr, FfiRefPtr}; +use rand_chacha::ChaCha20Rng; +use rand_core::{RngCore, SeedableRng}; +use std::{convert::TryInto, sync::Mutex}; + +pub type McChaCha20Rng = ChaCha20Rng; + +impl_into_ffi!(Mutex); + +/// Returns a new ChaCha20Rng instance initialized with the +/// seed value provided by the u64 long_val parameter +/// +/// # Arguments +/// +/// * `long_val` - an unsigned 64 bit value to use as the rng seed +/// +/// # Errors +/// +/// * `LibMcError::Poison` +#[no_mangle] +pub extern "C" fn mc_chacha20_rng_create_with_long( + long_val: u64, + out_error: FfiOptMutPtr>, +) -> FfiOptOwnedPtr> { + ffi_boundary_with_error(out_error, || { + Ok(Mutex::new(McChaCha20Rng::seed_from_u64(long_val))) + }) +} + +/// Returns a new ChaCha20Rng instance initialized with the +/// seed value provided by the bytes data, which must be at +/// least 32 bytes (only the first 32 bytes will be used) +/// +/// # Arguments +/// +/// * `bytes` - 32 bytes of data to use as the rng seed +/// +/// # Errors +/// +/// * `LibMcError::InvalidInput` +/// * `LibMcError::Poison` +#[no_mangle] +pub extern "C" fn mc_chacha20_rng_create_with_bytes( + bytes: FfiRefPtr, + out_error: FfiOptMutPtr>, +) -> FfiOptOwnedPtr> { + ffi_boundary_with_error(out_error, || { + let bytes: [u8; 32] = bytes.as_slice_of_len(32)?.try_into().map_err(|_| { + LibMcError::InvalidInput("seed bytes length must be exactly 32 bytes".to_owned()) + })?; + Ok(Mutex::new(McChaCha20Rng::from_seed(bytes))) + }) +} + +/// Returns the current word_pos of the ChaCha20Rng instance +/// +/// # Arguments +/// +/// * `chacha20_rng` - must be a valid ChaCha20Rng +/// * `out_word_pos` - pointer to buffer of 16 bytes where the current +/// chacha20_rng wordpos will be returned +/// +/// # Errors +/// +/// * `LibMcError::Poison` +#[no_mangle] +pub extern "C" fn mc_chacha20_rng_get_word_pos( + chacha20_rng: FfiMutPtr>, + out_word_pos: FfiMutPtr, + out_error: FfiOptMutPtr>, +) -> bool { + ffi_boundary_with_error(out_error, || { + let word_pos = chacha20_rng.lock()?.get_word_pos(); + let out_word_pos = out_word_pos.into_mut().as_slice_mut_of_len(16)?; + out_word_pos.copy_from_slice(&word_pos.to_be_bytes()); + Ok(()) + }) +} + +/// Sets the current word_pos of the ChaCha20Rng instance +/// +/// /// # Arguments +/// +/// * `chacha20_rng` - must be a valid ChaCha20Rng +/// * `out_word_pos` - pointer to buffer of 128 bytes where the current +/// chacha20_rng wordpos will be returned +/// +/// # Errors +/// +/// * `LibMcError::Poison` +#[no_mangle] +pub extern "C" fn mc_chacha20_rng_set_word_pos( + chacha20_rng: FfiMutPtr>, + bytes: FfiRefPtr, + out_error: FfiOptMutPtr>, +) -> bool { + ffi_boundary_with_error(out_error, || { + let bytes: [u8; 16] = bytes.as_slice_of_len(16)?.try_into().map_err(|_| { + LibMcError::InvalidInput( + "bytes length must be exactly 16 bytes for word_pos".to_owned(), + ) + })?; + chacha20_rng + .lock()? + .set_word_pos(u128::from_be_bytes(bytes)); + Ok(()) + }) +} + +/// Returns the next random u64 value from the ChaCha20Rng +/// +/// /// # Arguments +/// +/// * `chacha20_rng` - must be a valid ChaCha20Rng +/// +/// # Errors +/// +/// * `LibMcError::Poison` +#[no_mangle] +pub extern "C" fn mc_chacha20_rng_next_long( + chacha20_rng: FfiMutPtr>, + out_error: FfiOptMutPtr>, +) -> u64 { + ffi_boundary_with_error(out_error, || Ok(chacha20_rng.lock()?.next_u64())) +} + +/// frees the ChaCha20Rng +/// +/// # Preconditions +/// +/// * The ChaCha20Rng is no longer in use +/// +/// # Arguments +/// +/// * `chacha20_rng` - must be a valid ChaCha20Rng +#[no_mangle] +pub extern "C" fn mc_chacha20_rng_free(chacha20_rng: FfiOptOwnedPtr>) { + ffi_boundary(|| { + let _ = chacha20_rng; + }) +} diff --git a/libmobilecoin/src/common/buffer.rs b/libmobilecoin/src/common/buffer.rs index 6146c33ce3..7180591ade 100644 --- a/libmobilecoin/src/common/buffer.rs +++ b/libmobilecoin/src/common/buffer.rs @@ -178,63 +178,21 @@ impl AsMut<[u8]> for McMutableBuffer<'_> { } } -impl<'a> TryFromFfi<&McBuffer<'a>> for &'a [u8; 32] { +impl<'a, const N: usize> TryFromFfi<&McBuffer<'a>> for &'a [u8; N] { type Error = LibMcError; - - #[inline] - fn try_from_ffi(src: &McBuffer<'a>) -> Result { - let src = src.as_slice_of_len(32)?; - // SAFETY: ok to unwrap because we just checked length - Ok(<&[u8; 32]>::try_from(src).unwrap()) - } -} - -impl<'a> TryFromFfi<&McBuffer<'a>> for [u8; 32] { - type Error = LibMcError; - - #[inline] - fn try_from_ffi(src: &McBuffer<'a>) -> Result { - Ok(*<&'a [u8; 32]>::try_from_ffi(src)?) - } -} - -impl<'a> TryFromFfi<&McBuffer<'a>> for &'a [u8; 64] { - type Error = LibMcError; - #[inline] fn try_from_ffi(src: &McBuffer<'a>) -> Result { - let src = src.as_slice_of_len(64)?; + let src = src.as_slice_of_len(N)?; // SAFETY: ok to unwrap because we just checked length - Ok(<&[u8; 64]>::try_from(src).unwrap()) + Ok(<&[u8; N]>::try_from(src).unwrap()) } } -impl<'a> TryFromFfi<&McBuffer<'a>> for [u8; 64] { +impl<'a, const N: usize> TryFromFfi<&McBuffer<'a>> for [u8; N] { type Error = LibMcError; - - #[inline] - fn try_from_ffi(src: &McBuffer<'a>) -> Result { - Ok(*<&'a [u8; 64]>::try_from_ffi(src)?) - } -} - -impl<'a> TryFromFfi<&McBuffer<'a>> for &'a [u8; 66] { - type Error = LibMcError; - - #[inline] - fn try_from_ffi(src: &McBuffer<'a>) -> Result { - let src = src.as_slice_of_len(66)?; - // SAFETY: ok to unwrap because we just checked length - Ok(<&[u8; 66]>::try_from(src).unwrap()) - } -} - -impl<'a> TryFromFfi<&McBuffer<'a>> for [u8; 66] { - type Error = LibMcError; - #[inline] fn try_from_ffi(src: &McBuffer<'a>) -> Result { - Ok(*<&'a [u8; 66]>::try_from_ffi(src)?) + Ok(*<&'a [u8; N]>::try_from_ffi(src)?) } } diff --git a/libmobilecoin/src/error.rs b/libmobilecoin/src/error.rs index e30ccd030a..8bf10850d1 100644 --- a/libmobilecoin/src/error.rs +++ b/libmobilecoin/src/error.rs @@ -14,7 +14,7 @@ use mc_transaction_core::{AmountError, BlockVersionError}; use mc_transaction_std::TxBuilderError; use mc_util_serial::DecodeError; use protobuf::ProtobufError; -use std::os::raw::c_int; +use std::{os::raw::c_int, sync::PoisonError}; impl From for McError { fn from(err: LibMcError) -> Self { @@ -52,6 +52,15 @@ pub enum LibMcError { /// Fog pubkey error: {0}, FogPubkey(String), + + /// Poison + Poison, +} + +impl From> for LibMcError { + fn from(_src: PoisonError) -> Self { + Self::Poison + } } mod error_codes { @@ -59,6 +68,7 @@ mod error_codes { pub const LIB_MC_ERROR_CODE_UNKNOWN: c_int = -1; pub const LIB_MC_ERROR_CODE_PANIC: c_int = -2; + pub const LIB_MC_ERROR_CODE_POISON: c_int = -3; pub const LIB_MC_ERROR_CODE_INVALID_INPUT: c_int = 100; pub const LIB_MC_ERROR_CODE_INVALID_OUTPUT: c_int = 101; @@ -92,6 +102,7 @@ impl LibMcError { } LibMcError::TransactionCrypto(_) => LIB_MC_ERROR_CODE_TRANSACTION_CRYPTO, LibMcError::FogPubkey(_) => LIB_MC_ERROR_CODE_FOG_PUBKEY, + LibMcError::Poison => LIB_MC_ERROR_CODE_POISON, } } diff --git a/libmobilecoin/src/lib.rs b/libmobilecoin/src/lib.rs index d9d4320644..9376345e27 100644 --- a/libmobilecoin/src/lib.rs +++ b/libmobilecoin/src/lib.rs @@ -5,6 +5,7 @@ pub mod common; pub mod attest; pub mod bip39; +pub mod chacha20_rng; pub mod crypto; pub mod encodings; pub mod fog; From 9177cea33e2a82523ba5d6797c8e101b0fc58b10 Mon Sep 17 00:00:00 2001 From: Eran Rundstein Date: Tue, 13 Sep 2022 12:54:44 -0700 Subject: [PATCH 51/77] Cherrypick fog resolver changes that are required for wasm support (#2512) * Feature/fog resolver refactor (#2452) * wip refactoring into separate crates * continued reorg and cleanup of code * adding docs * updating cargo lock * removing default from cargo * updating use of FogResolver * updating FogReportTypes usage * incorrect cargo crate fix * removing dupe import of FogResolver * fixing incorrect crate import * remove unused import * Update fog/report/resolver/Cargo.toml Co-authored-by: Chris Beck * updating comment Co-authored-by: Chris Beck * rework error handling to not rely in visibility into no longer exposed details * cargo fmt * update Cargo.lock * trigger ci? * lock * cargo sort * use non obsolete xcode image * maybe fix ci? Co-authored-by: Brian Corbin Co-authored-by: Chris Beck --- .circleci/config.yml | 4 +- Cargo.lock | 50 ++++- Cargo.toml | 2 + android-bindings/Cargo.toml | 1 + android-bindings/src/bindings.rs | 4 +- attest/verifier/src/status.rs | 2 +- common/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/distribution/src/main.rs | 2 +- fog/ingest/report/Cargo.toml | 14 ++ .../report/src/lib.rs} | 0 fog/report/cli/Cargo.toml | 2 + fog/report/cli/src/main.rs | 6 +- fog/report/connection/src/lib.rs | 2 +- fog/report/resolver/Cargo.toml | 21 ++ fog/report/resolver/src/lib.rs | 91 +++++++++ fog/report/types/src/lib.rs | 35 +++- fog/report/validation/Cargo.toml | 5 - fog/report/validation/src/lib.rs | 191 ++++++++---------- fog/report/validation/src/traits.rs | 85 -------- fog/sample-paykit/Cargo.toml | 1 + fog/sample-paykit/src/cached_tx_data/mod.rs | 13 +- fog/sample-paykit/src/client.rs | 3 +- libmobilecoin/Cargo.toml | 3 + libmobilecoin/src/error.rs | 13 +- libmobilecoin/src/fog.rs | 6 +- libmobilecoin/src/transaction.rs | 2 +- mobilecoind/Cargo.toml | 1 + mobilecoind/src/config.rs | 2 +- transaction/core/Cargo.toml | 2 +- 30 files changed, 323 insertions(+), 244 deletions(-) create mode 100644 fog/ingest/report/Cargo.toml rename fog/{report/validation/src/ingest_report.rs => ingest/report/src/lib.rs} (100%) create mode 100644 fog/report/resolver/Cargo.toml create mode 100644 fog/report/resolver/src/lib.rs delete mode 100644 fog/report/validation/src/traits.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index 670bde1f90..4d28e56811 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ version: 2.1 defaults: builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_29 android-bindings-builder: &android-bindings-builder gcr.io/mobilenode-211420/android-bindings-builder:1_4 - default-xcode-version: &default-xcode-version "12.0.0" + default-xcode-version: &default-xcode-version "12.5.1" default-environment: &default-environment # sccache config @@ -218,7 +218,7 @@ commands: - run: name: Install Homebrew dependencies command: | - rm '/usr/local/lib/python3.8/site-packages/six.py' + rm -f /usr/local/lib/python3.8/site-packages/six.py brew bundle --no-upgrade save-homebrew-cache: diff --git a/Cargo.lock b/Cargo.lock index fe23ecffe9..4e6ef5ca1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2036,7 +2036,10 @@ dependencies = [ "mc-crypto-noise", "mc-crypto-rand", "mc-crypto-sig", + "mc-fog-ingest-report", "mc-fog-kex-rng", + "mc-fog-report-resolver", + "mc-fog-report-types", "mc-fog-report-validation", "mc-transaction-core", "mc-transaction-std", @@ -2278,6 +2281,7 @@ dependencies = [ "mc-crypto-noise", "mc-crypto-rand", "mc-fog-kex-rng", + "mc-fog-report-resolver", "mc-fog-report-types", "mc-fog-report-validation", "mc-transaction-core", @@ -3140,7 +3144,7 @@ dependencies = [ "mc-crypto-keys", "mc-fog-ingest-enclave-measurement", "mc-fog-report-connection", - "mc-fog-report-validation", + "mc-fog-report-resolver", "mc-ledger-db", "mc-transaction-core", "mc-transaction-std", @@ -3323,6 +3327,18 @@ dependencies = [ "mc-util-build-sgx", ] +[[package]] +name = "mc-fog-ingest-report" +version = "2.0.0" +dependencies = [ + "displaydoc", + "mc-attest-core", + "mc-attest-verifier", + "mc-crypto-keys", + "mc-util-encodings", + "serde", +] + [[package]] name = "mc-fog-ingest-server" version = "2.0.0" @@ -3745,6 +3761,8 @@ dependencies = [ "mc-fog-api", "mc-fog-ingest-enclave-measurement", "mc-fog-report-connection", + "mc-fog-report-resolver", + "mc-fog-report-types", "mc-fog-report-validation", "mc-util-cli", "mc-util-keyfile", @@ -3768,6 +3786,21 @@ dependencies = [ "mc-util-uri", ] +[[package]] +name = "mc-fog-report-resolver" +version = "2.0.0" +dependencies = [ + "mc-account-keys", + "mc-attest-verifier", + "mc-fog-ingest-report", + "mc-fog-report-types", + "mc-fog-report-validation", + "mc-fog-sig", + "mc-util-uri", + "mockall", + "serde", +] + [[package]] name = "mc-fog-report-server" version = "2.0.0" @@ -3820,16 +3853,11 @@ version = "2.0.0" dependencies = [ "displaydoc", "mc-account-keys", - "mc-attest-core", - "mc-attest-verifier", "mc-crypto-keys", - "mc-fog-report-types", "mc-fog-sig", - "mc-util-encodings", "mc-util-serial", "mc-util-uri", "mockall", - "serde", ] [[package]] @@ -3865,6 +3893,7 @@ dependencies = [ "mc-fog-ledger-connection", "mc-fog-ledger-enclave-measurement", "mc-fog-report-connection", + "mc-fog-report-resolver", "mc-fog-report-validation", "mc-fog-types", "mc-fog-uri", @@ -4443,6 +4472,7 @@ dependencies = [ "mc-crypto-keys", "mc-crypto-rand", "mc-fog-report-connection", + "mc-fog-report-resolver", "mc-fog-report-validation", "mc-fog-report-validation-test-utils", "mc-ledger-db", @@ -5404,9 +5434,9 @@ dependencies = [ [[package]] name = "mockall" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5641e476bbaf592a3939a7485fa079f427b4db21407d5ebfd5bba4e07a1f6f4c" +checksum = "e2be9a9090bc1cac2930688fa9478092a64c6a92ddc6ae0692d46b37d9cab709" dependencies = [ "cfg-if 1.0.0", "downcast", @@ -5419,9 +5449,9 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262d56735932ee0240d515656e5a7667af3af2a5b0af4da558c4cff2b2aeb0c7" +checksum = "86d702a0530a0141cf4ed147cf5ec7be6f2c187d4e37fcbefc39cf34116bfe8f" dependencies = [ "cfg-if 1.0.0", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 7617453996..4c176b1d88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ members = [ "fog/ingest/enclave/edl", "fog/ingest/enclave/impl", "fog/ingest/enclave/measurement", + "fog/ingest/report", "fog/ingest/server", "fog/kex_rng", "fog/ledger/connection", @@ -71,6 +72,7 @@ members = [ "fog/report/api", "fog/report/cli", "fog/report/connection", + "fog/report/resolver", "fog/report/server", "fog/report/types", "fog/report/validation", diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index 19cfd1da82..cb091fdedd 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -29,6 +29,7 @@ mc-crypto-box = { path = "../crypto/box" } mc-crypto-keys = { path = "../crypto/keys" } mc-crypto-noise = { path = "../crypto/noise" } mc-crypto-rand = { path = "../crypto/rand", features = ["std"] } +mc-fog-report-resolver = { path = "../fog/report/resolver" } mc-fog-report-types = { path = "../fog/report/types" } mc-fog-report-validation = { path = "../fog/report/validation" } mc-transaction-core = { path = "../transaction/core" } diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index a10978a25c..88c884d7b3 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -39,8 +39,8 @@ use mc_crypto_box::{CryptoBox, VersionedCryptoBox}; use mc_crypto_keys::{CompressedRistrettoPublic, RistrettoPrivate, RistrettoPublic, X25519}; use mc_crypto_rand::McRng; use mc_fog_kex_rng::{BufferedRng, KexRngPubkey, NewFromKex, StoredRng, VersionedKexRng}; -use mc_fog_report_types::{Report, ReportResponse}; -use mc_fog_report_validation::{FogReportResponses, FogResolver}; +use mc_fog_report_resolver::FogResolver; +use mc_fog_report_types::{FogReportResponses, Report, ReportResponse}; use mc_transaction_core::{ get_tx_out_shared_secret, onetime_keys::{ diff --git a/attest/verifier/src/status.rs b/attest/verifier/src/status.rs index f498452100..423dc3879f 100644 --- a/attest/verifier/src/status.rs +++ b/attest/verifier/src/status.rs @@ -666,7 +666,7 @@ mod test { } /// Ensure a CONFIGURATION_AND_SW_HARDENING_NEEDED result with the expected - /// MRENCLAVE but an insufficient sw and config advisory allow-listing + /// MRENCLAVE but an insufficient sw and config advisory allow-listing /// fails. #[test] fn mrenclave_multi_config_sw_fail_short() { diff --git a/common/Cargo.toml b/common/Cargo.toml index bc1716fb48..381584d058 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -71,5 +71,5 @@ slog-stdlog = { version = "4.1.1", optional = true } slog-term = { version = "2.9", optional = true } [dev-dependencies] -scoped_threadpool = "0.1.*" proptest = { version = "1.0", default-features = false, features = ["default-code-coverage"] } +scoped_threadpool = "0.1.*" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index 851150f2d8..52dbfeee3a 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -19,7 +19,7 @@ mc-consensus-enclave-measurement = { path = "../../consensus/enclave/measurement mc-crypto-keys = { path = "../../crypto/keys" } mc-fog-ingest-enclave-measurement = { path = "../ingest/enclave/measurement" } mc-fog-report-connection = { path = "../../fog/report/connection" } -mc-fog-report-validation = { path = "../../fog/report/validation" } +mc-fog-report-resolver = { path = "../../fog/report/resolver" } mc-ledger-db = { path = "../../ledger/db" } mc-transaction-core = { path = "../../transaction/core" } mc-transaction-std = { path = "../../transaction/std" } diff --git a/fog/distribution/src/main.rs b/fog/distribution/src/main.rs index 2ac3410eb8..13b06558a4 100755 --- a/fog/distribution/src/main.rs +++ b/fog/distribution/src/main.rs @@ -34,7 +34,7 @@ use mc_connection::{ use mc_crypto_keys::{CompressedRistrettoPublic, RistrettoPublic}; use mc_fog_distribution::Config; use mc_fog_report_connection::{Error as ReportConnError, GrpcFogReportConnection}; -use mc_fog_report_validation::FogResolver; +use mc_fog_report_resolver::FogResolver; use mc_ledger_db::{Ledger, LedgerDB}; use mc_transaction_core::{ get_tx_out_shared_secret, diff --git a/fog/ingest/report/Cargo.toml b/fog/ingest/report/Cargo.toml new file mode 100644 index 0000000000..25d802fed0 --- /dev/null +++ b/fog/ingest/report/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "mc-fog-ingest-report" +version = "2.0.0" +authors = ["MobileCoin"] +edition = "2021" + +[dependencies] +mc-attest-core = { path = "../../../attest/core", default-features = false } +mc-attest-verifier = { path = "../../../attest/verifier", default-features = false } +mc-crypto-keys = { path = "../../../crypto/keys" } +mc-util-encodings = { path = "../../../util/encodings" } + +displaydoc = { version = "0.2", default-features = false } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } diff --git a/fog/report/validation/src/ingest_report.rs b/fog/ingest/report/src/lib.rs similarity index 100% rename from fog/report/validation/src/ingest_report.rs rename to fog/ingest/report/src/lib.rs diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index 6de1e31cba..cce62e8831 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -18,6 +18,8 @@ mc-crypto-keys = { path = "../../../crypto/keys" } mc-fog-api = { path = "../../api" } mc-fog-ingest-enclave-measurement = { path = "../../ingest/enclave/measurement" } mc-fog-report-connection = { path = "../connection" } +mc-fog-report-resolver = { path = "../resolver" } +mc-fog-report-types = { path = "../types" } mc-fog-report-validation = { path = "../validation" } mc-util-cli = { path = "../../../util/cli" } mc-util-keyfile = { path = "../../../util/keyfile" } diff --git a/fog/report/cli/src/main.rs b/fog/report/cli/src/main.rs index 16b1df29fc..6d66d97c47 100644 --- a/fog/report/cli/src/main.rs +++ b/fog/report/cli/src/main.rs @@ -22,9 +22,9 @@ use mc_common::logger::{create_root_logger, log, Logger}; use mc_crypto_keys::{CompressedRistrettoPublic, RistrettoPublic}; use mc_fog_api::report_parse::try_extract_unvalidated_ingress_pubkey_from_fog_report; use mc_fog_report_connection::{Error, GrpcFogReportConnection}; -use mc_fog_report_validation::{ - FogPubkeyResolver, FogReportResponses, FogResolver, FullyValidatedFogPubkey, -}; +use mc_fog_report_resolver::FogResolver; +use mc_fog_report_types::FogReportResponses; +use mc_fog_report_validation::{FogPubkeyResolver, FullyValidatedFogPubkey}; use mc_util_cli::ParserWithBuildInfo; use mc_util_uri::FogUri; use std::{ diff --git a/fog/report/connection/src/lib.rs b/fog/report/connection/src/lib.rs index 1b544890a6..2fee2e87be 100644 --- a/fog/report/connection/src/lib.rs +++ b/fog/report/connection/src/lib.rs @@ -15,7 +15,7 @@ use mc_util_grpc::ConnectionUriGrpcioChannel; use mc_util_uri::FogUri; use std::sync::Arc; -pub use mc_fog_report_validation::FogReportResponses; +pub use mc_fog_report_types::FogReportResponses; /// Fog report server connection based on grpcio /// diff --git a/fog/report/resolver/Cargo.toml b/fog/report/resolver/Cargo.toml new file mode 100644 index 0000000000..f90b2518c0 --- /dev/null +++ b/fog/report/resolver/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "mc-fog-report-resolver" +version = "2.0.0" +authors = ["MobileCoin"] +edition = "2021" + +[features] +default = [] +automock = ["mockall"] + +[dependencies] +mc-account-keys = { path = "../../../account-keys" } +mc-attest-verifier = { path = "../../../attest/verifier", default-features = false } +mc-fog-ingest-report = { path = "../../ingest/report" } +mc-fog-report-types = { path = "../types" } +mc-fog-report-validation = { path = "../validation" } +mc-fog-sig = { path = "../../sig", default-features = false } +mc-util-uri = { path = "../../../util/uri" } + +mockall = { version = "0.11.2", optional = true } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } diff --git a/fog/report/resolver/src/lib.rs b/fog/report/resolver/src/lib.rs new file mode 100644 index 0000000000..0d09506cfa --- /dev/null +++ b/fog/report/resolver/src/lib.rs @@ -0,0 +1,91 @@ +// Copyright (c) 2018-2022 The MobileCoin Foundation + +//! Logic for representing fog public keys from the fog-report server +//! that have been fully validated, and the associated metadata. + +#![deny(missing_docs)] + +extern crate alloc; + +use mc_fog_report_validation::{FogPubkeyError, FogPubkeyResolver, FullyValidatedFogPubkey}; + +use mc_fog_ingest_report::IngestReportVerifier; + +use alloc::string::{String, ToString}; +use core::str::FromStr; +use mc_account_keys::PublicAddress; +use mc_attest_verifier::Verifier; +use mc_fog_report_types::{FogReportResponses, ReportResponse}; +use mc_fog_sig::Verifier as FogSigVerifier; +use mc_util_uri::{FogUri, UriParseError}; +use serde::{Deserialize, Serialize}; + +/// A collection of unvalidated fog reports, together with an IAS verifier. +/// This object is passed to the TransactionBuilder object. +/// When fog is not involved, it can simply be defaulted. +/// +/// Once constructed, this object can get validated fog pubkeys to build fog +/// hints for transactions, without talking to the internet, and so is +/// compatible with offline transactions to fog recipients. Only getting the +/// FogReportResponses requires an online connection. +#[derive(Default, Clone, Debug, Serialize, Deserialize)] +pub struct FogResolver { + responses: FogReportResponses, + verifier: IngestReportVerifier, +} + +impl FogResolver { + /// Create a new FogResolver object, given serialized (unverified) + /// fog report server responses, + /// and an attestation verifier for fog ingest measurements. + pub fn new(responses: FogReportResponses, verifier: &Verifier) -> Result { + // Normalize URI strings + let responses: FogReportResponses = responses + .into_iter() + .map( + |(uri_str, resp)| -> Result<(String, ReportResponse), UriParseError> { + let uri = FogUri::from_str(&uri_str)?.to_string(); + Ok((uri, resp)) + }, + ) + .collect::>()?; + Ok(Self { + responses, + verifier: IngestReportVerifier::from(verifier), + }) + } +} + +impl FogPubkeyResolver for FogResolver { + fn get_fog_pubkey( + &self, + recipient: &PublicAddress, + ) -> Result { + let url = recipient + .fog_report_url() + .ok_or(FogPubkeyError::NoFogReportUrl)?; + // Normalize the string to URL before lookup + let url = FogUri::from_str(url)?.to_string(); + if let Some(result) = self.responses.get(&url) { + // Verify the authority signature chain + recipient.verify_fog_sig(result)?; + // Get the report corresponding to our ID + let report_id = recipient.fog_report_id().unwrap_or("").to_string(); + for report in result.reports.iter() { + if report_id == report.fog_report_id { + let pubkey = self + .verifier + .validate_ingest_ias_report(report.report.clone()) + .map_err(|e| FogPubkeyError::IngestReport(e.to_string()))?; + return Ok(FullyValidatedFogPubkey { + pubkey, + pubkey_expiry: report.pubkey_expiry, + }); + } + } + Err(FogPubkeyError::NoMatchingReportId(url, report_id)) + } else { + Err(FogPubkeyError::NoMatchingReportResponse(url)) + } + } +} diff --git a/fog/report/types/src/lib.rs b/fog/report/types/src/lib.rs index 95206c5f93..680a0b019b 100644 --- a/fog/report/types/src/lib.rs +++ b/fog/report/types/src/lib.rs @@ -9,7 +9,7 @@ extern crate alloc; -use alloc::{string::String, vec::Vec}; +use alloc::{collections::BTreeMap, string::String, vec::Vec}; use mc_attest_core::VerificationReport; use mc_crypto_digestible::Digestible; use prost::Message; @@ -46,3 +46,36 @@ pub struct ReportResponse { #[prost(bytes, tag = "3")] pub signature: Vec, } + +/// Represents a set of unvalidated responses from Fog report servers +/// Key = Fog-url that was contacted, must match the string in user's public +/// address Value = The complete response from the fog report server +/// +/// When constructing a transaction, the fog-url for each recipient should be +/// extracted from their public address, then a request to that report server +/// should be made. The responses should be collected in a map-structure (like +/// this). This should be done for each recipient. +/// +/// This map structure is ultimately consumed by the TransactionBuilder object, +/// which validates the responses against the fog data in the public addresses +/// when building the transaction. +/// +/// This map structure should not be cached, because the fog pubkeys have an +/// expiry date and don't live that long. They can be cached for a short time, +/// but the transaction builder enforces that the tombstone block for the +/// transaction is limited by the pubkey expiry value of any fog pubkey that is +/// used, so if these are cached too long, the transaction will be rejected by +/// consensus. +/// +/// In the case of constructing off-line transactions with Fog recipients, the +/// flow is: (1) Take fog-urls from (offline) public addresses to the online +/// machine (2) Hit the fog report servers (online machine), producing +/// FogReportResponses (3) Take FogReportResponses to the offline machine, and +/// use with transaction builder, to create the transaction offline. +/// (4) Take the constructed transaction to the online machine and submit to +/// consensus. +/// +/// Note: there is no particular reason for this to be BTreeMap instead of +/// HashMap, except that it is slightly more portable, only requiring the alloc +/// crate. +pub type FogReportResponses = BTreeMap; diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index a10409491e..e528262e2c 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -10,15 +10,10 @@ automock = ["mockall"] [dependencies] mc-account-keys = { path = "../../../account-keys" } -mc-attest-core = { path = "../../../attest/core", default-features = false } -mc-attest-verifier = { path = "../../../attest/verifier", default-features = false } mc-crypto-keys = { path = "../../../crypto/keys" } -mc-fog-report-types = { path = "../types" } mc-fog-sig = { path = "../../sig", default-features = false } -mc-util-encodings = { path = "../../../util/encodings" } mc-util-serial = { path = "../../../util/serial" } mc-util-uri = { path = "../../../util/uri" } displaydoc = { version = "0.2", default-features = false } mockall = { version = "0.11.0", optional = true } -serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } diff --git a/fog/report/validation/src/lib.rs b/fog/report/validation/src/lib.rs index 42269bea90..04dccc36b1 100644 --- a/fog/report/validation/src/lib.rs +++ b/fog/report/validation/src/lib.rs @@ -14,127 +14,104 @@ extern crate alloc; -mod traits; +use core::fmt::{Debug, Display}; +use displaydoc::Display; +use mc_account_keys::PublicAddress; +use mc_crypto_keys::RistrettoPublic; +use mc_fog_sig::Error as FogSigError; +use mc_util_uri::UriParseError; +#[cfg(feature = "automock")] +use mockall::*; +use std::collections::HashMap; -/// Data structure for fog-ingest report validation -pub mod ingest_report; +/// Class that can resolve a public address to a fully-validated fog public key +/// structure, including the pubkey expiry data from the report server. +#[cfg_attr(feature = "automock", automock)] +pub trait FogPubkeyResolver { + /// Fetch and validate a fog public key, given a recipient's public address + fn get_fog_pubkey( + &self, + recipient: &PublicAddress, + ) -> Result; +} -#[cfg(feature = "automock")] -pub use crate::traits::MockFogPubkeyResolver; -pub use crate::traits::{FogPubkeyError, FogPubkeyResolver, FullyValidatedFogPubkey}; +/// Represents a fog public key validated to use for creating encrypted fog +/// hints. This object should be constructed only when the IAS report has been +/// validated, and the chain of trust from the connection has been validated, +/// and the the fog user's fog_authority_sig over the root subjectPublicKeyInfo +/// in the signature chain has been validated. +#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] +pub struct FullyValidatedFogPubkey { + /// The ristretto curve point which was extracted from the IAS report + /// additional data after validation. This is the encryption key used to + /// create encrypted fog hints. The corresponding private key lives only + /// in SGX ingest nodes. + pub pubkey: RistrettoPublic, + /// The pubkey_expiry value is the latest block that fog-service promises + /// that is valid to encrypt fog hints using this key for. + /// The client should obey this limit by not setting tombstone block for a + /// transaction larger than this limit if the fog pubkey is used. + pub pubkey_expiry: u64, +} -use crate::ingest_report::IngestReportVerifier; -use alloc::{ - collections::BTreeMap, - string::{String, ToString}, -}; -use core::str::FromStr; -use mc_account_keys::PublicAddress; -use mc_attest_verifier::Verifier; -use mc_fog_report_types::ReportResponse; -use mc_fog_sig::Verifier as FogSigVerifier; -use mc_util_uri::{FogUri, UriParseError}; -use serde::{Deserialize, Serialize}; +/// An error that can occur when trying to get a validated fog pubkey from the +/// FogResolver object +/// TODO: Add x509 errors, user-sig check errors, etc. here +#[derive(Display, Debug)] +pub enum FogPubkeyError { + /// No matching reports response for url = {0} + NoMatchingReportResponse(String), + /// No matching report id for url = {0}, report_id = {1} + NoMatchingReportId(String, String), + /// Address has no fog_report_url, cannot fetch fog pubkey + NoFogReportUrl, + /// Failed to parse fog url: {0} + Url(UriParseError), + /// Ingest report deserialization error: {0}, + Deserialization(mc_util_serial::decode::Error), + /// Ingest report verification error: {0} + IngestReport(String), + /// Authority verification error: {0} + Authority(String), +} -/// Represents a set of unvalidated responses from Fog report servers -/// Key = Fog-url that was contacted, must match the string in user's public -/// address Value = The complete response from the fog report server -/// -/// When constructing a transaction, the fog-url for each recipient should be -/// extracted from their public address, then a request to that report server -/// should be made. The responses should be collected in a map-structure (like -/// this). This should be done for each recipient. -/// -/// This map structure is ultimately consumed by the TransactionBuilder object, -/// which validates the responses against the fog data in the public addresses -/// when building the transaction. -/// -/// This map structure should not be cached, because the fog pubkeys have an -/// expiry date and don't live that long. They can be cached for a short time, -/// but the transaction builder enforces that the tombstone block for the -/// transaction is limited by the pubkey expiry value of any fog pubkey that is -/// used, so if these are cached too long, the transaction will be rejected by -/// consensus. -/// -/// In the case of constructing off-line transactions with Fog recipients, the -/// flow is: (1) Take fog-urls from (offline) public addresses to the online -/// machine (2) Hit the fog report servers (online machine), producing -/// FogReportResponses (3) Take FogReportResponses to the offline machine, and -/// use with transaction builder, to create the transaction offline. -/// (4) Take the constructed transaction to the online machine and submit to -/// consensus. -/// -/// Note: there is no particular reason for this to be BTreeMap instead of -/// HashMap, except that it is slightly more portable, only requiring the alloc -/// crate. -pub type FogReportResponses = BTreeMap; +impl From for FogPubkeyError { + fn from(src: mc_util_serial::decode::Error) -> Self { + Self::Deserialization(src) + } +} -/// A collection of unvalidated fog reports, together with an IAS verifier. -/// This object is passed to the TransactionBuilder object. -/// When fog is not involved, it can simply be defaulted. -/// -/// Once constructed, this object can get validated fog pubkeys to build fog -/// hints for transactions, without talking to the internet, and so is -/// compatible with offline transactions to fog recipients. Only getting the -/// FogReportResponses requires an online connection. -#[derive(Default, Clone, Debug, Serialize, Deserialize)] -pub struct FogResolver { - responses: FogReportResponses, - verifier: IngestReportVerifier, +impl From for FogPubkeyError { + fn from(src: UriParseError) -> Self { + Self::Url(src) + } } +impl From> for FogPubkeyError { + fn from(src: FogSigError) -> Self { + FogPubkeyError::Authority(src.to_string()) + } +} + +/// A basic implementation of the FogPubkeyResolver trait that must be seeded +/// with a HashMap of PublicAddresses to FullValidatedFogPubkeys. +pub struct FogResolver(HashMap); + impl FogResolver { - /// Create a new FogResolver object, given serialized (unverified) - /// fog report server responses, - /// and an attestation verifier for fog ingest measurements. - pub fn new(responses: FogReportResponses, verifier: &Verifier) -> Result { - // Normalize URI strings - let responses: FogReportResponses = responses - .into_iter() - .map( - |(uri_str, resp)| -> Result<(String, ReportResponse), UriParseError> { - let uri = FogUri::from_str(&uri_str)?.to_string(); - Ok((uri, resp)) - }, - ) - .collect::>()?; - Ok(Self { - responses, - verifier: IngestReportVerifier::from(verifier), - }) + /// Create a new FogResolver with an filled HashMap of responses + pub fn new(responses: HashMap) -> Self { + FogResolver(responses) } } impl FogPubkeyResolver for FogResolver { fn get_fog_pubkey( &self, - recipient: &PublicAddress, + address: &PublicAddress, ) -> Result { - if let Some(url) = recipient.fog_report_url() { - // Normalize the string to URL before lookup - let url = FogUri::from_str(url)?.to_string(); - if let Some(result) = self.responses.get(&url) { - // Verify the authority signature chain - recipient.verify_fog_sig(result)?; - // Get the report corresponding to our ID - let report_id = recipient.fog_report_id().unwrap_or("").to_string(); - for report in result.reports.iter() { - if report_id == report.fog_report_id { - let pubkey = self - .verifier - .validate_ingest_ias_report(report.report.clone())?; - return Ok(FullyValidatedFogPubkey { - pubkey, - pubkey_expiry: report.pubkey_expiry, - }); - } - } - Err(FogPubkeyError::NoMatchingReportId(url, report_id)) - } else { - Err(FogPubkeyError::NoMatchingReportResponse(url)) - } - } else { - Err(FogPubkeyError::NoFogReportUrl) - } + self.0 + .get(address) + .cloned() + .ok_or(FogPubkeyError::NoFogReportUrl) } } diff --git a/fog/report/validation/src/traits.rs b/fog/report/validation/src/traits.rs deleted file mode 100644 index 8d5b4f14d3..0000000000 --- a/fog/report/validation/src/traits.rs +++ /dev/null @@ -1,85 +0,0 @@ -#[cfg(feature = "automock")] -use mockall::*; - -use crate::ingest_report::Error as IngestReportError; -use core::fmt::{Debug, Display}; -use displaydoc::Display; -use mc_account_keys::PublicAddress; -use mc_crypto_keys::RistrettoPublic; -use mc_fog_sig::Error as FogSigError; -use mc_util_uri::UriParseError; - -/// Class that can resolve a public address to a fully-validated fog public key -/// structure, including the pubkey expiry data from the report server. -#[cfg_attr(feature = "automock", automock)] -pub trait FogPubkeyResolver { - /// Fetch and validate a fog public key, given a recipient's public address - fn get_fog_pubkey( - &self, - recipient: &PublicAddress, - ) -> Result; -} - -/// Represents a fog public key validated to use for creating encrypted fog -/// hints. This object should be constructed only when the IAS report has been -/// validated, and the chain of trust from the connection has been validated, -/// and the the fog user's fog_authority_sig over the root subjectPublicKeyInfo -/// in the signature chain has been validated. -#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] -pub struct FullyValidatedFogPubkey { - /// The ristretto curve point which was extracted from the IAS report - /// additional data after validation. This is the encryption key used to - /// create encrypted fog hints. The corresponding private key lives only - /// in SGX ingest nodes. - pub pubkey: RistrettoPublic, - /// The pubkey_expiry value is the latest block that fog-service promises - /// that is valid to encrypt fog hints using this key for. - /// The client should obey this limit by not setting tombstone block for a - /// transaction larger than this limit if the fog pubkey is used. - pub pubkey_expiry: u64, -} - -/// An error that can occur when trying to get a validated fog pubkey from the -/// FogResolver object -/// TODO: Add x509 errors, user-sig check errors, etc. here -#[derive(Display, Debug)] -pub enum FogPubkeyError { - /// No matching reports response for url = {0} - NoMatchingReportResponse(String), - /// No matching report id for url = {0}, report_id = {1} - NoMatchingReportId(String, String), - /// Address has no fog_report_url, cannot fetch fog pubkey - NoFogReportUrl, - /// Failed to parse fog url: {0} - Url(UriParseError), - /// Ingest report deserialization error: {0}, - Deserialization(mc_util_serial::decode::Error), - /// Ingest report verification error: {0} - IngestReport(IngestReportError), - /// Authority verification error: {0} - Authority(String), -} - -impl From for FogPubkeyError { - fn from(src: IngestReportError) -> Self { - Self::IngestReport(src) - } -} - -impl From for FogPubkeyError { - fn from(src: mc_util_serial::decode::Error) -> Self { - Self::Deserialization(src) - } -} - -impl From for FogPubkeyError { - fn from(src: UriParseError) -> Self { - Self::Url(src) - } -} - -impl From> for FogPubkeyError { - fn from(src: FogSigError) -> Self { - FogPubkeyError::Authority(src.to_string()) - } -} diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index bff6c1bcbf..fda740f475 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -40,6 +40,7 @@ mc-fog-ingest-enclave-measurement = { path = "../ingest/enclave/measurement" } mc-fog-ledger-connection = { path = "../ledger/connection" } mc-fog-ledger-enclave-measurement = { path = "../ledger/enclave/measurement" } mc-fog-report-connection = { path = "../../fog/report/connection" } +mc-fog-report-resolver = { path = "../../fog/report/resolver" } mc-fog-report-validation = { path = "../../fog/report/validation" } mc-fog-types = { path = "../types" } mc-fog-uri = { path = "../uri" } diff --git a/fog/sample-paykit/src/cached_tx_data/mod.rs b/fog/sample-paykit/src/cached_tx_data/mod.rs index 8afc2cf3bc..ad2df762cb 100644 --- a/fog/sample-paykit/src/cached_tx_data/mod.rs +++ b/fog/sample-paykit/src/cached_tx_data/mod.rs @@ -9,8 +9,7 @@ use core::{ }; use displaydoc::Display; use mc_account_keys::{ - AccountKey, PublicAddress, CHANGE_SUBADDRESS_INDEX, - INVALID_SUBADDRESS_INDEX, + AccountKey, PublicAddress, CHANGE_SUBADDRESS_INDEX, INVALID_SUBADDRESS_INDEX, }; use mc_common::logger::{log, Logger}; use mc_crypto_keys::RistrettoPublic; @@ -68,11 +67,11 @@ const TELEMETRY_NUM_TXOS_KEY: Key = telemetry_static_key!("num-txos"); /// default and change subaddress indexes. /// /// Note: We also put the historical change subaddress of 1 in this range. -/// This is because we ran the test client as a canary for several months using 1 -/// as the change subaddress, so those accounts now have many subaddress index 1 TxOuts. -/// Adding this to the searched range means that they don't lose all this money, -/// and also silences the warnings when they get TxOuts from fog on "unexpected" -/// subaddresses. +/// This is because we ran the test client as a canary for several months using +/// 1 as the change subaddress, so those accounts now have many subaddress index +/// 1 TxOuts. Adding this to the searched range means that they don't lose all +/// this money, and also silences the warnings when they get TxOuts from fog on +/// "unexpected" subaddresses. const HISTORICAL_CHANGE_SUBADDRESS_INDEX: u64 = 1; const SUBADDRESS_LOW_RANGE: RangeInclusive = 0..=HISTORICAL_CHANGE_SUBADDRESS_INDEX; const SUBADDRESS_HIGH_RANGE: Range = CHANGE_SUBADDRESS_INDEX..INVALID_SUBADDRESS_INDEX; diff --git a/fog/sample-paykit/src/client.rs b/fog/sample-paykit/src/client.rs index d915839d36..9bbd27ceb2 100644 --- a/fog/sample-paykit/src/client.rs +++ b/fog/sample-paykit/src/client.rs @@ -22,7 +22,8 @@ use mc_fog_ledger_connection::{ FogUntrustedLedgerGrpcClient, OutputResultExtension, }; use mc_fog_report_connection::GrpcFogReportConnection; -use mc_fog_report_validation::{FogPubkeyResolver, FogResolver}; +use mc_fog_report_resolver::FogResolver; +use mc_fog_report_validation::FogPubkeyResolver; use mc_fog_types::BlockCount; use mc_fog_view_connection::FogViewGrpcClient; use mc_transaction_core::{ diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index b8d46595b4..863d206819 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -43,7 +43,10 @@ mc-crypto-keys = { path = "../crypto/keys" } mc-crypto-noise = { path = "../crypto/noise" } mc-crypto-rand = { path = "../crypto/rand", features = ["std"] } mc-crypto-sig = { path = "../crypto/sig" } +mc-fog-ingest-report = { path = "../fog/ingest/report" } mc-fog-kex-rng = { path = "../fog/kex_rng" } +mc-fog-report-resolver = { path = "../fog/report/resolver" } +mc-fog-report-types = { path = "../fog/report/types" } mc-fog-report-validation = { path = "../fog/report/validation" } mc-transaction-core = { path = "../transaction/core" } mc-transaction-std = { path = "../transaction/std" } diff --git a/libmobilecoin/src/error.rs b/libmobilecoin/src/error.rs index 8bf10850d1..9bb5638b3d 100644 --- a/libmobilecoin/src/error.rs +++ b/libmobilecoin/src/error.rs @@ -9,7 +9,7 @@ use mc_crypto_box::{AeadError, Error as CryptoBoxError}; use mc_crypto_keys::KeyError; use mc_crypto_noise::CipherError; use mc_fog_kex_rng::Error as FogKexRngError; -use mc_fog_report_validation::{ingest_report::Error as IngestReportError, FogPubkeyError}; +use mc_fog_report_validation::FogPubkeyError; use mc_transaction_core::{AmountError, BlockVersionError}; use mc_transaction_std::TxBuilderError; use mc_util_serial::DecodeError; @@ -195,11 +195,8 @@ impl From for LibMcError { impl From for LibMcError { fn from(err: TxBuilderError) -> Self { - if let TxBuilderError::FogPublicKey(FogPubkeyError::IngestReport( - IngestReportError::Verifier(VerifierError::Verification(_)), - )) = err - { - LibMcError::AttestationVerificationFailed(format!("{:?}", err)) + if let TxBuilderError::FogPublicKey(fog_pub_key_err) = err { + LibMcError::from(fog_pub_key_err) } else { LibMcError::InvalidInput(format!("{:?}", err)) } @@ -213,10 +210,6 @@ impl From for LibMcError { | FogPubkeyError::Url(_) | FogPubkeyError::Deserialization(_) => LibMcError::InvalidInput(err.to_string()), - FogPubkeyError::IngestReport(IngestReportError::Verifier( - VerifierError::Verification(_), - )) => LibMcError::AttestationVerificationFailed(err.to_string()), - _ => LibMcError::FogPubkey(err.to_string()), } } diff --git a/libmobilecoin/src/fog.rs b/libmobilecoin/src/fog.rs index a31e65bd9c..e89e8bba3c 100644 --- a/libmobilecoin/src/fog.rs +++ b/libmobilecoin/src/fog.rs @@ -7,9 +7,9 @@ use mc_account_keys::PublicAddress; use mc_attest_verifier::Verifier; use mc_crypto_keys::{ReprBytes, RistrettoPrivate, RistrettoPublic}; use mc_fog_kex_rng::{BufferedRng, KexRngPubkey, NewFromKex, StoredRng, VersionedKexRng}; -use mc_fog_report_validation::{ - FogPubkeyResolver, FogReportResponses, FogResolver, FullyValidatedFogPubkey, -}; +use mc_fog_report_resolver::FogResolver; +use mc_fog_report_types::FogReportResponses; +use mc_fog_report_validation::{FogPubkeyResolver, FullyValidatedFogPubkey}; use mc_util_ffi::*; use mc_util_serial::Message; use mc_util_uri::FogUri; diff --git a/libmobilecoin/src/transaction.rs b/libmobilecoin/src/transaction.rs index a52c6e0771..8a5742a65d 100644 --- a/libmobilecoin/src/transaction.rs +++ b/libmobilecoin/src/transaction.rs @@ -12,7 +12,7 @@ use crc::Crc; use generic_array::{typenum::U66, GenericArray}; use mc_account_keys::{AccountKey, PublicAddress, ShortAddressHash}; use mc_crypto_keys::{CompressedRistrettoPublic, ReprBytes, RistrettoPrivate, RistrettoPublic}; -use mc_fog_report_validation::FogResolver; +use mc_fog_report_resolver::FogResolver; use mc_transaction_core::{ get_tx_out_shared_secret, onetime_keys::{recover_onetime_private_key, recover_public_subaddress_spend_key}, diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index b76a9ee6bb..2ed447165a 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -28,6 +28,7 @@ mc-crypto-hashes = { path = "../crypto/hashes" } mc-crypto-keys = { path = "../crypto/keys" } mc-crypto-rand = { path = "../crypto/rand" } mc-fog-report-connection = { path = "../fog/report/connection" } +mc-fog-report-resolver = { path = "../fog/report/resolver" } mc-fog-report-validation = { path = "../fog/report/validation" } mc-ledger-db = { path = "../ledger/db" } mc-ledger-migration = { path = "../ledger/migration" } diff --git a/mobilecoind/src/config.rs b/mobilecoind/src/config.rs index fcdfb58889..a0f6605e41 100644 --- a/mobilecoind/src/config.rs +++ b/mobilecoind/src/config.rs @@ -10,7 +10,7 @@ use mc_common::{logger::Logger, ResponderId}; use mc_connection::{ConnectionManager, HardcodedCredentialsProvider, ThickClient}; use mc_consensus_scp::QuorumSet; use mc_fog_report_connection::GrpcFogReportConnection; -use mc_fog_report_validation::FogResolver; +use mc_fog_report_resolver::FogResolver; use mc_mobilecoind_api::MobilecoindUri; use mc_sgx_css::Signature; use mc_util_parse::{load_css_file, parse_duration_in_seconds}; diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index 2ec32e8bc4..9eaaabd4c7 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -46,10 +46,10 @@ curve25519-dalek = { version = "4.0.0-pre.2", default-features = false, features curve25519-dalek = { version = "4.0.0-pre.2", default-features = false, features = ["nightly", "u64_backend"] } [dev-dependencies] +proptest = { version = "1.0", default-features = false, features = ["default-code-coverage"] } rand = "0.8" rand_hc = "0.3" tempdir = "0.3" -proptest = { version = "1.0", default-features = false, features = ["default-code-coverage"] } mc-crypto-digestible-test-utils = { path = "../../crypto/digestible/test-utils" } mc-crypto-rand = { path = "../../crypto/rand" } From e2f1c33a0d2e700d5f12fe7055071f00890d5c19 Mon Sep 17 00:00:00 2001 From: Eran Rundstein Date: Tue, 13 Sep 2022 16:12:10 -0700 Subject: [PATCH 52/77] Cherrypick PR #2502 that made targetting wasm work (#2520) * Eran/wasm experiment (#2502) * wasm build support * poc * use OsRng * simple test * rename and simplify test * meh * try to add wasm-pack build to ci, to support copper * fixup * fixup * fix version * update Cargo.lock * lock files * cargo sort Co-authored-by: Eran Rundstein * add wasm tests to circleci * lock file * try without sccache * wrestle ci * Revert "try without sccache" This reverts commit 7d7f45117cf4c9ff5f2231ecdb8c77723e2a03b8. Co-authored-by: Chris Beck --- .circleci/config.yml | 33 +++++++++++++++++ Cargo.lock | 53 ++++++++++++++++++++++++++- Cargo.toml | 1 + attest/core/Cargo.toml | 2 +- attest/core/src/nonce.rs | 2 +- consensus/enclave/trusted/Cargo.lock | 2 +- crypto/rand/src/lib.rs | 3 ++ crypto/rand/src/wasm.rs | 5 +++ fog/ingest/enclave/trusted/Cargo.lock | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 2 +- fog/view/enclave/trusted/Cargo.lock | 2 +- util/build/script/src/env.rs | 3 ++ wasm-test/Cargo.toml | 25 +++++++++++++ wasm-test/src/lib.rs | 20 ++++++++++ 14 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 crypto/rand/src/wasm.rs create mode 100644 wasm-test/Cargo.toml create mode 100644 wasm-test/src/lib.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index 4d28e56811..42b97cc85b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -368,6 +368,22 @@ commands: - store_artifacts: path: /tmp/core_dumps + run-wasm-tests: + steps: + - run: + name: Run wasm tests + command: | + curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | bash + apt-get install -y clang-10 nodejs + CC=clang-10 wasm-pack test --node wasm-test + - run: + command: | + mkdir -p /tmp/core_dumps + cp core.* /tmp/core_dumps + when: on_fail + - store_artifacts: + path: /tmp/core_dumps + run-consensus-tests: steps: - run: @@ -781,6 +797,19 @@ jobs: - check-dirty-git - post-build + # Run wasm tests on a single container + run-wasm-tests: + executor: build-executor + environment: + <<: *default-build-environment + steps: + - prepare-for-build + - run-wasm-tests + - check-dirty-git + - when: + condition: { equal: [ << pipeline.git.branch >>, master ] } + steps: [ save-sccache-cache ] + workflows: version: 2 # Build and run tests on a single container @@ -829,3 +858,7 @@ workflows: # Run tests on a single container - build-and-test-go: filters: { branches: { ignore: /^deploy\/.*/ } } + + # Run wasm tests on a single container + - run-wasm-tests: + filters: { branches: { ignore: /^deploy\/.*/ } } diff --git a/Cargo.lock b/Cargo.lock index 4e6ef5ca1b..b666c77f6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -726,6 +726,16 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen", +] + [[package]] name = "cookie" version = "0.16.0" @@ -1528,8 +1538,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.10.2+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -2392,7 +2404,6 @@ dependencies = [ "hex_fmt", "mc-common", "mc-crypto-digestible", - "mc-crypto-rand", "mc-sgx-css", "mc-sgx-types", "mc-util-build-script", @@ -2402,6 +2413,7 @@ dependencies = [ "pem", "prost", "rand 0.8.5", + "rand_core 0.6.3", "rand_hc 0.3.1", "rjson", "serde", @@ -5268,6 +5280,21 @@ dependencies = [ "url", ] +[[package]] +name = "mc-wasm-test" +version = "2.0.0" +dependencies = [ + "getrandom 0.2.6", + "mc-account-keys", + "mc-api", + "mc-crypto-keys", + "mc-transaction-core", + "mc-transaction-std", + "rand 0.8.5", + "wasm-bindgen", + "wasm-bindgen-test", +] + [[package]] name = "mc-watcher" version = "2.0.0" @@ -8043,6 +8070,30 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +[[package]] +name = "wasm-bindgen-test" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96f1aa7971fdf61ef0f353602102dbea75a56e225ed036c1e3740564b91e6b7e" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6006f79628dfeb96a86d4db51fbf1344cd7fd8408f06fc9aa3c84913a4789688" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "web-sys" version = "0.3.55" diff --git a/Cargo.toml b/Cargo.toml index 4c176b1d88..cd3db60e66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -151,6 +151,7 @@ members = [ "util/test-helper", "util/test-vector", "util/uri", + "wasm-test", "watcher", "watcher/api", ] diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index 33f1f65eeb..61592600fa 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -24,7 +24,6 @@ std = [ [dependencies] mc-common = { path = "../../common", default-features = false } mc-crypto-digestible = { path = "../../crypto/digestible" } -mc-crypto-rand = { path = "../../crypto/rand" } mc-sgx-css = { path = "../../sgx/css" } mc-sgx-types = { path = "../../sgx/types" } mc-util-encodings = { path = "../../util/encodings" } @@ -36,6 +35,7 @@ digest = "0.10" displaydoc = { version = "0.2", default-features = false } hex_fmt = "0.3" prost = { version = "0.10", default-features = false } +rand_core = { version = "0.6", default-features = false } rjson = "0.3.1" serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } sha2 = { version = "0.10", default-features = false } diff --git a/attest/core/src/nonce.rs b/attest/core/src/nonce.rs index f3eb07db52..303faad8da 100644 --- a/attest/core/src/nonce.rs +++ b/attest/core/src/nonce.rs @@ -13,9 +13,9 @@ use core::{ write, }; use hex_fmt::HexFmt; -use mc_crypto_rand::{CryptoRng, RngCore}; use mc_sgx_types::sgx_quote_nonce_t; use mc_util_encodings::{Error as EncodingError, FromHex, ToHex}; +use rand_core::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use subtle::{Choice, ConstantTimeEq}; diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index 5dce4c2203..310a74b676 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -699,13 +699,13 @@ dependencies = [ "hex_fmt", "mc-common", "mc-crypto-digestible", - "mc-crypto-rand", "mc-sgx-css", "mc-sgx-types", "mc-util-build-script", "mc-util-build-sgx", "mc-util-encodings", "prost", + "rand_core", "rjson", "serde", "sha2", diff --git a/crypto/rand/src/lib.rs b/crypto/rand/src/lib.rs index fc1cc93fcb..294c43d9ef 100644 --- a/crypto/rand/src/lib.rs +++ b/crypto/rand/src/lib.rs @@ -16,6 +16,9 @@ cfg_if! { if #[cfg(target_feature = "rdrand")] { mod rdrandrng; pub use rdrandrng::McRng; + } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] { + mod wasm; + pub use wasm::McRng; } else { mod fallback; pub use fallback::McRng; diff --git a/crypto/rand/src/wasm.rs b/crypto/rand/src/wasm.rs new file mode 100644 index 0000000000..ebfac575cc --- /dev/null +++ b/crypto/rand/src/wasm.rs @@ -0,0 +1,5 @@ +// Copyright (c) 2018-2022 The MobileCoin Foundation + +use rand::rngs::OsRng; + +pub type McRng = OsRng; diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 79b84f0aab..3ff0c4be1a 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -719,13 +719,13 @@ dependencies = [ "hex_fmt", "mc-common", "mc-crypto-digestible", - "mc-crypto-rand", "mc-sgx-css", "mc-sgx-types", "mc-util-build-script", "mc-util-build-sgx", "mc-util-encodings", "prost", + "rand_core", "rjson", "serde", "sha2", diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 8a3e7be53a..43ef170c1f 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -723,13 +723,13 @@ dependencies = [ "hex_fmt", "mc-common", "mc-crypto-digestible", - "mc-crypto-rand", "mc-sgx-css", "mc-sgx-types", "mc-util-build-script", "mc-util-build-sgx", "mc-util-encodings", "prost", + "rand_core", "rjson", "serde", "sha2", diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index d67c31e9d8..30cbe12a28 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -729,13 +729,13 @@ dependencies = [ "hex_fmt", "mc-common", "mc-crypto-digestible", - "mc-crypto-rand", "mc-sgx-css", "mc-sgx-types", "mc-util-build-script", "mc-util-build-sgx", "mc-util-encodings", "prost", + "rand_core", "rjson", "serde", "sha2", diff --git a/util/build/script/src/env.rs b/util/build/script/src/env.rs index 36b500d911..4f66ab47de 100644 --- a/util/build/script/src/env.rs +++ b/util/build/script/src/env.rs @@ -21,6 +21,8 @@ pub enum TargetFamily { Unix, /// The environment is some form of windows Windows, + /// The environment is wasm + Wasm, } /// An enumeration of errors which can occur while parsing the target family @@ -38,6 +40,7 @@ impl TryFrom<&str> for TargetFamily { match src { "unix" => Ok(TargetFamily::Unix), "windows" => Ok(TargetFamily::Windows), + "wasm" => Ok(TargetFamily::Wasm), other => Err(TargetFamilyError::Unknown(other.to_owned())), } } diff --git a/wasm-test/Cargo.toml b/wasm-test/Cargo.toml new file mode 100644 index 0000000000..dfcaec247a --- /dev/null +++ b/wasm-test/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "mc-wasm-test" +version = "2.0.0" +authors = ["MobileCoin"] +edition = "2021" + +[lib] +name = "mc_wasm_test" +crate-type = ["lib", "staticlib", "cdylib"] + +[dependencies] +# These are crates that we want to ensure build successfully for the wasm target +mc-account-keys = { path = "../account-keys" } +mc-api = { path = "../api" } +mc-crypto-keys = { path = "../crypto/keys" } +mc-transaction-core = { path = "../transaction/core" } +mc-transaction-std = { path = "../transaction/std" } + +# These are required since they enable feature flags needed for wasm builds +getrandom = { version = "0.2", features = ["js"] } +rand = { version = "0.8", features = ["getrandom"] } + +# Used for very basic testing +wasm-bindgen = "0.2" +wasm-bindgen-test = "0.3" diff --git a/wasm-test/src/lib.rs b/wasm-test/src/lib.rs new file mode 100644 index 0000000000..3e1784d1e6 --- /dev/null +++ b/wasm-test/src/lib.rs @@ -0,0 +1,20 @@ +// Copyright (c) 2018-2022 The MobileCoin Foundation + +//! Crate used to ensure we can build to the wasm target. + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn add(a: u32, b: u32) -> u32 { + a + b +} + +mod tests { + use super::*; + use wasm_bindgen_test::*; + + #[wasm_bindgen_test] + fn add_works() { + assert_eq!(add(1, 2), 3); + } +} From 9c4ceaf020043d5f2e78b6a4375bd800720267de Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 15 Sep 2022 11:00:44 -0600 Subject: [PATCH 53/77] Pick chain id to release-v2 (#2382) * cherry-pick proof of concept for "chain-id" via grpc headers (#2312) * proof of concept for "network-id" via grpc headers This includes: * Fog view, report, and consensus now take `--network-id` or `MC_NETWORK_ID` * They do not attempt to validate this string at this time * Fog ledger is not done in this commit since it is less essential from the point of view of failing fast during a balance check * These servers search for a `network-id` grpc header and check it against their startup config if it is present. If the client provided value doesn't match then we return a grpc error with a specific message including the server-side network id. * The go-grpc-gateway also pipes this header through now. Plus tests that this works * The thick client and related fog enclave connection objects now take a network id string parameter. If it is non-empty then they set the grpc network id header. * The fog test client now requires `MC_NETWORK_ID` and uses this value in the headers. * CI is updated so that the local network tests set network id everywhere. Not done yet: * Actual tests that network id mismatch on consensus leads to a tx or mint request being rejected * Actual tests that network id mismatch on e.g. fog-report leads to a request being rejected * Update mint client Note: Some reviewers proposed to rename this from "network-id" to "chain-id", we may follow up with that rename in a subsequent commt. * fix go-grpc-gateway testing, and mob tool * rename to chain id per request * add chain id to fog ledger server * cargo fmt * make mint client use chain id, add consensus service tests for chain id * fixups, fix tests, formatting * fix previous * fix previous * fixup consensus tests * add chain-id to mobilecoind * more fix to mobilecoind * Update fog/view/connection/src/lib.rs * cargo fmt * fix build * delete accidentally copied file * disable go-grpc-gateway tests for now * work around lack of ip-info patch in release/v2 circle-ci * add MC_CHAIN_ID to the helm templates This is based on the diff in https://github.com/mobilecoinfoundation/mobilecoin/commit/8203e7cf7e4c275486a3e8676838427d13cd03e0 However, in most places I used the same `valueFrom:` segment as is used for `MC_BRANCH`, because in that diff those things match also. I am not sure if that is correct but it seems like it's worth a shot. Needs review. Thanks. * remove a file we don't want to move from master to here * revert undesired changes to mob that got pulled by cherry-pick * fix automatic dev env delete when feature/release branch is deleted (#2493) * CD - wrong context for namespace variable (#2500) * add MC_CHAIN_ID vars to helm charts * remove code that looks wrong / should not have been picked * fix messed up comments (thanks Eran) Co-authored-by: Jason Greathouse --- .circleci/config.yml | 7 +- .github/workflows/mobilecoin-dev-cd.yaml | 26 ++- .github/workflows/mobilecoin-dev-delete.yaml | 46 +++-- .../mobilecoin-dispatch-dev-delete.yaml | 25 +-- .../mobilecoin-dispatch-dev-reset.yaml | 25 --- .../mobilecoin-workflow-dev-deploy.yaml | 6 +- .../mobilecoin-workflow-dev-reset.yaml | 20 +++ ...ilecoin-workflow-dev-update-consensus.yaml | 4 +- .../templates/gateway-deployment.yaml | 13 +- .../templates/node-deployment.yaml | 5 + .../templates/fog-ingest-statefulset.yaml | 10 +- .../templates/toolbox-deployment.yaml | 5 + .../templates/fog-ledger-statefulset.yaml | 10 +- .../templates/fog-report-deployment.yaml | 10 +- .../templates/fog-view-deployment.yaml | 10 +- .../templates/fog-test-client-deployment.yaml | 5 + .../templates/mobilecoind-deployment.yaml | 5 + .../watcher/templates/watcher-deployment.yaml | 5 + .internal-ci/util/metadata.sh | 6 + Cargo.lock | 1 + connection/src/thick.rs | 14 +- consensus/mint-client/src/bin/main.rs | 50 ++++-- consensus/mint-client/src/config.rs | 16 ++ consensus/service/config/src/lib.rs | 6 + .../service/src/api/attested_api_service.rs | 31 +++- .../service/src/api/client_api_service.rs | 158 +++++++++++++++++- consensus/service/src/consensus_service.rs | 2 + fog/distribution/src/config.rs | 2 + fog/distribution/src/main.rs | 3 +- fog/enclave_connection/src/lib.rs | 15 +- fog/ledger/connection/src/key_image.rs | 15 +- fog/ledger/connection/src/merkle_proof.rs | 5 +- fog/ledger/server/Cargo.toml | 1 + fog/ledger/server/src/block_service.rs | 11 +- fog/ledger/server/src/config.rs | 4 + fog/ledger/server/src/key_image_service.rs | 15 +- fog/ledger/server/src/merkle_proof_service.rs | 33 +++- fog/ledger/server/src/server.rs | 4 + .../server/src/untrusted_tx_out_service.rs | 11 +- fog/ledger/server/tests/connection.rs | 52 +++++- fog/report/cli/src/main.rs | 9 +- fog/report/connection/src/lib.rs | 26 ++- fog/report/server/src/bin/main.rs | 8 +- fog/report/server/src/config.rs | 4 + fog/report/server/src/server.rs | 3 +- fog/report/server/src/service.rs | 15 +- fog/report/server/tests/grpc_apis.rs | 8 +- fog/sample-paykit/proto/remote_wallet.proto | 6 +- fog/sample-paykit/src/bin/balance_check.rs | 5 + .../src/bin/sample_paykit_remote_wallet.rs | 4 + fog/sample-paykit/src/client_builder.rs | 10 +- fog/test-client/src/bin/main.rs | 1 + fog/test-client/src/config.rs | 4 + fog/test-client/src/test_client.rs | 4 + fog/test_infra/src/lib.rs | 37 ++-- fog/view/connection/src/lib.rs | 10 +- fog/view/load-test/src/main.rs | 2 + fog/view/server/src/config.rs | 4 + fog/view/server/src/fog_view_service.rs | 19 ++- fog/view/server/src/server.rs | 1 + fog/view/server/tests/smoke_tests.rs | 10 +- go-grpc-gateway/main.go | 3 + go-grpc-gateway/test.sh | 36 +++- go-grpc-gateway/testing/Cargo.toml | 1 + go-grpc-gateway/testing/src/bin/main.rs | 6 +- go-grpc-gateway/testing/src/config.rs | 4 + go-grpc-gateway/testing/src/server.rs | 4 +- go-grpc-gateway/testing/src/service.rs | 12 +- ledger/sync/src/test_app/main.rs | 2 + mob | 4 + mobilecoind/src/config.rs | 7 +- tools/fog-local-network/local_fog.py | 4 + tools/local-network/local_network.py | 8 +- util/grpc/src/chain_id.rs | 23 +++ util/grpc/src/lib.rs | 2 + watcher/src/verification_reports_collector.rs | 2 + 76 files changed, 824 insertions(+), 176 deletions(-) delete mode 100644 .github/workflows/mobilecoin-dispatch-dev-reset.yaml create mode 100644 util/grpc/src/chain_id.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index 42b97cc85b..3722b17366 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -448,6 +448,7 @@ commands: export INGEST_ENCLAVE_PRIVKEY=$(pwd)/Enclave_private.pem export LEDGER_ENCLAVE_PRIVKEY=$(pwd)/Enclave_private.pem export VIEW_ENCLAVE_PRIVKEY=$(pwd)/Enclave_private.pem + export MC_CHAIN_ID="local" apt-get update && apt-get install -y python3-venv cd tools/fog-local-network @@ -486,6 +487,7 @@ commands: export LEDGER_ENCLAVE_PRIVKEY=$(pwd)/Enclave_private.pem export VIEW_ENCLAVE_PRIVKEY=$(pwd)/Enclave_private.pem export MC_LOG=trace + export MC_CHAIN_ID="local" cargo build -p mc-util-keyfile -p mc-util-generate-sample-ledger -p mc-consensus-service -p mc-ledger-distribution -p mc-admin-http-gateway -p mc-util-grpc-admin-tool -p mc-mobilecoind -p mc-crypto-x509-test-vectors -p mc-fog-distribution -p mc-fog-test-client -p mc-fog-ingest-server -p mc-fog-ingest-client -p mc-fog-view-server -p mc-fog-report-server -p mc-fog-ledger-server -p mc-fog-sql-recovery-db -p mc-consensus-mint-client -p mc-util-seeded-ed25519-key-gen --release export FOG_AUTHORITY_ROOT=$(./target/release/mc-crypto-x509-test-vectors --type=chain --test-name=ok_rsa_head) @@ -856,8 +858,9 @@ workflows: filters: { branches: { ignore: /^deploy\/.*/ } } # Run tests on a single container - - build-and-test-go: - filters: { branches: { ignore: /^deploy\/.*/ } } + # FIXME + # - build-and-test-go: + # filters: { branches: { ignore: /^deploy\/.*/ } } # Run wasm tests on a single container - run-wasm-tests: diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 7948b0e9d6..6fce0d8872 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -378,24 +378,18 @@ jobs: # Reset existing namespace ################################# dev-reset: - runs-on: [self-hosted, Linux, small] needs: - generate-metadata - steps: - - name: Reset development namespace - if: "! contains(github.event.head_commit.message, '[skip dev-reset]')" - uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 - with: - workflow: mobilecoin-dispatch-dev-reset - token: ${{ secrets.ACTIONS_TOKEN }} - wait-for-completion: true - wait-for-completion-timeout: 30m - wait-for-completion-interval: 30s - display-workflow-run-url-interval: 30s - inputs: | - { - "namespace": "${{ needs.generate-metadata.outputs.namespace }}" - } + uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml + with: + namespace: ${{ needs.generate-metadata.outputs.namespace }} + delete_namespace: false + secrets: + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} ####################################### # Deploy previous release to namespace diff --git a/.github/workflows/mobilecoin-dev-delete.yaml b/.github/workflows/mobilecoin-dev-delete.yaml index d309f0fa1b..10ddc4c06d 100644 --- a/.github/workflows/mobilecoin-dev-delete.yaml +++ b/.github/workflows/mobilecoin-dev-delete.yaml @@ -8,28 +8,44 @@ on: delete: {} jobs: - delete: - if: startsWith(github.ref, 'refs/branch/feature/') + metadata: + if: startsWith(github.event.ref, 'feature/') || startsWith(github.event.ref, 'release/') runs-on: [self-hosted, Linux, small] + outputs: + namespace: ${{ steps.meta.outputs.namespace }} + steps: - name: Checkout uses: actions/checkout@v3 - name: Generate version metadata id: meta + env: + # Use the ref name from the payload. The GITHUB_REF_NAME will always be "master" + DELETE_REF_NAME: ${{ github.event.ref }} run: | .internal-ci/util/metadata.sh - - name: Delete branch namespace - uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 - with: - workflow: mobilecoin-dispatch-dev-delete - token: ${{ secrets.ACTIONS_TOKEN }} - wait-for-completion: true - wait-for-completion-timeout: 30m - wait-for-completion-interval: 30s - display-workflow-run-url-interval: 30s - inputs: | - { - "namespace": "${{ steps.meta.outputs.namespace }}" - } + delete: + needs: + - metadata + uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml + with: + namespace: ${{ needs.metadata.outputs.namespace }} + delete_namespace: true + secrets: + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + + why-was-this-skipped: + if: always() && needs.metadata.result == 'skipped' + needs: + - metadata + runs-on: [self-hosted, Linux, small] + steps: + - name: details + run: | + echo "Deleted branch: ${{ github.event.ref }} did not match feature/* or release/*" diff --git a/.github/workflows/mobilecoin-dispatch-dev-delete.yaml b/.github/workflows/mobilecoin-dispatch-dev-delete.yaml index e4041ae21f..a7d655f54b 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-delete.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-delete.yaml @@ -1,6 +1,6 @@ # Copyright (c) 2018-2022 The MobileCoin Foundation # -# MobileCoin Core projects - Dispatch (manual) Job - Delete target dev namespace and all of its components. +# MobileCoin Core projects - Dispatch (manual) Job - Delete target dev env components and optionally the k8s namespace. name: mobilecoin-dispatch-dev-delete @@ -11,30 +11,21 @@ on: description: "Target Namespace" type: string required: true + delete_namespace: + description: "Delete Target Namespace" + type: boolean + required: true + default: true jobs: reset: uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml with: - namespace: ${{ github.event.inputs.namespace }} + namespace: ${{ inputs.namespace }} + delete_namespace: ${{ inputs.delete_namespace }} secrets: RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} RANCHER_URL: ${{ secrets.RANCHER_URL }} RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - - delete: - runs-on: [self-hosted, Linux, small] - needs: - - reset - steps: - - name: Delete namespace - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: namespace-delete - namespace: ${{ github.event.inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} - diff --git a/.github/workflows/mobilecoin-dispatch-dev-reset.yaml b/.github/workflows/mobilecoin-dispatch-dev-reset.yaml deleted file mode 100644 index 0e0c0cfcd6..0000000000 --- a/.github/workflows/mobilecoin-dispatch-dev-reset.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2018-2022 The MobileCoin Foundation -# -# MobileCoin Core projects - Dispatch (manual) Job - Reset/remove all components from a development namespace. - -name: mobilecoin-dispatch-dev-reset - -on: - workflow_dispatch: - inputs: - namespace: - description: "Target Namespace" - type: string - required: true - -jobs: - reset: - uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml - with: - namespace: ${{ github.event.inputs.namespace }} - secrets: - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml index 1ea88adbfc..ec50e112f9 100644 --- a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -18,12 +18,12 @@ on: docker_image_org: description: "Docker Image Org" type: string - required: true + required: false default: docker.io/mobilecoin chart_repo: description: "Chart Repo URL" type: string - required: true + required: false default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public ingest_color: description: "Fog Ingest blue/green" @@ -33,7 +33,7 @@ on: description: "Enable minting config" type: string default: 'false' - required: true + required: false block_version: description: "block_version" type: string diff --git a/.github/workflows/mobilecoin-workflow-dev-reset.yaml b/.github/workflows/mobilecoin-workflow-dev-reset.yaml index ba7ed1e1f5..0de06eed91 100644 --- a/.github/workflows/mobilecoin-workflow-dev-reset.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-reset.yaml @@ -13,6 +13,11 @@ on: description: "Target Namespace" type: string required: true + delete_namespace: + description: "Delete Target Namespace" + type: boolean + default: false + required: false secrets: RANCHER_CLUSTER: description: "Rancher cluster name" @@ -98,3 +103,18 @@ jobs: aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node3.${NAMESPACE}.development.mobilecoin.com aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node4.${NAMESPACE}.development.mobilecoin.com aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node5.${NAMESPACE}.development.mobilecoin.com + + delete-namespace: + if: inputs.delete_namespace + needs: + - reset-storage + runs-on: [self-hosted, Linux, small] + steps: + - name: Delete namespace + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: namespace-delete + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} diff --git a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml index 54d7df45df..530c20a361 100644 --- a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml @@ -18,12 +18,12 @@ on: docker_image_org: description: "Docker Image Org" type: string - required: true + required: false default: docker.io/mobilecoin chart_repo: description: "Chart Repo URL" type: string - required: true + required: false default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public minting_config_enabled: description: "Enable minting config" diff --git a/.internal-ci/helm/consensus-node/templates/gateway-deployment.yaml b/.internal-ci/helm/consensus-node/templates/gateway-deployment.yaml index 351e887739..db8049ae1e 100644 --- a/.internal-ci/helm/consensus-node/templates/gateway-deployment.yaml +++ b/.internal-ci/helm/consensus-node/templates/gateway-deployment.yaml @@ -26,7 +26,7 @@ spec: - name: grpc-gateway image: "{{ .Values.grpcGateway.image.org | default .Values.image.org }}/{{ .Values.grpcGateway.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: IfNotPresent - command: + command: - /usr/bin/go-grpc-gateway - -grpc-server-endpoint={{ include "consensusNode.clientHostname" . }}:443 - -http-server-listen=:8000 @@ -34,3 +34,14 @@ spec: ports: - name: gateway containerPort: 8000 + env: + - name: MC_BRANCH + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network diff --git a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml index 27ffe72598..f2a8d22ea3 100644 --- a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml +++ b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml @@ -123,6 +123,11 @@ spec: configMapKeyRef: name: mobilecoin-network key: network + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network volumeMounts: - name: sealed-signing-key mountPath: /sealed diff --git a/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml b/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml index ba35efc7e1..a82f8ce1e2 100644 --- a/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml +++ b/.internal-ci/helm/fog-ingest/templates/fog-ingest-statefulset.yaml @@ -92,8 +92,14 @@ spec: # Maps to Sentry Environment - name: MC_BRANCH valueFrom: - fieldRef: - fieldPath: metadata.namespace + configMapKeyRef: + name: mobilecoin-network + key: network + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network - name: FOGDB_HOST valueFrom: configMapKeyRef: diff --git a/.internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml b/.internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml index ceca6aa0d3..72583d5f51 100644 --- a/.internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml +++ b/.internal-ci/helm/fog-ingest/templates/toolbox-deployment.yaml @@ -62,6 +62,11 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network - name: RUST_LOG value: error - name: CLIENT_AUTH_TOKEN_SECRET diff --git a/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml b/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml index eeb7f5f5ee..aa7a687e23 100644 --- a/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-ledger-statefulset.yaml @@ -83,8 +83,14 @@ spec: # Maps to Sentry Environment - name: MC_BRANCH valueFrom: - fieldRef: - fieldPath: metadata.namespace + configMapKeyRef: + name: mobilecoin-network + key: network + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network - name: CLIENT_AUTH_TOKEN_SECRET valueFrom: secretKeyRef: diff --git a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml index 8eec153a9c..c41d154422 100644 --- a/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-report-deployment.yaml @@ -71,8 +71,14 @@ spec: # Maps to Sentry Environment - name: MC_BRANCH valueFrom: - fieldRef: - fieldPath: metadata.namespace + configMapKeyRef: + name: mobilecoin-network + key: network + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network - name: FOGDB_HOST valueFrom: configMapKeyRef: diff --git a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml index 875ed06ab6..3ee744a036 100644 --- a/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml +++ b/.internal-ci/helm/fog-services/templates/fog-view-deployment.yaml @@ -91,8 +91,14 @@ spec: # Maps to Sentry Environment - name: MC_BRANCH valueFrom: - fieldRef: - fieldPath: metadata.namespace + configMapKeyRef: + name: mobilecoin-network + key: network + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network - name: FOGDB_HOST valueFrom: configMapKeyRef: diff --git a/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml b/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml index 9bdb3da71d..648eea0b48 100644 --- a/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml +++ b/.internal-ci/helm/fog-test-client/templates/fog-test-client-deployment.yaml @@ -35,6 +35,11 @@ spec: - all readOnlyRootFilesystem: true env: + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network - name: MC_FOG_VIEW valueFrom: configMapKeyRef: diff --git a/.internal-ci/helm/mobilecoind/templates/mobilecoind-deployment.yaml b/.internal-ci/helm/mobilecoind/templates/mobilecoind-deployment.yaml index ca4e5fceae..ac17f08264 100644 --- a/.internal-ci/helm/mobilecoind/templates/mobilecoind-deployment.yaml +++ b/.internal-ci/helm/mobilecoind/templates/mobilecoind-deployment.yaml @@ -73,6 +73,11 @@ spec: value: "full" - name: "RUST_LOG" value: "info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error,rocket=warn,=warn" + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network volumeMounts: - name: data mountPath: /data diff --git a/.internal-ci/helm/watcher/templates/watcher-deployment.yaml b/.internal-ci/helm/watcher/templates/watcher-deployment.yaml index 89bd5b700e..4a99017060 100644 --- a/.internal-ci/helm/watcher/templates/watcher-deployment.yaml +++ b/.internal-ci/helm/watcher/templates/watcher-deployment.yaml @@ -87,6 +87,11 @@ spec: value: "full" - name: "RUST_LOG" value: "info,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,reqwest=warn,rusoto_core=error,rusoto_signature=error,h2=error" + - name: MC_CHAIN_ID + valueFrom: + configMapKeyRef: + name: mobilecoin-network + key: network volumeMounts: - name: watcher-db-dir mountPath: /watcher diff --git a/.internal-ci/util/metadata.sh b/.internal-ci/util/metadata.sh index 624a2dde8b..07cd692064 100755 --- a/.internal-ci/util/metadata.sh +++ b/.internal-ci/util/metadata.sh @@ -35,6 +35,12 @@ namespace_prefix="mc" branch="${GITHUB_REF_NAME}" sha="sha-${GITHUB_SHA:0:8}" +# Override branch with delete ref if set. +if [[ -n "${DELETE_REF_NAME}" ]] +then + branch="${DELETE_REF_NAME}" +fi + case "${GITHUB_REF_TYPE}" in tag) # check for valid tag and set outputs diff --git a/Cargo.lock b/Cargo.lock index b666c77f6e..fde34873e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3556,6 +3556,7 @@ dependencies = [ "mc-common", "mc-crypto-keys", "mc-fog-api", + "mc-fog-enclave-connection", "mc-fog-ledger-connection", "mc-fog-ledger-enclave", "mc-fog-ledger-enclave-api", diff --git a/connection/src/thick.rs b/connection/src/thick.rs index f77777718f..3d8a1e4422 100644 --- a/connection/src/thick.rs +++ b/connection/src/thick.rs @@ -38,7 +38,7 @@ use mc_crypto_keys::X25519; use mc_crypto_noise::CipherError; use mc_crypto_rand::McRng; use mc_transaction_core::{tx::Tx, Block, BlockID, BlockIndex}; -use mc_util_grpc::{ConnectionUriGrpcioChannel, GrpcCookieStore}; +use mc_util_grpc::{ConnectionUriGrpcioChannel, GrpcCookieStore, CHAIN_ID_GRPC_HEADER}; use mc_util_serial::encode; use mc_util_uri::{ConnectionUri, ConsensusClientUri as ClientUri, UriConversionError}; use secrecy::{ExposeSecret, SecretVec}; @@ -122,6 +122,9 @@ impl AttestationError for ThickClientAttestationError { /// A connection from a client to a consensus enclave. pub struct ThickClient { + /// The chain id. This is used with the chain-id grpc header if + /// provided. Ignored if empty string. + chain_id: String, /// The destination's URI uri: ClientUri, /// The logging instance @@ -147,6 +150,7 @@ pub struct ThickClient { impl ThickClient { /// Create a new attested connection to the given consensus node. pub fn new( + chain_id: String, uri: ClientUri, verifier: Verifier, env: Arc, @@ -162,6 +166,7 @@ impl ThickClient { let consensus_client_api_client = ConsensusClientApiClient::new(ch); Ok(Self { + chain_id, uri, logger, blockchain_api_client, @@ -243,6 +248,13 @@ impl ThickClient { } } + // Add the chain id header if we have a chain id specified + if !self.chain_id.is_empty() { + metadata_builder + .add_str(CHAIN_ID_GRPC_HEADER, &self.chain_id) + .expect("Error setting chain-id header"); + } + Ok(CallOption::default().headers(metadata_builder.build())) } diff --git a/consensus/mint-client/src/bin/main.rs b/consensus/mint-client/src/bin/main.rs index b08ce9be30..235991a409 100644 --- a/consensus/mint-client/src/bin/main.rs +++ b/consensus/mint-client/src/bin/main.rs @@ -3,7 +3,7 @@ //! Entrypoint for the consensus mint client. use clap::Parser; -use grpcio::{ChannelBuilder, EnvBuilder}; +use grpcio::{CallOption, ChannelBuilder, EnvBuilder, MetadataBuilder}; use mc_common::logger::{create_app_logger, o}; use mc_consensus_api::{ consensus_client_grpc::ConsensusClientApiClient, consensus_common_grpc::BlockchainApiClient, @@ -17,16 +17,34 @@ use mc_transaction_core::{ constants::MAX_TOMBSTONE_BLOCKS, mint::{MintConfigTx, MintTx}, }; -use mc_util_grpc::ConnectionUriGrpcioChannel; +use mc_util_grpc::{ConnectionUriGrpcioChannel, CHAIN_ID_GRPC_HEADER}; use protobuf::ProtobufEnum; use std::{fs, process::exit, sync::Arc}; +// Make a "call option" object which includes appropriate grpc headers +fn call_option(chain_id: &str) -> CallOption { + let mut metadata_builder = MetadataBuilder::new(); + + // Add the chain id header if we have a chain id specified + if !chain_id.is_empty() { + metadata_builder + .add_str(CHAIN_ID_GRPC_HEADER, chain_id) + .expect("Could not add chain-id header"); + } + + CallOption::default().headers(metadata_builder.build()) +} + fn main() { let (logger, _global_logger_guard) = create_app_logger(o!()); let config = Config::parse(); match config.command { - Commands::GenerateAndSubmitMintConfigTx { node, params } => { + Commands::GenerateAndSubmitMintConfigTx { + node, + params, + chain_id, + } => { let env = Arc::new(EnvBuilder::new().name_prefix("mint-client-grpc").build()); let ch = ChannelBuilder::default_channel_builder(env).connect_to_uri(&node, &logger); let client_api = ConsensusClientApiClient::new(ch.clone()); @@ -46,7 +64,7 @@ fn main() { } let resp = client_api - .propose_mint_config_tx(&(&tx).into()) + .propose_mint_config_tx_opt(&(&tx).into(), call_option(&chain_id)) .expect("propose tx"); println!("response: {:?}", resp); @@ -79,7 +97,11 @@ fn main() { println!("Hash: {}", hex::encode(hash)); } - Commands::SubmitMintConfigTx { node, tx_filenames } => { + Commands::SubmitMintConfigTx { + node, + tx_filenames, + chain_id, + } => { // Load all txs. let txs = TxFile::load_multiple::(&tx_filenames).expect("failed loading txs"); @@ -111,7 +133,7 @@ fn main() { let client_api = ConsensusClientApiClient::new(ch); let resp = client_api - .propose_mint_config_tx(&(&merged_tx).into()) + .propose_mint_config_tx_opt(&(&merged_tx).into(), call_option(&chain_id)) .expect("propose tx"); println!("response: {:?}", resp); @@ -121,7 +143,11 @@ fn main() { exit(resp.get_result().get_code().value()); } - Commands::GenerateAndSubmitMintTx { node, params } => { + Commands::GenerateAndSubmitMintTx { + node, + params, + chain_id, + } => { let env = Arc::new(EnvBuilder::new().name_prefix("mint-client-grpc").build()); let ch = ChannelBuilder::default_channel_builder(env).connect_to_uri(&node, &logger); let client_api = ConsensusClientApiClient::new(ch.clone()); @@ -141,7 +167,7 @@ fn main() { } let resp = client_api - .propose_mint_tx(&(&tx).into()) + .propose_mint_tx_opt(&(&tx).into(), call_option(&chain_id)) .expect("propose tx"); println!("response: {:?}", resp); @@ -174,7 +200,11 @@ fn main() { println!("Hash: {}", hex::encode(hash)); } - Commands::SubmitMintTx { node, tx_filenames } => { + Commands::SubmitMintTx { + node, + tx_filenames, + chain_id, + } => { // Load all txs. let txs = TxFile::load_multiple::(&tx_filenames).expect("failed loading txs"); @@ -205,7 +235,7 @@ fn main() { let client_api = ConsensusClientApiClient::new(ch); let resp = client_api - .propose_mint_tx(&(&merged_tx).into()) + .propose_mint_tx_opt(&(&merged_tx).into(), call_option(&chain_id)) .expect("propose tx"); println!("response: {:?}", resp); diff --git a/consensus/mint-client/src/config.rs b/consensus/mint-client/src/config.rs index 5afc0511ea..53772d8506 100644 --- a/consensus/mint-client/src/config.rs +++ b/consensus/mint-client/src/config.rs @@ -231,6 +231,10 @@ pub enum Commands { /// Generate and submit a MintConfigTx transaction. #[clap(arg_required_else_help = true)] GenerateAndSubmitMintConfigTx { + /// The chain id of the network we expect to connect to + #[clap(long, env = "MC_CHAIN_ID")] + chain_id: String, + /// URI of consensus node to connect to. #[clap(long, env = "MC_CONSENSUS_URI")] node: ConsensusClientUri, @@ -259,6 +263,10 @@ pub enum Commands { /// Submit json-encoded MintConfigTx(s). If multiple transactions are /// provided, signatures will be merged. SubmitMintConfigTx { + /// The chain id of the network we expect to connect to + #[clap(long, env = "MC_CHAIN_ID")] + chain_id: String, + /// URI of consensus node to connect to. #[clap(long, env = "MC_CONSENSUS_URI")] node: ConsensusClientUri, @@ -277,6 +285,10 @@ pub enum Commands { /// Generate and submit a MintTx transaction. #[clap(arg_required_else_help = true)] GenerateAndSubmitMintTx { + /// The chain id of the network we expect to connect to + #[clap(long, env = "MC_CHAIN_ID")] + chain_id: String, + /// URI of consensus node to connect to. #[clap(long, env = "MC_CONSENSUS_URI")] node: ConsensusClientUri, @@ -305,6 +317,10 @@ pub enum Commands { /// Submit json-encoded MintTx(s). If multiple transactions are provided, /// signatures will be merged. SubmitMintTx { + /// The chain id of the network we expect to connect to + #[clap(long, env = "MC_CHAIN_ID")] + chain_id: String, + /// URI of consensus node to connect to. #[clap(long, env = "MC_CONSENSUS_URI")] node: ConsensusClientUri, diff --git a/consensus/service/config/src/lib.rs b/consensus/service/config/src/lib.rs index 7158098531..40d2aae45c 100644 --- a/consensus/service/config/src/lib.rs +++ b/consensus/service/config/src/lib.rs @@ -26,6 +26,10 @@ use std::{fmt::Debug, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; version )] pub struct Config { + /// The chain id of the network we are a part of + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// Peer Responder ID /// /// This ID needs to match the host:port remote peers use when connecting to @@ -180,6 +184,7 @@ mod tests { #[test] fn test_local_uris_with_pubkey() { let config = Config { + chain_id: "local".to_string(), peer_responder_id: ResponderId::from_str("localhost:8081").unwrap(), client_responder_id: ResponderId::from_str("localhost:3223").unwrap(), msg_signer_key: keypair_from_base64( @@ -248,6 +253,7 @@ mod tests { #[test] fn test_deployed_uris_with_pubkey() { let config = Config { + chain_id: "local".to_string(), peer_responder_id: ResponderId::from_str("peer1.NETWORKNAME.mobilecoin.com:443").unwrap(), client_responder_id: ResponderId::from_str("node1.NETWORKNAME.mobilecoin.com:443").unwrap(), msg_signer_key: keypair_from_base64( diff --git a/consensus/service/src/api/attested_api_service.rs b/consensus/service/src/api/attested_api_service.rs index c0d3fff414..6afcbf117b 100644 --- a/consensus/service/src/api/attested_api_service.rs +++ b/consensus/service/src/api/attested_api_service.rs @@ -10,12 +10,15 @@ use mc_common::{ HashSet, }; use mc_consensus_enclave::ConsensusEnclave; -use mc_util_grpc::{rpc_logger, rpc_permissions_error, send_result, Authenticator}; +use mc_util_grpc::{ + check_request_chain_id, rpc_logger, rpc_permissions_error, send_result, Authenticator, +}; use mc_util_metrics::SVC_COUNTERS; use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct AttestedApiService { + chain_id: String, enclave: Arc, authenticator: Arc, logger: Logger, @@ -24,11 +27,13 @@ pub struct AttestedApiService { impl AttestedApiService { pub fn new( + chain_id: String, enclave: Arc, authenticator: Arc, logger: Logger, ) -> Self { Self { + chain_id, enclave, authenticator, logger, @@ -41,6 +46,10 @@ impl AttestedApi for AttestedApiService { fn auth(&mut self, ctx: RpcContext, request: AuthMessage, sink: UnarySink) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } @@ -84,6 +93,10 @@ impl AttestedApi for AttestedApiService { fn auth(&mut self, ctx: RpcContext, request: AuthMessage, sink: UnarySink) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } @@ -170,8 +183,12 @@ mod peer_tests { )); let enclave = Arc::new(MockConsensusEnclave::new()); - let attested_api_service = - AttestedApiService::::new(enclave, authenticator, logger); + let attested_api_service = AttestedApiService::::new( + "local".to_string(), + enclave, + authenticator, + logger, + ); let (client, _server) = get_client_server(attested_api_service); @@ -238,8 +255,12 @@ mod client_tests { )); let enclave = Arc::new(MockConsensusEnclave::new()); - let attested_api_service = - AttestedApiService::::new(enclave, authenticator, logger); + let attested_api_service = AttestedApiService::::new( + "local".to_string(), + enclave, + authenticator, + logger, + ); let (client, _server) = get_client_server(attested_api_service); diff --git a/consensus/service/src/api/client_api_service.rs b/consensus/service/src/api/client_api_service.rs index ee404034db..ff9c9902c1 100644 --- a/consensus/service/src/api/client_api_service.rs +++ b/consensus/service/src/api/client_api_service.rs @@ -24,7 +24,7 @@ use mc_consensus_service_config::Config; use mc_ledger_db::Ledger; use mc_peers::ConsensusValue; use mc_transaction_core::mint::{MintConfigTx, MintTx}; -use mc_util_grpc::{rpc_logger, send_result, Authenticator}; +use mc_util_grpc::{check_request_chain_id, rpc_logger, send_result, Authenticator}; use mc_util_metrics::{self, SVC_COUNTERS}; use std::{convert::TryFrom, sync::Arc}; @@ -209,6 +209,10 @@ impl ConsensusClientApi for ClientApiService { ) { let _timer = SVC_COUNTERS.req(&ctx); + if let Err(err) = check_request_chain_id(&self.config.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), &self.logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), &self.logger); } @@ -253,6 +257,10 @@ impl ConsensusClientApi for ClientApiService { ) { let _timer = SVC_COUNTERS.req(&ctx); + if let Err(err) = check_request_chain_id(&self.config.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), &self.logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), &self.logger); } @@ -287,6 +295,10 @@ impl ConsensusClientApi for ClientApiService { ) { let _timer = SVC_COUNTERS.req(&ctx); + if let Err(err) = check_request_chain_id(&self.config.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), &self.logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), &self.logger); } @@ -337,7 +349,8 @@ mod client_api_tests { }; use clap::Parser; use grpcio::{ - ChannelBuilder, Environment, Error as GrpcError, RpcStatusCode, Server, ServerBuilder, + CallOption, ChannelBuilder, Environment, Error as GrpcError, MetadataBuilder, + RpcStatusCode, Server, ServerBuilder, }; use mc_attest_api::attest::Message; use mc_common::{ @@ -361,7 +374,9 @@ mod client_api_tests { }; use mc_transaction_core_test_utils::{create_mint_config_tx, create_mint_tx}; use mc_util_from_random::FromRandom; - use mc_util_grpc::{AnonymousAuthenticator, TokenAuthenticator}; + use mc_util_grpc::{ + AnonymousAuthenticator, TokenAuthenticator, CHAIN_ID_GRPC_HEADER, CHAIN_ID_MISMATCH_ERR_MSG, + }; use rand_core::SeedableRng; use rand_hc::Hc128Rng; use serial_test::serial; @@ -390,6 +405,7 @@ mod client_api_tests { fn get_config() -> Config { Config::try_parse_from(&[ "foo", + "--chain-id=local", "--peer-responder-id=localhost:8081", "--client-responder-id=localhost:3223", "--msg-signer-key=MC4CAQAwBQYDK2VwBCIEIC50QXQll2Y9qxztvmsUgcBBIxkmk7EQjxzQTa926bKo", @@ -405,6 +421,20 @@ mod client_api_tests { .unwrap() } + // Make a "call option" object which includes appropriate grpc headers + fn call_option(chain_id: &str) -> CallOption { + let mut metadata_builder = MetadataBuilder::new(); + + // Add the chain id header if we have a chain id specified + if !chain_id.is_empty() { + metadata_builder + .add_str(CHAIN_ID_GRPC_HEADER, chain_id) + .expect("Could not add chain-id header"); + } + + CallOption::default().headers(metadata_builder.build()) + } + // A note about `#[serial(counters)]`: some of the tests here rely on // manipulating and observing the value of the global prometheus counters. // Since the client API calls that are being tested also manipulate them, the @@ -479,6 +509,128 @@ mod client_api_tests { } } + #[test_with_logger] + #[serial(counters)] + fn test_client_tx_propose_ok_with_chain_id(logger: Logger) { + let mut consensus_enclave = MockConsensusEnclave::new(); + { + // Return a TxContext that contains some KeyImages. + let tx_context = TxContext { + key_images: vec![KeyImage::default(), KeyImage::default()], + ..Default::default() + }; + + consensus_enclave + .expect_client_tx_propose() + .times(1) + .return_const(Ok(tx_context)); + } + + // Arc, Option<&ResponderId>) + Sync + Send> + let scp_client_value_sender = Arc::new( + |_value: ConsensusValue, + _node_id: Option<&NodeID>, + _responder_id: Option<&ResponderId>| { + // TODO: store inputs for inspection. + }, + ); + + let num_blocks = 5; + let mut ledger = MockLedger::new(); + // The service should request num_blocks. + ledger + .expect_num_blocks() + .times(1) + .return_const(Ok(num_blocks)); + + let mut tx_manager = MockTxManager::new(); + tx_manager + .expect_insert() + .times(1) + .return_const(Ok(TxHash::default())); + tx_manager.expect_validate().times(1).return_const(Ok(())); + + let is_serving_fn = Arc::new(|| -> bool { true }); + + let authenticator = AnonymousAuthenticator::default(); + + let instance = ClientApiService::new( + get_config(), + Arc::new(consensus_enclave), + scp_client_value_sender, + Arc::new(ledger), + Arc::new(tx_manager), + Arc::new(MockMintTxManager::new()), + is_serving_fn, + Arc::new(authenticator), + logger, + ); + + // gRPC client and server. + let (client, _server) = get_client_server(instance); + let message = Message::default(); + + // Try with chain id header + match client.client_tx_propose_opt(&message, call_option("local")) { + Ok(propose_tx_response) => { + assert_eq!(propose_tx_response.get_result(), ProposeTxResult::Ok); + assert_eq!(propose_tx_response.get_block_count(), num_blocks); + } + Err(e) => panic!("Unexpected error: {:?}", e), + } + } + + #[test_with_logger] + #[serial(counters)] + fn test_client_tx_propose_ok_wrong_chain_id(logger: Logger) { + let consensus_enclave = MockConsensusEnclave::new(); + + // Arc, Option<&ResponderId>) + Sync + Send> + let scp_client_value_sender = Arc::new( + |_value: ConsensusValue, + _node_id: Option<&NodeID>, + _responder_id: Option<&ResponderId>| { + // TODO: store inputs for inspection. + }, + ); + + let ledger = MockLedger::new(); + + let tx_manager = MockTxManager::new(); + + let is_serving_fn = Arc::new(|| -> bool { true }); + + let authenticator = AnonymousAuthenticator::default(); + + let instance = ClientApiService::new( + get_config(), + Arc::new(consensus_enclave), + scp_client_value_sender, + Arc::new(ledger), + Arc::new(tx_manager), + Arc::new(MockMintTxManager::new()), + is_serving_fn, + Arc::new(authenticator), + logger, + ); + + // gRPC client and server. + let (client, _server) = get_client_server(instance); + let message = Message::default(); + + // Try with wrong chain id header + match client.client_tx_propose_opt(&message, call_option("wrong")) { + Err(grpcio::Error::RpcFailure(status)) => { + let expected = format!("{} '{}'", CHAIN_ID_MISMATCH_ERR_MSG, "local"); + assert_eq!(status.message(), expected); + } + Ok(_) => { + panic!("Got success, but failure was expected"); + } + Err(e) => panic!("Unexpected error: {:?}", e), + } + } + #[test_with_logger] #[serial(counters)] // Should return ProposeTxResult::ContainsSpentKeyImage if the tx contains a diff --git a/consensus/service/src/consensus_service.rs b/consensus/service/src/consensus_service.rs index 3d15b3f471..023f0e2132 100644 --- a/consensus/service/src/consensus_service.rs +++ b/consensus/service/src/consensus_service.rs @@ -348,6 +348,7 @@ impl< )); let attested_service = create_attested_api(AttestedApiService::::new( + self.config.chain_id.clone(), enclave, self.client_authenticator.clone(), self.logger.clone(), @@ -469,6 +470,7 @@ impl< )); let attested_service = create_attested_api(AttestedApiService::::new( + self.config.chain_id.clone(), enclave, peer_authenticator, self.logger.clone(), diff --git a/fog/distribution/src/config.rs b/fog/distribution/src/config.rs index 20505e1379..6e12244ebb 100644 --- a/fog/distribution/src/config.rs +++ b/fog/distribution/src/config.rs @@ -118,6 +118,8 @@ impl Config { ); let logger = logger.new(o!("mc.cxn" => uri.addr())); ThickClient::new( + // TODO: Supply a chain-id to fog distribution? + String::default(), uri.clone(), verifier.clone(), env, diff --git a/fog/distribution/src/main.rs b/fog/distribution/src/main.rs index 13b06558a4..f13c5c3925 100755 --- a/fog/distribution/src/main.rs +++ b/fog/distribution/src/main.rs @@ -451,7 +451,8 @@ fn build_fog_resolver( // XXX: This retry should possibly be in the GrpcFogPubkeyResolver object itself // instead 15'th fibonacci is 987, so the last delay should be ~100 // seconds - let conn = GrpcFogReportConnection::new(env.clone(), logger.clone()); + // TODO: Supply a chain id to fog-distribution? + let conn = GrpcFogReportConnection::new(String::default(), env.clone(), logger.clone()); let responses = retry( delay::Fibonacci::from_millis(100) .map(delay::jitter) diff --git a/fog/enclave_connection/src/lib.rs b/fog/enclave_connection/src/lib.rs index 537779851b..862961fa03 100644 --- a/fog/enclave_connection/src/lib.rs +++ b/fog/enclave_connection/src/lib.rs @@ -19,7 +19,7 @@ use mc_common::{ use mc_connection::{AttestedConnection, Connection}; use mc_crypto_keys::X25519; use mc_crypto_rand::McRng; -use mc_util_grpc::{BasicCredentials, GrpcCookieStore}; +use mc_util_grpc::{BasicCredentials, GrpcCookieStore, CHAIN_ID_GRPC_HEADER}; use mc_util_uri::ConnectionUri; use retry::OperationResult; use sha2::Sha512; @@ -51,6 +51,8 @@ pub trait EnclaveGrpcChannel: Send + Sync { /// A generic object representing an attested connection to a remote enclave pub struct EnclaveConnection { + /// Chain id, ignored if empty + chain_id: String, /// The URI we are connecting to, and which provides the ResponderId uri: U, /// Abstraction of one or more grpc connections @@ -137,11 +139,12 @@ impl AttestedConnection for EnclaveConn } impl EnclaveConnection { - pub fn new(uri: U, grpc: G, verifier: Verifier, logger: Logger) -> Self { + pub fn new(chain_id: String, uri: U, grpc: G, verifier: Verifier, logger: Logger) -> Self { let creds = BasicCredentials::new(&uri.username(), &uri.password()); let cookies = CookieJar::default(); Self { + chain_id, uri, grpc, attest_cipher: None, @@ -167,6 +170,14 @@ impl EnclaveConnection { .add_str("Authorization", &self.creds.authorization_header()) .expect("Error setting authorization header"); } + + // Add the chain id header if we have a chain id specified + if !self.chain_id.is_empty() { + metadata_builder + .add_str(CHAIN_ID_GRPC_HEADER, &self.chain_id) + .expect("Could not add chain-id header"); + } + retval.headers(metadata_builder.build()) } diff --git a/fog/ledger/connection/src/key_image.rs b/fog/ledger/connection/src/key_image.rs index 5527c6e216..1b0f08d0c8 100644 --- a/fog/ledger/connection/src/key_image.rs +++ b/fog/ledger/connection/src/key_image.rs @@ -26,12 +26,15 @@ impl FogKeyImageGrpcClient { /// Create a new client object /// /// Arguments: - /// uri: The uri to connect to - /// grpc_retry_config: The retry policy to use when connecting - /// verifier: The attestation verifier - /// env: The grpc environment (thread pool) to use for this connection - /// logger: for logging + /// * chain_id: The id of the network we expect to talk to. Ignored if + /// empty. + /// * uri: The uri to connect to + /// * grpc_retry_config: The retry policy to use when connecting + /// * verifier: The attestation verifier + /// * env: The grpc environment (thread pool) to use for this connection + /// * logger: for logging pub fn new( + chain_id: String, uri: FogLedgerUri, grpc_retry_config: GrpcRetryConfig, verifier: Verifier, @@ -45,7 +48,7 @@ impl FogKeyImageGrpcClient { let grpc_client = FogKeyImageApiClient::new(ch); Self { - conn: EnclaveConnection::new(uri.clone(), grpc_client, verifier, logger), + conn: EnclaveConnection::new(chain_id, uri.clone(), grpc_client, verifier, logger), grpc_retry_config, uri, } diff --git a/fog/ledger/connection/src/merkle_proof.rs b/fog/ledger/connection/src/merkle_proof.rs index 9b4885ac4c..66ea994e78 100644 --- a/fog/ledger/connection/src/merkle_proof.rs +++ b/fog/ledger/connection/src/merkle_proof.rs @@ -27,12 +27,15 @@ impl FogMerkleProofGrpcClient { /// Create a new client object /// /// Arguments: + /// * chain_id: The id of the network we expect to talk to. Ignored if + /// empty. /// * uri: The uri to connect to /// * grpc_retry_config: The retry policy to use for connection errors /// * verifier: The attestation verifier /// * env: The grpc environment to use (thread pool) /// * logger: for logging pub fn new( + chain_id: String, uri: FogLedgerUri, grpc_retry_config: GrpcRetryConfig, verifier: Verifier, @@ -46,7 +49,7 @@ impl FogMerkleProofGrpcClient { let grpc_client = FogMerkleProofApiClient::new(ch); Self { - conn: EnclaveConnection::new(uri.clone(), grpc_client, verifier, logger), + conn: EnclaveConnection::new(chain_id, uri.clone(), grpc_client, verifier, logger), grpc_retry_config, uri, } diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index 64a388ba31..cc189df9c3 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -38,6 +38,7 @@ mc-watcher-api = { path = "../../../watcher/api" } # fog mc-fog-api = { path = "../../api" } +mc-fog-enclave-connection = { path = "../../enclave_connection" } mc-fog-ledger-enclave = { path = "../enclave" } mc-fog-ledger-enclave-api = { path = "../enclave/api" } mc-fog-types = { path = "../../types" } diff --git a/fog/ledger/server/src/block_service.rs b/fog/ledger/server/src/block_service.rs index 35e351fdde..0cb5d059b5 100644 --- a/fog/ledger/server/src/block_service.rs +++ b/fog/ledger/server/src/block_service.rs @@ -8,7 +8,9 @@ use mc_fog_api::{ ledger_grpc::FogBlockApi, }; use mc_ledger_db::{self, Error as DbError, Ledger}; -use mc_util_grpc::{rpc_database_err, rpc_logger, send_result, Authenticator}; +use mc_util_grpc::{ + check_request_chain_id, rpc_database_err, rpc_logger, send_result, Authenticator, +}; use mc_util_metrics::SVC_COUNTERS; use mc_watcher::watcher_db::WatcherDB; use mc_watcher_api::TimestampResultCode; @@ -16,6 +18,7 @@ use std::sync::Arc; #[derive(Clone)] pub struct BlockService { + chain_id: String, ledger: L, watcher: WatcherDB, authenticator: Arc, @@ -24,12 +27,14 @@ pub struct BlockService { impl BlockService { pub fn new( + chain_id: String, ledger: L, watcher: WatcherDB, authenticator: Arc, logger: Logger, ) -> Self { Self { + chain_id, ledger, watcher, authenticator, @@ -107,6 +112,10 @@ impl FogBlockApi for BlockService { ) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } diff --git a/fog/ledger/server/src/config.rs b/fog/ledger/server/src/config.rs index e5f1dc8504..16eda23323 100644 --- a/fog/ledger/server/src/config.rs +++ b/fog/ledger/server/src/config.rs @@ -17,6 +17,10 @@ use std::{path::PathBuf, time::Duration}; #[derive(Clone, Parser, Serialize)] #[clap(version)] pub struct LedgerServerConfig { + /// The chain id of the network we are a part of + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// gRPC listening URI for client requests. #[clap(long, env = "MC_CLIENT_LISTEN_URI")] pub client_listen_uri: FogLedgerUri, diff --git a/fog/ledger/server/src/key_image_service.rs b/fog/ledger/server/src/key_image_service.rs index d16e95ebca..0670444aeb 100644 --- a/fog/ledger/server/src/key_image_service.rs +++ b/fog/ledger/server/src/key_image_service.rs @@ -11,8 +11,8 @@ use mc_fog_ledger_enclave::LedgerEnclaveProxy; use mc_fog_ledger_enclave_api::{Error as EnclaveError, UntrustedKeyImageQueryResponse}; use mc_ledger_db::{self, Ledger}; use mc_util_grpc::{ - rpc_internal_error, rpc_invalid_arg_error, rpc_logger, rpc_permissions_error, send_result, - Authenticator, + check_request_chain_id, rpc_internal_error, rpc_invalid_arg_error, rpc_logger, + rpc_permissions_error, send_result, Authenticator, }; use mc_util_metrics::SVC_COUNTERS; use mc_watcher::watcher_db::WatcherDB; @@ -20,6 +20,7 @@ use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct KeyImageService { + chain_id: String, ledger: L, watcher: WatcherDB, enclave: E, @@ -31,6 +32,7 @@ pub struct KeyImageService { impl KeyImageService { pub fn new( + chain_id: String, ledger: L, watcher: WatcherDB, enclave: E, @@ -39,6 +41,7 @@ impl KeyImageService { logger: Logger, ) -> Self { Self { + chain_id, ledger, watcher, enclave, @@ -124,6 +127,10 @@ impl FogKeyImageApi for KeyImageServic fn check_key_images(&mut self, ctx: RpcContext, request: Message, sink: UnarySink) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } @@ -135,6 +142,10 @@ impl FogKeyImageApi for KeyImageServic fn auth(&mut self, ctx: RpcContext, request: AuthMessage, sink: UnarySink) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } diff --git a/fog/ledger/server/src/merkle_proof_service.rs b/fog/ledger/server/src/merkle_proof_service.rs index bb114fa4a1..191d5b4bfd 100644 --- a/fog/ledger/server/src/merkle_proof_service.rs +++ b/fog/ledger/server/src/merkle_proof_service.rs @@ -10,8 +10,8 @@ use mc_fog_ledger_enclave_api::Error as EnclaveError; use mc_ledger_db::{self, Error as DbError, Ledger}; use mc_transaction_core::tx::{TxOut, TxOutMembershipProof}; use mc_util_grpc::{ - rpc_database_err, rpc_internal_error, rpc_invalid_arg_error, rpc_logger, rpc_permissions_error, - send_result, Authenticator, + check_request_chain_id, rpc_database_err, rpc_internal_error, rpc_invalid_arg_error, + rpc_logger, rpc_permissions_error, send_result, Authenticator, }; use mc_util_metrics::SVC_COUNTERS; use std::{convert::From, sync::Arc}; @@ -21,6 +21,7 @@ pub const MAX_REQUEST_SIZE: usize = 2000; #[derive(Clone)] pub struct MerkleProofService { + chain_id: String, ledger: L, enclave: E, authenticator: Arc, @@ -29,12 +30,14 @@ pub struct MerkleProofService { impl MerkleProofService { pub fn new( + chain_id: String, ledger: L, enclave: E, authenticator: Arc, logger: Logger, ) -> Self { Self { + chain_id, ledger, enclave, authenticator, @@ -167,6 +170,10 @@ impl FogMerkleProofApi for MerkleProof fn get_outputs(&mut self, ctx: RpcContext, request: Message, sink: UnarySink) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } @@ -178,6 +185,10 @@ impl FogMerkleProofApi for MerkleProof fn auth(&mut self, ctx: RpcContext, request: AuthMessage, sink: UnarySink) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } @@ -302,8 +313,13 @@ mod test { let enclave = MockEnclave::default(); let authenticator = Arc::new(AnonymousAuthenticator::default()); - let mut ledger_server_node = - MerkleProofService::new(mock_ledger.clone(), enclave, authenticator, logger.clone()); + let mut ledger_server_node = MerkleProofService::new( + "local".to_string(), + mock_ledger.clone(), + enclave, + authenticator, + logger.clone(), + ); let request = OutputContext { indexes: (0..50).collect(), @@ -356,8 +372,13 @@ mod test { let enclave = MockEnclave::default(); let authenticator = Arc::new(AnonymousAuthenticator::default()); - let mut ledger_server_node = - MerkleProofService::new(mock_ledger, enclave, authenticator, logger.clone()); + let mut ledger_server_node = MerkleProofService::new( + "local".to_string(), + mock_ledger, + enclave, + authenticator, + logger.clone(), + ); let request = OutputContext { indexes: (0..50).collect(), diff --git a/fog/ledger/server/src/server.rs b/fog/ledger/server/src/server.rs index 392a46c876..29908ebd42 100644 --- a/fog/ledger/server/src/server.rs +++ b/fog/ledger/server/src/server.rs @@ -103,6 +103,7 @@ impl LedgerServer LedgerServer { + chain_id: String, ledger: L, watcher: WatcherDB, authenticator: Arc, @@ -26,12 +29,14 @@ pub struct UntrustedTxOutService { impl UntrustedTxOutService { pub fn new( + chain_id: String, ledger: L, watcher: WatcherDB, authenticator: Arc, logger: Logger, ) -> Self { Self { + chain_id, ledger, watcher, authenticator, @@ -156,6 +161,10 @@ impl FogUntrustedTxOutApi for UntrustedTxOutService { ) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } diff --git a/fog/ledger/server/tests/connection.rs b/fog/ledger/server/tests/connection.rs index 53c601e275..e73d0bbf4c 100644 --- a/fog/ledger/server/tests/connection.rs +++ b/fog/ledger/server/tests/connection.rs @@ -15,7 +15,7 @@ use mc_common::{ use mc_crypto_keys::{CompressedRistrettoPublic, Ed25519Pair, RistrettoPrivate}; use mc_fog_api::ledger::TxOutResultCode; use mc_fog_ledger_connection::{ - FogKeyImageGrpcClient, FogMerkleProofGrpcClient, FogUntrustedLedgerGrpcClient, + Error, FogKeyImageGrpcClient, FogMerkleProofGrpcClient, FogUntrustedLedgerGrpcClient, KeyImageResultExtension, OutputResultExtension, }; use mc_fog_ledger_enclave::LedgerSgxEnclave; @@ -28,7 +28,7 @@ use mc_transaction_core::{ BlockVersion, Token, }; use mc_util_from_random::FromRandom; -use mc_util_grpc::GrpcRetryConfig; +use mc_util_grpc::{GrpcRetryConfig, CHAIN_ID_MISMATCH_ERR_MSG}; use mc_util_test_helper::{CryptoRng, RngCore, RngType, SeedableRng}; use mc_watcher::watcher_db::WatcherDB; use std::{ @@ -119,6 +119,7 @@ fn fog_ledger_merkle_proofs_test(logger: Logger) { )) .unwrap(); let config = LedgerServerConfig { + chain_id: "local".to_string(), ledger_db: db_full_path.to_path_buf(), watcher_db: watcher_dir, admin_listen_uri: Default::default(), @@ -168,10 +169,11 @@ fn fog_ledger_merkle_proofs_test(logger: Logger) { verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); let mut client = FogMerkleProofGrpcClient::new( - client_uri, + "local".to_string(), + client_uri.clone(), GRPC_RETRY_CONFIG, - verifier, - grpc_env, + verifier.clone(), + grpc_env.clone(), logger.clone(), ); @@ -220,6 +222,42 @@ fn fog_ledger_merkle_proofs_test(logger: Logger) { assert!(response.results[1].status().as_ref().unwrap().is_some()); assert!(response.results[2].status().as_ref().unwrap().is_none()); assert!(response.results[3].status().as_ref().unwrap().is_none()); + + // Check that wrong chain id results in an error + let mut client = FogMerkleProofGrpcClient::new( + "wrong".to_string(), + client_uri, + GRPC_RETRY_CONFIG, + verifier, + grpc_env, + logger.clone(), + ); + + let result = client.get_outputs( + vec![0u64, 1u64, 2u64, 3u64, 4u64, 5u64, 6u64, 7u64, 8u64], + num_blocks - 1, + ); + + if let Err(err) = result { + match err { + Error::Connection( + _, + retry::Error::Operation { + error: + mc_fog_enclave_connection::Error::Rpc(grpcio::Error::RpcFailure(status)), + .. + }, + ) => { + let expected = format!("{} '{}'", CHAIN_ID_MISMATCH_ERR_MSG, "local"); + assert_eq!(status.message(), expected); + } + _ => { + panic!("unexpected grpcio error: {}", err); + } + } + } else { + panic!("Expected an error when chain-id is wrong"); + } } // grpcio detaches all its threads and does not join them :( @@ -313,6 +351,7 @@ fn fog_ledger_key_images_test(logger: Logger) { )) .unwrap(); let config = LedgerServerConfig { + chain_id: "local".to_string(), ledger_db: db_full_path.to_path_buf(), watcher_db: watcher_dir, admin_listen_uri: Default::default(), @@ -362,6 +401,7 @@ fn fog_ledger_key_images_test(logger: Logger) { verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); let mut client = FogKeyImageGrpcClient::new( + String::default(), client_uri, GRPC_RETRY_CONFIG, verifier, @@ -512,6 +552,7 @@ fn fog_ledger_blocks_api_test(logger: Logger) { )) .unwrap(); let config = LedgerServerConfig { + chain_id: "local".to_string(), ledger_db: db_full_path.to_path_buf(), watcher_db: watcher_dir, admin_listen_uri: Default::default(), @@ -673,6 +714,7 @@ fn fog_ledger_untrusted_tx_out_api_test(logger: Logger) { )) .unwrap(); let config = LedgerServerConfig { + chain_id: "local".to_string(), ledger_db: db_full_path.to_path_buf(), watcher_db: watcher_dir, admin_listen_uri: Default::default(), diff --git a/fog/report/cli/src/main.rs b/fog/report/cli/src/main.rs index 6d66d97c47..8bb9bb12bc 100644 --- a/fog/report/cli/src/main.rs +++ b/fog/report/cli/src/main.rs @@ -54,6 +54,10 @@ use std::{ #[derive(Debug, clap::Parser)] #[clap(version)] struct Config { + /// The chain id of the network we expect to interact with + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// Path to mobilecoin public address. Fog url and spki will be extracted, /// and fog signature will be checked, unless no-validate is passed. #[clap(long, short, env = "MC_PUBLIC_ADDRESS")] @@ -94,6 +98,7 @@ struct Config { /// Get fog response with retries, retrying if NoReports error occurs fn get_fog_response_with_retries( + chain_id: &str, fog_uri: FogUri, retry_duration: Duration, logger: &Logger, @@ -101,7 +106,7 @@ fn get_fog_response_with_retries( // Create the grpc object and report verifier let grpc_env = Arc::new(EnvBuilder::new().name_prefix("cli").build()); - let conn = GrpcFogReportConnection::new(grpc_env, logger.clone()); + let conn = GrpcFogReportConnection::new(chain_id.to_owned(), grpc_env, logger.clone()); let deadline = Instant::now() + retry_duration; loop { @@ -234,6 +239,7 @@ fn main() { // Try to make request let responses = get_fog_response_with_retries( + &config.chain_id, fog_uri.clone(), Duration::from_secs(config.retry_seconds), &logger, @@ -261,6 +267,7 @@ fn main() { // Try to make request let responses = get_fog_response_with_retries( + &config.chain_id, fog_uri, Duration::from_secs(config.retry_seconds), &logger, diff --git a/fog/report/connection/src/lib.rs b/fog/report/connection/src/lib.rs index 2fee2e87be..f4583e80b6 100644 --- a/fog/report/connection/src/lib.rs +++ b/fog/report/connection/src/lib.rs @@ -7,11 +7,11 @@ //! with fog recipients. use displaydoc::Display; -use grpcio::{ChannelBuilder, Environment}; +use grpcio::{CallOption, ChannelBuilder, Environment, MetadataBuilder}; use mc_common::logger::{log, o, Logger}; use mc_fog_report_api::{report::ReportRequest, report_grpc}; use mc_fog_report_types::ReportResponse; -use mc_util_grpc::ConnectionUriGrpcioChannel; +use mc_util_grpc::{ConnectionUriGrpcioChannel, CHAIN_ID_GRPC_HEADER}; use mc_util_uri::FogUri; use std::sync::Arc; @@ -24,6 +24,8 @@ pub use mc_fog_report_types::FogReportResponses; /// establishing new connections each time. #[derive(Clone)] pub struct GrpcFogReportConnection { + /// chain id, ignored if empty + chain_id: String, /// grpc environment env: Arc, /// The logging instance @@ -32,8 +34,12 @@ pub struct GrpcFogReportConnection { impl GrpcFogReportConnection { /// Create a new GrpcFogReportConnection object - pub fn new(env: Arc, logger: Logger) -> Self { - Self { env, logger } + pub fn new(chain_id: String, env: Arc, logger: Logger) -> Self { + Self { + chain_id, + env, + logger, + } } /// Fetch fog reports corresponding to a series of FogUris, returning @@ -79,8 +85,18 @@ impl GrpcFogReportConnection { let report_grpc_client = report_grpc::ReportApiClient::new(ch); // Request reports + let mut metadata_builder = MetadataBuilder::new(); + if !self.chain_id.is_empty() { + metadata_builder + .add_str(CHAIN_ID_GRPC_HEADER, &self.chain_id) + .expect("Could not add chain-id header"); + } + let req = ReportRequest::new(); - let resp = report_grpc_client.get_reports(&req)?; + let resp = report_grpc_client.get_reports_opt( + &req, + CallOption::default().headers(metadata_builder.build()), + )?; if resp.reports.len() == 0 { log::warn!( diff --git a/fog/report/server/src/bin/main.rs b/fog/report/server/src/bin/main.rs index 900e6ba950..644bea0156 100644 --- a/fog/report/server/src/bin/main.rs +++ b/fog/report/server/src/bin/main.rs @@ -27,7 +27,13 @@ fn main() { ) .expect("Failed connecting to database"); - let mut server = Server::new(db, &config.client_listen_uri, materials, logger.clone()); + let mut server = Server::new( + db, + config.chain_id.clone(), + &config.client_listen_uri, + materials, + logger.clone(), + ); server.start(); let config2 = config.clone(); diff --git a/fog/report/server/src/config.rs b/fog/report/server/src/config.rs index b43e68ece8..fa48f5503e 100644 --- a/fog/report/server/src/config.rs +++ b/fog/report/server/src/config.rs @@ -22,6 +22,10 @@ use x509_signature::X509Certificate; version )] pub struct Config { + /// The chain id of the network we are a part of + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// gRPC listening URI for client requests. #[clap(long, env = "MC_CLIENT_LISTEN_URI")] pub client_listen_uri: FogUri, diff --git a/fog/report/server/src/server.rs b/fog/report/server/src/server.rs index 8500de8838..4f5324cf04 100644 --- a/fog/report/server/src/server.rs +++ b/fog/report/server/src/server.rs @@ -22,6 +22,7 @@ impl Server { /// Construct a new server object. pub fn new( db: impl ReportDb + Clone + Send + Sync + 'static, + chain_id: String, client_listen_uri: &FogUri, materials: Materials, logger: Logger, @@ -33,7 +34,7 @@ impl Server { ); let report_service = - report_grpc::create_report_api(Service::new(db, materials, logger.clone())); + report_grpc::create_report_api(Service::new(chain_id, db, materials, logger.clone())); log::debug!(logger, "Constructed Report GRPC Service"); // Health check service diff --git a/fog/report/server/src/service.rs b/fog/report/server/src/service.rs index bdff721f98..e612ef5eec 100644 --- a/fog/report/server/src/service.rs +++ b/fog/report/server/src/service.rs @@ -13,7 +13,9 @@ use mc_fog_api::{ use mc_fog_recovery_db_iface::{RecoveryDbError, ReportDb}; use mc_fog_report_types::{Report, ReportResponse}; use mc_fog_sig_report::Signer as ReportSigner; -use mc_util_grpc::{rpc_database_err, rpc_internal_error, rpc_logger, send_result}; +use mc_util_grpc::{ + check_request_chain_id, rpc_database_err, rpc_internal_error, rpc_logger, send_result, +}; use mc_util_metrics::SVC_COUNTERS; use prost::DecodeError; use signature::{Error as SignatureError, Signature}; @@ -27,6 +29,10 @@ pub struct Service { /// Cryptographic materials used in response construction materials: Materials, + /// Chain id to check against the user-provided chain id (if present in + /// request) + chain_id: String, + /// Slog logger object logger: Logger, } @@ -69,8 +75,9 @@ impl Error { impl Service { /// Creates a new report service node (but does not create sockets and start /// it etc.) - pub fn new(report_db: R, materials: Materials, logger: Logger) -> Self { + pub fn new(chain_id: String, report_db: R, materials: Materials, logger: Logger) -> Self { Self { + chain_id, report_db, materials, logger, @@ -120,6 +127,10 @@ impl ReportApi for Service { ) { let _timer = SVC_COUNTERS.req(&ctx); logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + // Build a prost response, then convert it to rpc/protobuf types and the errors // to rpc status codes. send_result( diff --git a/fog/report/server/tests/grpc_apis.rs b/fog/report/server/tests/grpc_apis.rs index 1c35f73e50..7bd3d7b4b1 100644 --- a/fog/report/server/tests/grpc_apis.rs +++ b/fog/report/server/tests/grpc_apis.rs @@ -31,7 +31,13 @@ fn report_server_grpc_tests(logger: Logger) { .expect("Could not parse x509 test vectors key"); let client_uri = FogUri::from_str("insecure-fog://0.0.0.0:3400").unwrap(); - let mut server = Server::new(db, &client_uri, materials, logger.clone()); + let mut server = Server::new( + db, + "local".to_string(), + &client_uri, + materials, + logger.clone(), + ); server.start(); let env = Arc::new(grpcio::EnvBuilder::new().build()); diff --git a/fog/sample-paykit/proto/remote_wallet.proto b/fog/sample-paykit/proto/remote_wallet.proto index 2eb3abeccf..f1bc0bd132 100644 --- a/fog/sample-paykit/proto/remote_wallet.proto +++ b/fog/sample-paykit/proto/remote_wallet.proto @@ -34,11 +34,15 @@ service RemoteWalletApi { message FreshBalanceCheckRequest { /// Mnemonic key for the account the new client will be using. string mnemonic = 1; - /// FOG URI (should have view and ledger servers accessible). + + /// Fog URI (should have view and ledger servers accessible). string fog_uri = 2; /// Account Index for the account the new client will be using. uint32 account_index = 3; + + /// Chain id + string chain_id = 4; } message BalanceCheckResponse { diff --git a/fog/sample-paykit/src/bin/balance_check.rs b/fog/sample-paykit/src/bin/balance_check.rs index 42de58af9e..4839af8091 100644 --- a/fog/sample-paykit/src/bin/balance_check.rs +++ b/fog/sample-paykit/src/bin/balance_check.rs @@ -28,6 +28,10 @@ use std::{ #[derive(Debug, Parser)] struct Config { + /// The chain id of the network we expect to interact with + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// Path to root identity file to use /// Note: This contains the fog-url which is the same as the report-server /// uri @@ -58,6 +62,7 @@ fn main() { .expect("Could not create dummy consensus client uri"); let mut sample_paykit = ClientBuilder::new( + config.chain_id.clone(), consensus_client_uri, config.view_uri.clone(), config.ledger_uri, diff --git a/fog/sample-paykit/src/bin/sample_paykit_remote_wallet.rs b/fog/sample-paykit/src/bin/sample_paykit_remote_wallet.rs index ccf2fd21be..0ee5c7e061 100644 --- a/fog/sample-paykit/src/bin/sample_paykit_remote_wallet.rs +++ b/fog/sample-paykit/src/bin/sample_paykit_remote_wallet.rs @@ -123,8 +123,12 @@ impl RemoteWalletService { )); }; + // Get chain id if any. (Empty string is ignored and this is proto default) + let chain_id = request.get_chain_id(); + // Create client and perform balance check. let mut client = ClientBuilder::new( + chain_id.to_owned(), consensus_client_uri, fog_view_uri, fog_ledger_uri, diff --git a/fog/sample-paykit/src/client_builder.rs b/fog/sample-paykit/src/client_builder.rs index cf531c23ff..545d431a3e 100644 --- a/fog/sample-paykit/src/client_builder.rs +++ b/fog/sample-paykit/src/client_builder.rs @@ -24,6 +24,7 @@ use std::sync::Arc; /// Builder object which helps to initialize the sample paykit pub struct ClientBuilder { // Required + chain_id: String, uri: ConsensusClientUri, key: AccountKey, logger: Logger, @@ -51,6 +52,7 @@ pub struct ClientBuilder { impl ClientBuilder { /// Create a new client builder object pub fn new( + chain_id: String, uri: ConsensusClientUri, fog_view_address: FogViewUri, ledger_server_address: FogLedgerUri, @@ -58,6 +60,7 @@ impl ClientBuilder { logger: Logger, ) -> Self { Self { + chain_id, uri, key, logger, @@ -149,6 +152,7 @@ impl ClientBuilder { ); let consensus_service_conn = ThickClient::new( + self.chain_id.clone(), self.uri.clone(), verifier, grpc_env.clone(), @@ -165,7 +169,8 @@ impl ClientBuilder { fog_ingest_verifier ); - let fog_report_conn = GrpcFogReportConnection::new(grpc_env, self.logger.clone()); + let fog_report_conn = + GrpcFogReportConnection::new(self.chain_id.clone(), grpc_env, self.logger.clone()); Client::new( consensus_service_conn, @@ -191,6 +196,7 @@ impl ClientBuilder { log::debug!(self.logger, "Fog view attestation verifier: {:?}", verifier); FogViewGrpcClient::new( + self.chain_id.clone(), self.fog_view_address.clone(), self.grpc_retry_config, verifier, @@ -219,6 +225,7 @@ impl ClientBuilder { ( FogMerkleProofGrpcClient::new( + self.chain_id.clone(), self.ledger_server_address.clone(), self.grpc_retry_config, verifier.clone(), @@ -226,6 +233,7 @@ impl ClientBuilder { self.logger.clone(), ), FogKeyImageGrpcClient::new( + self.chain_id.clone(), self.ledger_server_address.clone(), self.grpc_retry_config, verifier, diff --git a/fog/test-client/src/bin/main.rs b/fog/test-client/src/bin/main.rs index 2d1ac42482..cee4f088c1 100644 --- a/fog/test-client/src/bin/main.rs +++ b/fog/test-client/src/bin/main.rs @@ -75,6 +75,7 @@ fn main() { let test_client = TestClient::new( policy, account_keys, + config.chain_id, config.consensus_config.consensus_validators, config.fog_ledger, config.fog_view, diff --git a/fog/test-client/src/config.rs b/fog/test-client/src/config.rs index ebd241bd03..b598b0592e 100644 --- a/fog/test-client/src/config.rs +++ b/fog/test-client/src/config.rs @@ -23,6 +23,10 @@ use std::{path::PathBuf, time::Duration}; version )] pub struct TestClientConfig { + /// The chain id of the network we expect to interact with + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// A URI to host the prometheus data at. /// /// Prometheus data includes number of successes and failure, and histograms diff --git a/fog/test-client/src/test_client.rs b/fog/test-client/src/test_client.rs index 55c62031cc..ea33dd6245 100644 --- a/fog/test-client/src/test_client.rs +++ b/fog/test-client/src/test_client.rs @@ -109,6 +109,7 @@ pub struct TestClient { policy: TestClientPolicy, grpc_retry_config: GrpcRetryConfig, account_keys: Vec, + chain_id: String, consensus_uris: Vec, fog_ledger: FogLedgerUri, fog_view: FogViewUri, @@ -136,6 +137,7 @@ impl TestClient { pub fn new( policy: TestClientPolicy, account_keys: Vec, + chain_id: String, consensus_uris: Vec, fog_ledger: FogLedgerUri, fog_view: FogViewUri, @@ -154,6 +156,7 @@ impl TestClient { policy, grpc_retry_config, account_keys, + chain_id, consensus_uris, fog_ledger, fog_view, @@ -221,6 +224,7 @@ impl TestClient { ); let uri = &self.consensus_uris[i % self.consensus_uris.len()]; let client = ClientBuilder::new( + self.chain_id.clone(), uri.clone(), self.fog_view.clone(), self.fog_ledger.clone(), diff --git a/fog/test_infra/src/lib.rs b/fog/test_infra/src/lib.rs index 0fe6ded960..813a2a8664 100644 --- a/fog/test_infra/src/lib.rs +++ b/fog/test_infra/src/lib.rs @@ -29,28 +29,35 @@ use std::{convert::TryFrom, env, path::PathBuf}; /// sense for our infrastructure. pub fn get_enclave_path(filename: &str) -> PathBuf { // First try searching right next to the target, this is for circle-ci - let maybe_result = env::current_exe() - .expect("Could not get current exe") - .with_file_name(filename); + let current_exe = env::current_exe().expect("Could not get current exe"); + let maybe_result = current_exe.with_file_name(filename); // Try statting the file if std::fs::metadata(maybe_result.clone()).is_ok() { return maybe_result; } - // During cargo test, the enclave.so won't be there, so we search in target - // instead as a fallback - let project_root = { - let mut result = env::current_exe().expect("Could not get current exe"); - while result.file_name().expect("No Filename for result") != "target" { - result = result.parent().expect("No parent for result").to_path_buf(); + // When building in the container, CARGO_TARGET_DIR is set to e.g. + // `/target/docker/debug`, and we should respect this. Otherwise, we can + // attempt to find it, assuming that current exe + let target_dir = match env::var("CARGO_TARGET_DIR") { + Ok(target_dir) => PathBuf::from(target_dir), + Err(_) => { + let mut result = current_exe; + while result + .file_name() + .expect("No Filename for result, could not find target directory") + != "target" + { + result = result + .parent() + .expect("No parent for result, could not find target directory") + .to_path_buf(); + } + result } - result - .parent() - .expect("Now no parent for result") - .to_path_buf() }; - project_root - .join("target") + + target_dir .join(mc_util_build_info::profile()) .join(filename) } diff --git a/fog/view/connection/src/lib.rs b/fog/view/connection/src/lib.rs index 17bf721f1e..eae30212b0 100644 --- a/fog/view/connection/src/lib.rs +++ b/fog/view/connection/src/lib.rs @@ -37,12 +37,14 @@ impl FogViewGrpcClient { /// Create a new fog view grpc client /// /// Arguments: + /// * chain-id: The id of the network we expect to connect to, if available /// * uri: The Uri to connect to /// * grpc_retry_config: Retry policy to use for connection issues /// * verifier: The attestation verifier /// * env: A grpc environment (thread pool) to use for this connection /// * logger: For logging pub fn new( + chain_id: String, uri: FogViewUri, grpc_retry_config: GrpcRetryConfig, verifier: Verifier, @@ -56,7 +58,13 @@ impl FogViewGrpcClient { let grpc_client = view_grpc::FogViewApiClient::new(ch); Self { - conn: EnclaveConnection::new(uri.clone(), grpc_client, verifier, logger.clone()), + conn: EnclaveConnection::new( + chain_id, + uri.clone(), + grpc_client, + verifier, + logger.clone(), + ), grpc_retry_config, uri, logger, diff --git a/fog/view/load-test/src/main.rs b/fog/view/load-test/src/main.rs index 6ad6612384..96d4facb69 100644 --- a/fog/view/load-test/src/main.rs +++ b/fog/view/load-test/src/main.rs @@ -140,7 +140,9 @@ fn build_fog_view_conn( let client_uri = FogViewUri::from_str(uri) .unwrap_or_else(|e| panic!("Could not parse client uri: {}: {:?}", uri, e)); + // TODO: Supply network-id to the load-test binary? FogViewGrpcClient::new( + String::default(), client_uri, grpc_retry_config, verifier, diff --git a/fog/view/server/src/config.rs b/fog/view/server/src/config.rs index 9f9f8ba24d..2b2579d847 100644 --- a/fog/view/server/src/config.rs +++ b/fog/view/server/src/config.rs @@ -17,6 +17,10 @@ use std::time::Duration; #[derive(Clone, Parser, Serialize)] #[clap(version)] pub struct MobileAcctViewConfig { + /// The chain id of the network we are a part of + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// The ID with which to respond to client attestation requests. /// /// This ID needs to match the host:port clients use in their URI when diff --git a/fog/view/server/src/fog_view_service.rs b/fog/view/server/src/fog_view_service.rs index 685bc2d45a..e216bd3765 100644 --- a/fog/view/server/src/fog_view_service.rs +++ b/fog/view/server/src/fog_view_service.rs @@ -1,6 +1,6 @@ // Copyright (c) 2018-2022 The MobileCoin Foundation -use crate::server::DbPollSharedState; +use crate::{config::MobileAcctViewConfig, server::DbPollSharedState}; use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink}; use mc_attest_api::attest; use mc_common::logger::{log, Logger}; @@ -10,8 +10,8 @@ use mc_fog_types::view::QueryRequestAAD; use mc_fog_view_enclave::{Error as ViewEnclaveError, ViewEnclaveProxy}; use mc_fog_view_enclave_api::UntrustedQueryResponse; use mc_util_grpc::{ - rpc_internal_error, rpc_invalid_arg_error, rpc_logger, rpc_permissions_error, send_result, - Authenticator, + check_request_chain_id, rpc_internal_error, rpc_invalid_arg_error, rpc_logger, + rpc_permissions_error, send_result, Authenticator, }; use mc_util_metrics::SVC_COUNTERS; use mc_util_telemetry::{tracer, Tracer}; @@ -19,6 +19,9 @@ use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct FogViewService { + /// Server Config + config: MobileAcctViewConfig, + /// Enclave providing access to the Recovery DB enclave: E, @@ -39,6 +42,7 @@ impl FogViewService { /// Creates a new fog-view-service node (but does not create sockets and /// start it etc.) pub fn new( + config: MobileAcctViewConfig, enclave: E, db: Arc, db_poll_shared_state: Arc>, @@ -46,6 +50,7 @@ impl FogViewService { logger: Logger, ) -> Self { Self { + config, enclave, db, db_poll_shared_state, @@ -139,6 +144,10 @@ impl FogViewApi for FogViewSe ) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.config.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } @@ -181,6 +190,10 @@ impl FogViewApi for FogViewSe ) { let _timer = SVC_COUNTERS.req(&ctx); mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.config.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { return send_result(ctx, sink, err.into(), logger); } diff --git a/fog/view/server/src/server.rs b/fog/view/server/src/server.rs index 0c658c5558..7a02758abe 100644 --- a/fog/view/server/src/server.rs +++ b/fog/view/server/src/server.rs @@ -95,6 +95,7 @@ where }; let fog_view_service = view_grpc::create_fog_view_api(FogViewService::new( + config.clone(), enclave.clone(), Arc::new(recovery_db), db_poll_thread.get_shared_state(), diff --git a/fog/view/server/tests/smoke_tests.rs b/fog/view/server/tests/smoke_tests.rs index 8b32dc2043..caca9c453c 100644 --- a/fog/view/server/tests/smoke_tests.rs +++ b/fog/view/server/tests/smoke_tests.rs @@ -67,6 +67,7 @@ fn get_test_environment( let server = { let config = ViewConfig { + chain_id: "local".to_string(), client_responder_id: ResponderId::from_str(&uri.addr()).unwrap(), client_listen_uri: uri.clone(), client_auth_token_secret: None, @@ -110,7 +111,14 @@ fn get_test_environment( let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); - FogViewGrpcClient::new(uri, GRPC_RETRY_CONFIG, verifier, grpcio_env, logger) + FogViewGrpcClient::new( + "local".to_string(), + uri, + GRPC_RETRY_CONFIG, + verifier, + grpcio_env, + logger, + ) }; (db_test_context, server, client) diff --git a/go-grpc-gateway/main.go b/go-grpc-gateway/main.go index 68d4adc677..f6f8bf156a 100644 --- a/go-grpc-gateway/main.go +++ b/go-grpc-gateway/main.go @@ -27,6 +27,9 @@ func headerMatcher(header string) (string, bool) { if header == "Cookie" { return "cookie", true } + if header == "Chain-Id" { + return "chain-id", true + } return runtime.DefaultHeaderMatcher(header) } diff --git a/go-grpc-gateway/test.sh b/go-grpc-gateway/test.sh index cc0b919977..4017f370b8 100755 --- a/go-grpc-gateway/test.sh +++ b/go-grpc-gateway/test.sh @@ -11,7 +11,9 @@ if [ ! -f "grpc-proxy" ]; then exit 1 fi -if [ ! -f "../target/debug/stub" ]; then +: "${CARGO_TARGET_DIR:=/tmp/mobilenode/target/}" + +if [ ! -f "$CARGO_TARGET_DIR/debug/stub" ]; then echo "Missing rust testing stub, needs cargo build" exit 1 fi @@ -26,7 +28,7 @@ trap my_exit EXIT INT HUP TERM set -x # Spawn rust stub server -./../target/debug/stub --client-listen-uri insecure-fog://localhost:3000 & +"$CARGO_TARGET_DIR/debug/stub" --chain-id "local" --client-listen-uri insecure-fog://localhost:3000 & pid=$! sleep 1 @@ -61,5 +63,35 @@ if [ "$result" != "$expected" ]; then exit 1 fi +# Test if Chain-Id is being properly passed on +result=$(curl -XPOST -H "Content-Type: application/x-protobuf" -H "Chain-Id: local" http://localhost:8080/report.ReportAPI/GetReports -d "") +expected=$(echo -e "\\032\\004\\001\\001") +if [ "$result" != "$expected" ]; then + set +x + echo "Unexpected result for ReportAPI/GetReports with Chain-Id: local" + echo "$result" + echo "Expected:" + echo "$expected" + exit 1 +fi + +# Test the same as above (with chain id header) and check that we get a 200 status response +result=$(curl -o /dev/null -w "%{http_code}" -XPOST -H "Content-Type: application/x-protobuf" -H "Chain-Id: local" http://localhost:8080/report.ReportAPI/GetReports -d "") +expected="200" +if [ "$result" != "$expected" ]; then + echo "Bad status with Chain-Id: local" + echo "$result" + exit 1 +fi + +# Test if an error is being propagated when Chain-Id is wrong +result=$(curl -o /dev/null -w "%{http_code}" -XPOST -H "Content-Type: application/x-protobuf" -H "Chain-Id: wrong" http://localhost:8080/report.ReportAPI/GetReports -d "") +expected="400" +if [ "$result" != "$expected" ]; then + echo "Passed, but we expected failure for ReportAPI/GetReports with Chain-Id: wrong" + echo "$result" + exit 1 +fi + set +x echo "Success!" diff --git a/go-grpc-gateway/testing/Cargo.toml b/go-grpc-gateway/testing/Cargo.toml index 2303ec70d7..6e2b324bba 100644 --- a/go-grpc-gateway/testing/Cargo.toml +++ b/go-grpc-gateway/testing/Cargo.toml @@ -4,6 +4,7 @@ version = "1.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" +default-run = "stub" [lib] name = "fog_stub_server" diff --git a/go-grpc-gateway/testing/src/bin/main.rs b/go-grpc-gateway/testing/src/bin/main.rs index 3b2b57d496..9eb5850475 100644 --- a/go-grpc-gateway/testing/src/bin/main.rs +++ b/go-grpc-gateway/testing/src/bin/main.rs @@ -14,7 +14,11 @@ fn main() { let config = Config::parse(); - let mut server = Server::new(&config.client_listen_uri, logger.clone()); + let mut server = Server::new( + &config.client_listen_uri, + config.chain_id.clone(), + logger.clone(), + ); server.start(); loop { diff --git a/go-grpc-gateway/testing/src/config.rs b/go-grpc-gateway/testing/src/config.rs index 96413a6282..24beb71bf2 100644 --- a/go-grpc-gateway/testing/src/config.rs +++ b/go-grpc-gateway/testing/src/config.rs @@ -8,6 +8,10 @@ use serde::Serialize; #[derive(Clone, Debug, Parser, Serialize)] #[clap(name = "stub-server", about = "Stub which implements fog grpc apis.")] pub struct Config { + /// The chain id of the network we are a part of + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// gRPC listening URI for client requests. #[clap(long, env = "MC_CLIENT_LISTEN_URI")] pub client_listen_uri: FogUri, diff --git a/go-grpc-gateway/testing/src/server.rs b/go-grpc-gateway/testing/src/server.rs index 0d089600e6..1f0245da07 100644 --- a/go-grpc-gateway/testing/src/server.rs +++ b/go-grpc-gateway/testing/src/server.rs @@ -15,14 +15,14 @@ pub struct Server { impl Server { /// Instantiate a server, ready to listen at the given URI - pub fn new(client_listen_uri: &FogUri, logger: Logger) -> Self { + pub fn new(client_listen_uri: &FogUri, chain_id: String, logger: Logger) -> Self { let env = Arc::new( grpcio::EnvBuilder::new() .name_prefix("StubServer-RPC".to_string()) .build(), ); - let service = Service::new(logger.clone()); + let service = Service::new(chain_id, logger.clone()); let report_service = report_grpc::create_report_api(service); log::debug!(logger, "Constructed Report GRPC Service"); diff --git a/go-grpc-gateway/testing/src/service.rs b/go-grpc-gateway/testing/src/service.rs index ce6368ebcb..738cdc7784 100644 --- a/go-grpc-gateway/testing/src/service.rs +++ b/go-grpc-gateway/testing/src/service.rs @@ -5,18 +5,20 @@ use mc_fog_report_api::{ report_grpc::ReportApi, }; use mc_fog_report_types::ReportResponse; -use mc_util_grpc::{rpc_logger, send_result}; +use mc_util_grpc::{check_request_chain_id, rpc_logger, send_result}; use mc_util_metrics::SVC_COUNTERS; #[derive(Clone)] pub struct Service { + /// Network id stirng + chain_id: String, /// Slog logger object logger: Logger, } impl Service { - pub fn new(logger: Logger) -> Self { - Self { logger } + pub fn new(chain_id: String, logger: Logger) -> Self { + Self { chain_id, logger } } fn build_report_response(&self) -> Result { @@ -38,6 +40,10 @@ impl ReportApi for Service { ) { let _timer = SVC_COUNTERS.req(&ctx); logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = check_request_chain_id(&self.chain_id, &ctx) { + return send_result(ctx, sink, Err(err), logger); + } + // Build a prost response, then convert it to rpc/protobuf types send_result( ctx, diff --git a/ledger/sync/src/test_app/main.rs b/ledger/sync/src/test_app/main.rs index b3ffbae81a..606ff119e3 100644 --- a/ledger/sync/src/test_app/main.rs +++ b/ledger/sync/src/test_app/main.rs @@ -113,6 +113,8 @@ fn main() { .expect("failed parsing URI"); ThickClient::new( + // TODO: Supply a chain-id here? + String::default(), node_uri.clone(), verifier.clone(), grpc_env.clone(), diff --git a/mob b/mob index 018f32e096..16b57cfd9f 100755 --- a/mob +++ b/mob @@ -293,6 +293,10 @@ docker_run = ["docker", "run", # container doesn't know mount_point so we have to set this "--env", "CARGO_HOME=" + mount_point + "/cargo", + # This is required to run the fog unit tests + "--env", "TEST_DATABASE_URL=postgres://localhost", + # This is consumed by servers when running locally in the container + "--env", "MC_CHAIN_ID=local", "--volume", mount_from + ":" + mount_point, "--workdir", workdir] diff --git a/mobilecoind/src/config.rs b/mobilecoind/src/config.rs index a0f6605e41..693a48f31b 100644 --- a/mobilecoind/src/config.rs +++ b/mobilecoind/src/config.rs @@ -200,7 +200,7 @@ impl Config { .build(), ); - let conn = GrpcFogReportConnection::new(env, logger); + let conn = GrpcFogReportConnection::new(self.peers_config.chain_id.to_owned(), env, logger); let verifier = self.get_fog_ingest_verifier(); @@ -282,6 +282,10 @@ impl Config { /// Wrapper for configuring and parsing peer URIs. #[derive(Clone, Debug, Parser)] pub struct PeersConfig { + /// The chain id of the network we expect to interact with + #[clap(long, env = "MC_CHAIN_ID")] + pub chain_id: String, + /// Validator nodes to connect to. /// Sample usages: /// --peer mc://foo:123 --peer mc://bar:456 @@ -324,6 +328,7 @@ impl PeersConfig { .iter() .map(|client_uri| { ThickClient::new( + self.chain_id.to_owned(), client_uri.clone(), verifier.clone(), grpc_env.clone(), diff --git a/tools/fog-local-network/local_fog.py b/tools/fog-local-network/local_fog.py index ebbce58a03..fab8eb6103 100644 --- a/tools/fog-local-network/local_fog.py +++ b/tools/fog-local-network/local_fog.py @@ -32,6 +32,10 @@ FOG_SQL_DATABASE_NAME = 'fog_local' +# Set a sane chain id if none is provided +if 'MC_CHAIN_ID' not in os.environ: + os.environ['MC_CHAIN_ID'] = 'local' + def target_dir(release): return os.path.join(PROJECT_DIR, 'target', 'release' if release else 'debug') diff --git a/tools/local-network/local_network.py b/tools/local-network/local_network.py index 00465c802b..2da978d5ce 100755 --- a/tools/local-network/local_network.py +++ b/tools/local-network/local_network.py @@ -43,6 +43,10 @@ if 'MC_LOG' not in os.environ: os.environ['MC_LOG'] = 'debug,rustls=warn,hyper=warn,tokio_reactor=warn,mio=warn,want=warn,rusoto_core=error,h2=error,reqwest=error,rocket=error,=error' +# Set a sane chain id if none is provided +if 'MC_CHAIN_ID' not in os.environ: + os.environ['MC_CHAIN_ID'] = 'local' + # Cloud logging-sepcific configuration LOG_BRANCH = os.getenv('LOG_BRANCH', None) LOGSTASH_HOST = os.getenv('LOGSTASH_HOST', None) @@ -461,7 +465,9 @@ def build_binaries(self): ) subprocess.run( - f'cd {PROJECT_DIR} && CONSENSUS_ENCLAVE_PRIVKEY="{enclave_pem}" cargo build -p mc-consensus-service -p mc-ledger-distribution -p mc-admin-http-gateway -p mc-util-grpc-admin-tool -p mc-mint-auditor -p mc-mobilecoind -p mc-crypto-x509-test-vectors -p mc-consensus-mint-client -p mc-util-seeded-ed25519-key-gen {CARGO_FLAGS}', + f'cd {PROJECT_DIR} && CONSENSUS_ENCLAVE_PRIVKEY="{enclave_pem}" cargo build -p mc-consensus-service -p mc-ledger-distribution -p mc-admin-http-gateway -p mc-util-grpc-admin-tool -p mc-mint-auditor -p mc-crypto-x509-test-vectors -p mc-consensus-mint-client -p mc-util-seeded-ed25519-key-gen {CARGO_FLAGS}', + f'cd {PROJECT_DIR} && CONSENSUS_ENCLAVE_PRIVKEY="{enclave_pem}" cargo build -p mc-mobilecoind --no-default-features {CARGO_FLAGS}', + shell=True, check=True, ) diff --git a/util/grpc/src/chain_id.rs b/util/grpc/src/chain_id.rs new file mode 100644 index 0000000000..fd15b8e21d --- /dev/null +++ b/util/grpc/src/chain_id.rs @@ -0,0 +1,23 @@ +use grpcio::{RpcContext, RpcStatus, RpcStatusCode}; + +/// The string used for the chain id GRPC header +/// Note that a corresponding HTTP header is defined by the go-grpc-gateway +/// code: Chain-Id +pub const CHAIN_ID_GRPC_HEADER: &str = "chain-id"; + +/// The error message used when a chain id mismatch occurs +pub const CHAIN_ID_MISMATCH_ERR_MSG: &str = "chain-id mismatch:"; + +/// Test the chain id of a request against the value on the server side. +/// This does nothing if the client does not supply a chain-id header. +pub fn check_request_chain_id(server_chain_id: &str, ctx: &RpcContext) -> Result<(), RpcStatus> { + for (header, value) in ctx.request_headers().iter() { + if header == CHAIN_ID_GRPC_HEADER && server_chain_id.as_bytes() != value { + return Err(RpcStatus::with_message( + RpcStatusCode::FAILED_PRECONDITION, + format!("{} '{}'", CHAIN_ID_MISMATCH_ERR_MSG, server_chain_id), + )); + } + } + Ok(()) +} diff --git a/util/grpc/src/lib.rs b/util/grpc/src/lib.rs index 4362e68144..4f20c92501 100644 --- a/util/grpc/src/lib.rs +++ b/util/grpc/src/lib.rs @@ -24,6 +24,7 @@ mod admin_server; mod admin_service; mod auth; mod build_info_service; +mod chain_id; mod cookie_helper; mod grpcio_extensions; mod health_service; @@ -40,6 +41,7 @@ pub use crate::{ }, autogenerated_code::*, build_info_service::BuildInfoService, + chain_id::{check_request_chain_id, CHAIN_ID_GRPC_HEADER, CHAIN_ID_MISMATCH_ERR_MSG}, cookie_helper::{Error as CookieError, GrpcCookieStore}, grpcio_extensions::{ConnectionUriGrpcioChannel, ConnectionUriGrpcioServer}, health_service::{HealthCheckStatus, HealthService, ReadinessIndicator}, diff --git a/watcher/src/verification_reports_collector.rs b/watcher/src/verification_reports_collector.rs index 1ae6ad6c2e..07c2621900 100644 --- a/watcher/src/verification_reports_collector.rs +++ b/watcher/src/verification_reports_collector.rs @@ -76,6 +76,8 @@ impl NodeClient for ConsensusNodeClient { // Contact node and get a VerificationReport. let verifier = Verifier::default(); let mut client = ThickClient::new( + // TODO: Supply a network-id to watcher? + String::default(), node_url.clone(), verifier, env, From d8ab723d34a71aac8f685b7e37c7d209c01eef45 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Mon, 19 Sep 2022 12:33:59 -0600 Subject: [PATCH 54/77] Add check to mint client to ensure public address doesn't have fog (#2546) (#2564) * Add check to mint client to ensure public address doesn't have fog The mint client reads from a b58 address when it creates a MintTxPrefix, but it doesn't (before this commit) check if that is actually a fog address. If it is, the fog part will get silently removed, and then the fog user won't find it. This change makes it give an error message. * fixups --- consensus/mint-client/src/config.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/consensus/mint-client/src/config.rs b/consensus/mint-client/src/config.rs index 53772d8506..92c3d5f5e4 100644 --- a/consensus/mint-client/src/config.rs +++ b/consensus/mint-client/src/config.rs @@ -162,6 +162,9 @@ impl MintTxPrefixParams { self, fallback_tombstone_block: impl Fn() -> u64, ) -> Result { + if let Some(fog_url) = self.recipient.fog_report_url() { + return Err(format!("This recipient has a fog url, but minting to fog users is not supported right now: '{}'", fog_url)); + } let tombstone_block = self.tombstone.unwrap_or_else(fallback_tombstone_block); let nonce = get_or_generate_nonce(self.nonce); Ok(MintTxPrefix { From 26e6096310bfd5be129970162f7da3e35f8c0c0f Mon Sep 17 00:00:00 2001 From: Eran Rundstein Date: Mon, 19 Sep 2022 11:55:26 -0700 Subject: [PATCH 55/77] Make mobilecoind expose network fees via an API call (#2060) (#2533) * Make mobilecoind expose network fees via an API call This makes mobilecoind hit consensus' `get_last_block_info` as part of the `GetNetworkStatus` call. It forwards a subset of that information in response. There is some argument that it should forward an entire `LastBlockInfo` response object without modification -- I decided not to do that because mobilecoind's proto doesn't currently depend on the consensus api proto, only the `external.proto` and `blockchain.proto`. Feel free to tell me to that dep is okay though. This will allow mobilecoind python scripts and other clients of mobilecoind to know the current (dynamic) network fees and block version and such. * Per Eran, make polling_network_state track BlockInfo, use this in mobilecoind This allows us to eliminate a bunch of calls to get block info, which were being made to get the network_block_version and minimum fees. * Make mobilecoind forward the whole LastBlockInfoResponse object Per Eran * missing docs, use `max_by_key` instead of `reduce` Co-authored-by: Chris Beck --- Cargo.lock | 1 + connection/src/thick.rs | 2 +- connection/src/traits.rs | 16 ++++++- .../network_state/polling_network_state.rs | 32 +++++++++----- mobilecoind/api/Cargo.toml | 1 + mobilecoind/api/build.rs | 5 +++ mobilecoind/api/proto/mobilecoind_api.proto | 4 ++ mobilecoind/api/src/lib.rs | 1 + mobilecoind/src/payments.rs | 44 +++++++++---------- mobilecoind/src/service.rs | 42 +++++++++++++++++- 10 files changed, 111 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fde34873e5..3a5b8832e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4531,6 +4531,7 @@ dependencies = [ "hex_fmt", "mc-api", "mc-common", + "mc-consensus-api", "mc-transaction-std", "mc-util-build-grpc", "mc-util-build-script", diff --git a/connection/src/thick.rs b/connection/src/thick.rs index 3d8a1e4422..1e3b18bb46 100644 --- a/connection/src/thick.rs +++ b/connection/src/thick.rs @@ -379,7 +379,7 @@ impl BlockchainConnection for ThickClient { } fn fetch_block_info(&mut self) -> Result { - trace_time!(self.logger, "ThickClient::fetch_block_height"); + trace_time!(self.logger, "ThickClient::fetch_block_info"); let block_info = self.authenticated_attested_call(|this, call_option| { this.blockchain_api_client diff --git a/connection/src/traits.rs b/connection/src/traits.rs index 91ca4c579e..975dde57e2 100644 --- a/connection/src/traits.rs +++ b/connection/src/traits.rs @@ -10,7 +10,7 @@ use mc_transaction_core::{tokens::Mob, tx::Tx, Block, BlockID, BlockIndex, Token use mc_util_serial::prost::alloc::fmt::Formatter; use mc_util_uri::ConnectionUri; use std::{ - collections::BTreeMap, + collections::{BTreeMap, HashMap}, fmt::{Debug, Display, Result as FmtResult}, hash::Hash, iter::FromIterator, @@ -116,6 +116,20 @@ impl From for BlockInfo { } } +impl From for LastBlockInfoResponse { + fn from(src: BlockInfo) -> Self { + let mut result = LastBlockInfoResponse::new(); + result.index = src.block_index; + result.network_block_version = src.network_block_version; + result.set_minimum_fees(HashMap::from_iter( + src.minimum_fees + .iter() + .map(|(token_id, fee)| (**token_id, *fee)), + )); + result + } +} + /// A connection trait providing APIs for use in retrieving blocks from a /// consensus node. pub trait BlockchainConnection: Connection { diff --git a/ledger/sync/src/network_state/polling_network_state.rs b/ledger/sync/src/network_state/polling_network_state.rs index 61baabee93..8b610bc3fd 100644 --- a/ledger/sync/src/network_state/polling_network_state.rs +++ b/ledger/sync/src/network_state/polling_network_state.rs @@ -10,7 +10,7 @@ use mc_common::{ ResponderId, }; use mc_connection::{ - BlockchainConnection, Connection, ConnectionManager, RetryableBlockchainConnection, + BlockInfo, BlockchainConnection, Connection, ConnectionManager, RetryableBlockchainConnection, }; use mc_consensus_scp::{ core_types::Ballot, msg::ExternalizePayload, Msg, QuorumSet, SlotIndex, Topic, @@ -40,6 +40,9 @@ pub struct PollingNetworkState { /// check logic. scp_network_state: SCPNetworkState, + /// Last block info objects, per responder id + block_infos: HashMap, + /// Logger. logger: Logger, } @@ -58,13 +61,14 @@ impl PollingNetworkState { Self { manager, scp_network_state: SCPNetworkState::new(local_node_id, quorum_set), + block_infos: Default::default(), logger, } } /// Polls peers to find out the current state of the network. pub fn poll(&mut self) { - type ResultsMap = HashMap>; + type ResultsMap = HashMap>; let results_and_condvar = Arc::new((Mutex::new(ResultsMap::default()), Condvar::new())); for conn in self.manager.conns() { @@ -82,24 +86,24 @@ impl PollingNetworkState { let &(ref lock, ref condvar) = &*thread_results_and_condvar; - let block_height_result = conn.fetch_block_height(Self::get_retry_iterator()); + let block_info_result = conn.fetch_block_info(Self::get_retry_iterator()); let mut results = lock.lock().expect("mutex poisoned"); - match &block_height_result { - Ok(index) => { + match &block_info_result { + Ok(info) => { log::debug!( thread_logger, "Last block reported by {}: {}", conn, - index + info.block_index ); - results.insert(responder_id.clone(), Some(*index)); + results.insert(responder_id.clone(), Some(info.clone())); } Err(err) => { log::error!( thread_logger, - "Failed getting last block from {}: {:?}", + "Failed getting block info from {}: {:?}", conn, err ); @@ -127,17 +131,19 @@ impl PollingNetworkState { ); // Hackishly feed into SCPNetworkState - for (responder_id, block_index) in results.iter() { - if let Some(block_index) = block_index { + for (responder_id, block_info) in results.iter() { + if let Some(block_info) = block_info.as_ref() { self.scp_network_state.push(Msg::<&str, ResponderId>::new( responder_id.clone(), QuorumSet::empty(), - *block_index as SlotIndex, + block_info.block_index as SlotIndex, Topic::Externalize(ExternalizePayload { C: Ballot::new(1, &["fake"]), HN: 1, }), )); + self.block_infos + .insert(responder_id.clone(), block_info.clone()); } } } @@ -146,6 +152,10 @@ impl PollingNetworkState { self.scp_network_state.peer_to_current_slot() } + pub fn peer_to_block_info(&self) -> &HashMap { + &self.block_infos + } + fn get_retry_iterator() -> Box> { // Start at 50ms, make 10 attempts (total would be 7150ms) Box::new(Fibonacci::from_millis(50).take(10).map(jitter)) diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index 05bb4ae36e..7340022995 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -8,6 +8,7 @@ links = "mc-mobilecoind-api" [dependencies] mc-api = { path = "../../api" } +mc-consensus-api = { path = "../../consensus/api" } mc-util-uri = { path = "../../util/uri" } futures = "0.3" diff --git a/mobilecoind/api/build.rs b/mobilecoind/api/build.rs index f4e95d95c8..8d3c89df80 100644 --- a/mobilecoind/api/build.rs +++ b/mobilecoind/api/build.rs @@ -16,7 +16,12 @@ fn main() { .depvar("MC_API_PROTOS_PATH") .expect("Could not read api's protos path") .to_owned(); + let consensus_api_proto_path = env + .depvar("MC_CONSENSUS_API_PROTOS_PATH") + .expect("Could not read api's protos path") + .to_owned(); let mut all_proto_dirs = api_proto_path.split(':').collect::>(); + all_proto_dirs.extend(consensus_api_proto_path.split(':')); all_proto_dirs.push(proto_str); mc_util_build_grpc::compile_protos_and_generate_mod_rs( diff --git a/mobilecoind/api/proto/mobilecoind_api.proto b/mobilecoind/api/proto/mobilecoind_api.proto index aee8bc4b70..2a1c646b43 100644 --- a/mobilecoind/api/proto/mobilecoind_api.proto +++ b/mobilecoind/api/proto/mobilecoind_api.proto @@ -8,6 +8,7 @@ syntax = "proto3"; import "google/protobuf/empty.proto"; import "external.proto"; import "blockchain.proto"; +import "consensus_common.proto"; package mobilecoind_api; @@ -825,6 +826,9 @@ message GetNetworkStatusResponse { // Whether we are behind. bool is_behind = 4; + + // The latest block info reported by a consensus node + consensus_common.LastBlockInfoResponse last_block_info = 5; } // diff --git a/mobilecoind/api/src/lib.rs b/mobilecoind/api/src/lib.rs index 714831dfa6..b3cad06e28 100644 --- a/mobilecoind/api/src/lib.rs +++ b/mobilecoind/api/src/lib.rs @@ -7,6 +7,7 @@ use mc_util_uri::{Uri, UriScheme}; mod autogenerated_code { // Expose proto data types from included third-party/external proto files. pub use mc_api::{blockchain, external, printable}; + pub use mc_consensus_api::consensus_common; pub use protobuf::well_known_types::Empty; // Needed due to how to the auto-generated code references the Empty message. diff --git a/mobilecoind/src/payments.rs b/mobilecoind/src/payments.rs index f94b4fab8d..eaa06637fa 100644 --- a/mobilecoind/src/payments.rs +++ b/mobilecoind/src/payments.rs @@ -9,8 +9,7 @@ use mc_common::{ HashMap, HashSet, }; use mc_connection::{ - BlockInfo, BlockchainConnection, ConnectionManager, RetryableBlockchainConnection, - RetryableUserTxConnection, UserTxConnection, + BlockInfo, BlockchainConnection, ConnectionManager, RetryableUserTxConnection, UserTxConnection, }; use mc_crypto_keys::RistrettoPublic; use mc_crypto_rand::{CryptoRng, RngCore}; @@ -29,7 +28,6 @@ use mc_transaction_std::{ }; use mc_util_uri::FogUri; use rand::Rng; -use rayon::prelude::*; use std::{ cmp::{max, Reverse}, convert::TryFrom, @@ -131,16 +129,6 @@ impl( - peer_manager: &ConnectionManager, -) -> Vec { - peer_manager - .conns() - .par_iter() - .filter_map(|conn| conn.fetch_block_info(empty()).ok()) - .collect() -} - fn get_network_block_version(block_infos: &[BlockInfo]) -> u32 { block_infos .iter() @@ -194,6 +182,7 @@ impl Result<(u64, u32), Error> { // Figure out the block_version and fee (involves network round-trips to // consensus, unless opt_fee is non-zero @@ -201,11 +190,10 @@ impl>, @@ -264,7 +255,8 @@ impl Result { let logger = self.logger.new( @@ -366,7 +361,8 @@ impl Result { let logger = self.logger.new(o!("receiver" => receiver.to_string())); log::trace!(logger, "Generating txo list transaction..."); @@ -495,7 +494,8 @@ impl Vec { + self.network_state + .read() + .expect("lock poisoned") + .peer_to_block_info() + .values() + .cloned() + .collect() + } + fn add_monitor_impl( &mut self, request: mc_mobilecoind_api::AddMonitorRequest, @@ -881,6 +893,7 @@ impl Date: Mon, 19 Sep 2022 16:31:49 -0700 Subject: [PATCH 56/77] added hash-tx-file subcommand to print the hash of a mint-tx or mint-config-tx file (#2406) (#2572) Co-authored-by: Henry Holtzman --- consensus/mint-client/src/bin/main.rs | 9 +++++++++ consensus/mint-client/src/config.rs | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/consensus/mint-client/src/bin/main.rs b/consensus/mint-client/src/bin/main.rs index 235991a409..b27e46d5ef 100644 --- a/consensus/mint-client/src/bin/main.rs +++ b/consensus/mint-client/src/bin/main.rs @@ -187,6 +187,15 @@ fn main() { .expect("failed writing output file"); } + Commands::HashTxFile { tx_file } => match tx_file { + TxFile::MintConfigTx(tx) => { + println!("{}", hex::encode(&tx.prefix.hash())); + } + TxFile::MintTx(tx) => { + println!("{}", hex::encode(&tx.prefix.hash())); + } + } + Commands::HashMintTx { params } => { let tx_prefix = params .try_into_mint_tx_prefix(|| panic!("missing tombstone block")) diff --git a/consensus/mint-client/src/config.rs b/consensus/mint-client/src/config.rs index 92c3d5f5e4..ad0756f491 100644 --- a/consensus/mint-client/src/config.rs +++ b/consensus/mint-client/src/config.rs @@ -263,6 +263,14 @@ pub enum Commands { params: MintConfigTxPrefixParams, }, + /// Produce a hash of a MintConfigTx or MintTx tranasaction from a JSON tx-file. + /// This is useful for offline/HSM signing. + HashTxFile { + /// The file to load + #[clap(long, parse(try_from_str = load_tx_file_from_path), env = "MC_MINTING_TX_FILE")] + tx_file: TxFile, + }, + /// Submit json-encoded MintConfigTx(s). If multiple transactions are /// provided, signatures will be merged. SubmitMintConfigTx { From b645a9afde95342177e00bac39dd4712dee4dd7b Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Tue, 4 Oct 2022 16:18:23 -0500 Subject: [PATCH 57/77] release/v2: [Fixes] CI/CD, chart, container - Fix consensus node bootstrap from scratch. (#2582) * fixes so we can bootstrap new network from scratch * Add fog report url var to deployment, clean up some linting errors introduced by previous commits. * Fix ledger bootstrap logic order * Generate python stubs for consensus_common in mobilecoind-related tests Co-authored-by: Joseph Kottke --- .../mobilecoin-workflow-dev-deploy.yaml | 1 + .internal-ci/docker/entrypoints/node_hw.sh | 23 ++++++++++--------- .../bin/wrapper-ledger-distribution.sh | 18 +++++++++++++-- .../templates/node-deployment.yaml | 10 ++++++++ .internal-ci/test/mint-auditor-test.sh | 6 +++++ .../test/mobilecoind-integration-test.sh | 9 ++++++++ .../test/mobilecoind-json-integration-test.sh | 6 +++++ .internal-ci/util/drain_accounts.sh | 6 +++++ consensus/mint-client/src/bin/main.rs | 2 +- consensus/mint-client/src/config.rs | 4 ++-- 10 files changed, 69 insertions(+), 16 deletions(-) diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml index ec50e112f9..7983fe8c8a 100644 --- a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -188,6 +188,7 @@ jobs: mkdir -p .tmp/seeds echo -n "${FOG_REPORT_SIGNING_CA_CERT}" > .tmp/seeds/FOG_REPORT_SIGNING_CA_CERT echo -n "/wallet-seeds/FOG_REPORT_SIGNING_CA_CERT" > .tmp/seeds/FOG_REPORT_SIGNING_CA_CERT_PATH + echo -n "fog://fog.${{ inputs.namespace }}.development.mobilecoin.com:443" > .tmp/seeds/FOG_REPORT_URL - name: Create wallet key secrets uses: mobilecoinofficial/gha-k8s-toolbox@v1 diff --git a/.internal-ci/docker/entrypoints/node_hw.sh b/.internal-ci/docker/entrypoints/node_hw.sh index c82767ef73..3217aa6b72 100755 --- a/.internal-ci/docker/entrypoints/node_hw.sh +++ b/.internal-ci/docker/entrypoints/node_hw.sh @@ -146,18 +146,8 @@ then cp /ledger/data.mdb "/ledger/data.mdb.$(date +%y%m%d-%H%M%S)" /usr/bin/mc-ledger-migration --ledger-db "${MC_LEDGER_PATH}" else - # Look for wallet keys seed - development and CD deploys - if [[ -n "${INITIAL_KEYS_SEED}" ]] - then - echo "INITIAL_KEYS_SEED found - populating origin data" - export INITIALIZE_LEDGER="true" - - /usr/local/bin/generate_origin_data.sh - - cp /tmp/sample_data/ledger/data.mdb "${MC_LEDGER_PATH}" - # Try to find origin block from s3 archive - preserve existing data, testnet/mainnet - elif archive_curl "${MC_TX_SOURCE_URL}" + if archive_curl "${MC_TX_SOURCE_URL}" then echo "Remote archive ledger found - restore with ledger-from-archive" echo " Note: RUST_LOG=warn so we don't get 1m+ lines of logs" @@ -170,6 +160,17 @@ then then echo "Found origin ledger at ${ORIGIN_LEDGER_PATH}" cp "${ORIGIN_LEDGER_PATH}" "${MC_LEDGER_PATH}" + + # Look for wallet keys seed - development and CD deploys + elif [[ -n "${INITIAL_KEYS_SEED}" ]] + then + echo "INITIAL_KEYS_SEED found - populating origin data" + export INITIALIZE_LEDGER="true" + + /usr/local/bin/generate_origin_data.sh + + cp /tmp/sample_data/ledger/data.mdb "${MC_LEDGER_PATH}" + else # We ain't found nothin, bail out! echo "INITIAL_KEYS_SEED not set, no remote ledger and cannot find origin ledger file" diff --git a/.internal-ci/docker/support/node_hw/bin/wrapper-ledger-distribution.sh b/.internal-ci/docker/support/node_hw/bin/wrapper-ledger-distribution.sh index 5145af39ad..ea4a0dc891 100755 --- a/.internal-ci/docker/support/node_hw/bin/wrapper-ledger-distribution.sh +++ b/.internal-ci/docker/support/node_hw/bin/wrapper-ledger-distribution.sh @@ -18,6 +18,11 @@ is_set() fi } +archive_curl() +{ + /usr/bin/curl -IfsSL --retry 3 "${1}00/00/00/00/00/00/00/0000000000000000.pb" -o /dev/null +} + is_set MC_DEST is_set AWS_ACCESS_KEY_ID is_set AWS_SECRET_ACCESS_KEY @@ -49,8 +54,17 @@ then export MC_START_FROM=last else - echo "mc.app:wrapper-ledger-distribution - no state file found MC_START_FROM=next" - export MC_START_FROM=next + echo "mc.app:wrapper-ledger-distribution - no state file found." + echo "mc.app:wrapper-ledger-distribution - checking for an existing block 0 in s3" + + if archive_curl "${MC_TX_SOURCE_URL}" + then + echo "mc.app:wrapper-ledger-distribution - block 0 found in s3 MC_START_FROM=next" + export MC_START_FROM=next + else + echo "mc.app:wrapper-ledger-distribution - no s3 archive found MC_START_FROM=zero" + export MC_START_FROM=zero + fi fi /usr/bin/ledger-distribution diff --git a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml index f2a8d22ea3..d51a51b910 100644 --- a/.internal-ci/helm/consensus-node/templates/node-deployment.yaml +++ b/.internal-ci/helm/consensus-node/templates/node-deployment.yaml @@ -101,6 +101,9 @@ spec: name: ias - configMapRef: name: {{ include "consensusNode.nodeConfig.configMap.name" . }} + - secretRef: + name: sample-keys-seeds + optional: true env: - name: PATH value: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64' @@ -142,6 +145,9 @@ spec: - name: node-cert mountPath: /certs readOnly: true + - name: wallet-seeds + mountPath: /wallet-seeds + readOnly: true resources: {{- toYaml .Values.node.resources | nindent 10}} {{- if eq .Values.jaegerTracing.enabled true }} @@ -197,6 +203,10 @@ spec: - name: node-cert secret: secretName: {{ include "consensusNode.fullname" . }}-internal-tls + - name: wallet-seeds + secret: + secretName: sample-keys-seeds + optional: true - name: ledger-db-dir {{- if eq .Values.node.persistence.enabled true }} persistentVolumeClaim: diff --git a/.internal-ci/test/mint-auditor-test.sh b/.internal-ci/test/mint-auditor-test.sh index 90b3631273..88f491ece5 100755 --- a/.internal-ci/test/mint-auditor-test.sh +++ b/.internal-ci/test/mint-auditor-test.sh @@ -66,6 +66,12 @@ python3 -m grpc_tools.protoc \ --python_out=. \ "/proto/api/blockchain.proto" +python3 -m grpc_tools.protoc \ + -I"/proto/api" -I"/proto/consensus" \ + --python_out=. \ + --grpc_python_out=. \ + "/proto/consensus/consensus_common.proto" + python3 -m grpc_tools.protoc \ -I"/proto/api" \ -I"/proto/mobilecoind" \ diff --git a/.internal-ci/test/mobilecoind-integration-test.sh b/.internal-ci/test/mobilecoind-integration-test.sh index 51403a737c..8053983dda 100755 --- a/.internal-ci/test/mobilecoind-integration-test.sh +++ b/.internal-ci/test/mobilecoind-integration-test.sh @@ -45,6 +45,15 @@ then --python_out=. "/proto/api/blockchain.proto" fi +if [[ -f "/proto/consensus/consensus_common.proto" ]] +then + python3 -m grpc_tools.protoc \ + -I"/proto/api" -I"/proto/consensus" \ + --python_out=. \ + --grpc_python_out=. \ + "/proto/consensus/consensus_common.proto" +fi + if [[ -f "/proto/mobilecoind/mobilecoind_api.proto" ]] then python3 -m grpc_tools.protoc \ diff --git a/.internal-ci/test/mobilecoind-json-integration-test.sh b/.internal-ci/test/mobilecoind-json-integration-test.sh index c227eae572..fb5e0b0362 100755 --- a/.internal-ci/test/mobilecoind-json-integration-test.sh +++ b/.internal-ci/test/mobilecoind-json-integration-test.sh @@ -69,6 +69,12 @@ python3 -m grpc_tools.protoc \ --python_out=. \ "/proto/api/blockchain.proto" +python3 -m grpc_tools.protoc \ + -I"/proto/api" -I"/proto/consensus" \ + --python_out=. \ + --grpc_python_out=. \ + "/proto/consensus/consensus_common.proto" + python3 -m grpc_tools.protoc \ -I"/proto/api" \ -I"/proto/mobilecoind" \ diff --git a/.internal-ci/util/drain_accounts.sh b/.internal-ci/util/drain_accounts.sh index a621db74a8..663ed5f000 100755 --- a/.internal-ci/util/drain_accounts.sh +++ b/.internal-ci/util/drain_accounts.sh @@ -87,6 +87,12 @@ python3 -m grpc_tools.protoc \ --python_out=. \ "/proto/api/blockchain.proto" +python3 -m grpc_tools.protoc \ + -I"/proto/api" -I"/proto/consensus" \ + --python_out=. \ + --grpc_python_out=. \ + "/proto/consensus/consensus_common.proto" + python3 -m grpc_tools.protoc \ -I"/proto/api" \ -I"/proto/mobilecoind" \ diff --git a/consensus/mint-client/src/bin/main.rs b/consensus/mint-client/src/bin/main.rs index b27e46d5ef..33a276f6ce 100644 --- a/consensus/mint-client/src/bin/main.rs +++ b/consensus/mint-client/src/bin/main.rs @@ -194,7 +194,7 @@ fn main() { TxFile::MintTx(tx) => { println!("{}", hex::encode(&tx.prefix.hash())); } - } + }, Commands::HashMintTx { params } => { let tx_prefix = params diff --git a/consensus/mint-client/src/config.rs b/consensus/mint-client/src/config.rs index ad0756f491..3a37acd9d1 100644 --- a/consensus/mint-client/src/config.rs +++ b/consensus/mint-client/src/config.rs @@ -263,8 +263,8 @@ pub enum Commands { params: MintConfigTxPrefixParams, }, - /// Produce a hash of a MintConfigTx or MintTx tranasaction from a JSON tx-file. - /// This is useful for offline/HSM signing. + /// Produce a hash of a MintConfigTx or MintTx tranasaction from a JSON + /// tx-file. This is useful for offline/HSM signing. HashTxFile { /// The file to load #[clap(long, parse(try_from_str = load_tx_file_from_path), env = "MC_MINTING_TX_FILE")] From f9f724795ed5e65e76a2a6970a1703a58de9af68 Mon Sep 17 00:00:00 2001 From: wjuan-mob Date: Tue, 4 Oct 2022 18:45:21 -0400 Subject: [PATCH 58/77] Feature/cherry pick tob 4 (#2651) * Add mint config tx duplicate nonce across tokens test (cherry picked from commit b4fdc016897f72a073180dc93d4cba080e39ec8e) * Filter nonces in combine mint config tx across tokens (cherry picked from commit 548a07db7d7634c3ebcc41a6509a669061b926d8) * Add test for duplicate nonce across token in mint tx combine * Fix duplicate nonce across multiple tokens in mint tx combine (cherry picked from commit 410c4dd68e3daf6120089996d1114b872d2f7a5d) * Remove unnecessary code from test. (cherry picked from commit 5e8c8e27af2080ad6e77e0c7325c263055535ed4) * Update check mint tx nonce to take token_id (cherry picked from commit 5b7909d96f3936ee7f7968096f4d1e72032c249c) * Update write mint tx to store by token_id and nonce. Add test for duplicate nonce. (cherry picked from commit d42a3557cf93ccce29dd9cfb5b94fc6521a2b29a) * Update check mint tx nonce to include token_id. (cherry picked from commit 34f1c29371f077d062ee3d655be57bad6f79f59c) * Fix comments. (cherry picked from commit 9755feaaf9bd8d286853873b96be914147c64cbe) * Lint. (cherry picked from commit e567e9c549c77d786fc1f6c2b80ed502eadcc4ca) * Add migration code for mint stores. (cherry picked from commit 05fc8e8498b619ea3a28ea494fd74a19b020e911) * Lint (cherry picked from commit b5165c789247b9b10ef210772364cee3a7d1c160) * Apply suggestions from code review Co-authored-by: Eran Rundstein (cherry picked from commit 6ad7aaf0591f22b129a25a942b30ccb42f46ed44) * Update write_validated_mint_config_txs to take token_id as well as nonce for the key. (cherry picked from commit 989bda781eb31d54a6b1d4ef2b1edd929231411f) * Fix failing test due to change from master to v2. * Lint. * Bring in change from master to get consensus common pb2 to build. --- consensus/service/src/mint_tx_manager/mod.rs | 177 ++++++++++++++++++- fog/ledger/test_infra/src/lib.rs | 12 +- ledger/db/src/ledger_db.rs | 34 ++-- ledger/db/src/ledger_trait.rs | 18 +- ledger/db/src/mint_config_store.rs | 177 +++++++++++++------ ledger/db/src/mint_tx_store.rs | 132 +++++++++++--- ledger/db/src/test_utils/mock_ledger.rs | 12 +- ledger/migration/src/lib.rs | 80 +++++++++ mint-auditor/tests/compile_proto.sh | 1 + 9 files changed, 544 insertions(+), 99 deletions(-) diff --git a/consensus/service/src/mint_tx_manager/mod.rs b/consensus/service/src/mint_tx_manager/mod.rs index a089bbbc9b..e7c48345cc 100644 --- a/consensus/service/src/mint_tx_manager/mod.rs +++ b/consensus/service/src/mint_tx_manager/mod.rs @@ -60,13 +60,22 @@ impl MintTxManagerImpl { } } +#[derive(Debug, Eq, Hash, PartialEq)] +struct NonceByTokenId { + nonce: Vec, + token_id: u64, +} + impl MintTxManager for MintTxManagerImpl { /// Validate a MintConfigTx transaction against the current ledger. fn validate_mint_config_tx(&self, mint_config_tx: &MintConfigTx) -> MintTxManagerResult<()> { // Ensure that we have not seen this transaction before. if self .ledger_db - .check_mint_config_tx_nonce(&mint_config_tx.prefix.nonce)? + .check_mint_config_tx_nonce( + mint_config_tx.prefix.token_id, + &mint_config_tx.prefix.nonce, + )? .is_some() { return Err(MintTxManagerError::MintValidation( @@ -107,13 +116,17 @@ impl MintTxManager for MintTxManagerImpl { let mut seen_nonces = HashSet::default(); let (allowed_txs, _rejected_txs) = candidates.into_iter().partition(|tx| { + let nonce_with_token_id = NonceByTokenId { + nonce: tx.prefix.nonce.clone(), + token_id: tx.prefix.token_id, + }; if seen_nonces.len() >= max_elements { return false; } - if seen_nonces.contains(&tx.prefix.nonce) { + if seen_nonces.contains(&nonce_with_token_id) { return false; } - seen_nonces.insert(tx.prefix.nonce.clone()); + seen_nonces.insert(nonce_with_token_id); true }); @@ -124,7 +137,7 @@ impl MintTxManager for MintTxManagerImpl { // Ensure that we have not seen this transaction before. if self .ledger_db - .check_mint_tx_nonce(&mint_tx.prefix.nonce)? + .check_mint_tx_nonce(mint_tx.prefix.token_id, &mint_tx.prefix.nonce)? .is_some() { return Err(MintTxManagerError::MintValidation( @@ -172,10 +185,14 @@ impl MintTxManager for MintTxManagerImpl { let mut seen_nonces = HashSet::default(); let mut seen_mint_configs = HashSet::default(); let (allowed_txs, _rejected_txs) = candidates.into_iter().partition(|tx| { + let nonce_with_token_id = NonceByTokenId { + nonce: tx.prefix.nonce.clone(), + token_id: tx.prefix.token_id, + }; if seen_nonces.len() >= max_elements { return false; } - if seen_nonces.contains(&tx.prefix.nonce) { + if seen_nonces.contains(&nonce_with_token_id) { return false; } @@ -197,7 +214,7 @@ impl MintTxManager for MintTxManagerImpl { return false; } - seen_nonces.insert(tx.prefix.nonce.clone()); + seen_nonces.insert(nonce_with_token_id); seen_mint_configs.insert(active_mint_config.mint_config); true }); @@ -564,6 +581,61 @@ mod mint_config_tx_tests { ); } + /// combine_mint_config_txs adequately sorts inputs and disposes of + /// duplicates when handling multiple token types. + #[test_with_logger] + fn combine_mint_config_txs_sorts_and_removes_dupes_multi_token(logger: Logger) { + let mut rng: StdRng = SeedableRng::from_seed([77u8; 32]); + + let token_id_1 = TokenId::from(1); + let token_id_2 = TokenId::from(2); + + let mut ledger = create_ledger(); + let n_blocks = 3; + let block_version = BlockVersion::MAX; + let sender = AccountKey::random(&mut rng); + initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); + + rng = SeedableRng::from_seed([77u8; 32]); + let mut rng2: StdRng = SeedableRng::from_seed([77u8; 32]); + + let (mint_config_tx1, signers) = create_mint_config_tx_and_signers(token_id_1, &mut rng); + let (mint_config_tx2, signers2) = create_mint_config_tx_and_signers(token_id_2, &mut rng2); + + assert_eq!(mint_config_tx1.prefix.nonce, mint_config_tx2.prefix.nonce); + + let token_id_to_governors = GovernorsMap::try_from_iter(vec![ + ( + token_id_1, + SignerSet::new(signers.iter().map(|s| s.public_key()).collect(), 1), + ), + ( + token_id_2, + SignerSet::new(signers2.iter().map(|s| s.public_key()).collect(), 1), + ), + ]) + .unwrap(); + let mint_tx_manager = + MintTxManagerImpl::new(ledger, BlockVersion::MAX, token_id_to_governors, logger); + + let mut expected_result = vec![mint_config_tx1.clone(), mint_config_tx2.clone()]; + expected_result.sort(); + + assert_eq!( + mint_tx_manager.combine_mint_config_txs( + &[ + mint_config_tx1.clone(), + mint_config_tx2.clone(), + mint_config_tx1.clone(), + mint_config_tx1, + mint_config_tx2, + ], + 100 + ), + Ok(expected_result) + ); + } + /// combine_mint_config_txs adequately caps the number of outputs. #[test_with_logger] fn combine_mint_config_txs_caps_num_of_outputs(logger: Logger) { @@ -1411,6 +1483,99 @@ mod mint_tx_tests { ); } + /// combine_mint_txs adequately sorts inputs and disposes of + /// duplicates. + #[test_with_logger] + fn combine_mint_txs_sorts_and_keeps_duplicate_nonces_across_tokens(logger: Logger) { + let mut rng: StdRng = SeedableRng::from_seed([77u8; 32]); + + let token_id_1 = TokenId::from(1); + let token_id_2 = TokenId::from(2); + + let mut ledger = create_ledger(); + let n_blocks = 3; + let block_version = BlockVersion::MAX; + let sender = AccountKey::random(&mut rng); + initialize_ledger(block_version, &mut ledger, n_blocks, &sender, &mut rng); + let parent_block = ledger.get_block(ledger.num_blocks().unwrap() - 1).unwrap(); + + // Create a mint configuration and append it to the ledger. + let (mint_config_tx, signers) = create_mint_config_tx_and_signers(token_id_1, &mut rng); + let (mint_config_tx2, signers2) = create_mint_config_tx_and_signers(token_id_2, &mut rng); + + let block_contents = BlockContents { + validated_mint_config_txs: vec![ + to_validated(&mint_config_tx), + to_validated(&mint_config_tx2), + ], + ..Default::default() + }; + let block = Block::new_with_parent( + BlockVersion::MAX, + &parent_block, + &Default::default(), + &block_contents, + ); + + ledger.append_block(&block, &block_contents, None).unwrap(); + let mut rng1: StdRng = SeedableRng::from_seed([77u8; 32]); + let mint_tx1 = create_mint_tx( + token_id_1, + &[Ed25519Pair::from(signers[0].private_key())], + 1, + &mut rng1, + ); + + let mut rng2: StdRng = SeedableRng::from_seed([77u8; 32]); + let mint_tx2 = create_mint_tx( + token_id_2, + &[Ed25519Pair::from(signers2[0].private_key())], + 1, + &mut rng2, + ); + + assert_eq!(mint_tx1.prefix.nonce, mint_tx2.prefix.nonce); + // Test txs, each one using a different mint configuration (determined by the + // signers) + let mint_txs = vec![mint_tx1, mint_tx2]; + + // Create MintTxManagerImpl + let token_id_to_governors = GovernorsMap::try_from_iter(vec![ + ( + token_id_1, + SignerSet::new(signers.iter().map(|s| s.public_key()).collect(), 1), + ), + ( + token_id_2, + SignerSet::new(signers2.iter().map(|s| s.public_key()).collect(), 1), + ), + ]) + .unwrap(); + let mint_tx_manager = + MintTxManagerImpl::new(ledger, BlockVersion::MAX, token_id_to_governors, logger); + + let mut expected_result = mint_txs.clone(); + expected_result.sort(); + + assert_eq!( + mint_tx_manager.combine_mint_txs( + &[ + mint_txs[0].clone(), + mint_txs[0].clone(), + mint_txs[1].clone(), + mint_txs[1].clone(), + mint_txs[0].clone(), + mint_txs[0].clone(), + mint_txs[1].clone(), + mint_txs[0].clone(), + mint_txs[1].clone(), + ], + 100 + ), + Ok(expected_result) + ); + } + /// combine_mint_txs only accepts one transaction for each mint /// configuration. #[test_with_logger] diff --git a/fog/ledger/test_infra/src/lib.rs b/fog/ledger/test_infra/src/lib.rs index 80786dcc8a..216ee5c5f0 100644 --- a/fog/ledger/test_infra/src/lib.rs +++ b/fog/ledger/test_infra/src/lib.rs @@ -200,11 +200,19 @@ impl Ledger for MockLedger { unimplemented!() } - fn check_mint_config_tx_nonce(&self, _nonce: &[u8]) -> Result, Error> { + fn check_mint_config_tx_nonce( + &self, + _token_id: u64, + _nonce: &[u8], + ) -> Result, Error> { unimplemented!() } - fn check_mint_tx_nonce(&self, _nonce: &[u8]) -> Result, Error> { + fn check_mint_tx_nonce( + &self, + _token_id: u64, + _nonce: &[u8], + ) -> Result, Error> { unimplemented!() } diff --git a/ledger/db/src/ledger_db.rs b/ledger/db/src/ledger_db.rs index a0516e424b..d6b00848a3 100644 --- a/ledger/db/src/ledger_db.rs +++ b/ledger/db/src/ledger_db.rs @@ -59,7 +59,7 @@ impl MetadataStoreSettings for LedgerDbMetadataStoreSettings { // db opening for any incompatibilities, and either refuse to open or // perform a migration. #[allow(clippy::inconsistent_digit_grouping)] - const LATEST_VERSION: u64 = 2022_02_22; + const LATEST_VERSION: u64 = 2022_09_21; /// The current crate version that manages the database. const CRATE_VERSION: &'static str = env!("CARGO_PKG_VERSION"); @@ -370,22 +370,31 @@ impl Ledger for LedgerDB { .get_active_mint_configs_map(&db_transaction) } - /// Checks if the ledger contains a given MintConfigTx nonce. - /// If so, returns the index of the block in which it entered the ledger. - /// Ok(None) is returned when the nonce is not in the ledger. - fn check_mint_config_tx_nonce(&self, nonce: &[u8]) -> Result, Error> { + /// Checks if the ledger contains a given MintConfigTx nonce for a given + /// token id. If so, returns the index of the block in which it entered + /// the ledger. Ok(None) is returned when the nonce is not in the + /// ledger. + fn check_mint_config_tx_nonce( + &self, + token_id: u64, + nonce: &[u8], + ) -> Result, Error> { let db_transaction = self.env.begin_ro_txn()?; self.mint_config_store - .check_mint_config_tx_nonce(nonce, &db_transaction) + .check_mint_config_tx_nonce(token_id, nonce, &db_transaction) } - /// Checks if the ledger contains a given MintTx nonce. + /// Checks if the ledger contains a given MintTx nonce for a given token id. /// If so, returns the index of the block in which it entered the ledger. /// Ok(None) is returned when the nonce is not in the ledger. - fn check_mint_tx_nonce(&self, nonce: &[u8]) -> Result, Error> { + fn check_mint_tx_nonce( + &self, + token_id: u64, + nonce: &[u8], + ) -> Result, Error> { let db_transaction = self.env.begin_ro_txn()?; self.mint_tx_store - .check_mint_tx_nonce(nonce, &db_transaction) + .check_mint_tx_nonce(token_id, nonce, &db_transaction) } /// Attempt to get an active mint configuration that is able to verify and @@ -718,7 +727,11 @@ impl LedgerDB { for mint_tx in block_contents.mint_txs.iter() { if self .mint_tx_store - .check_mint_tx_nonce(&mint_tx.prefix.nonce, db_transaction)? + .check_mint_tx_nonce( + mint_tx.prefix.token_id, + &mint_tx.prefix.nonce, + db_transaction, + )? .is_some() { return Err(Error::DuplicateMintTx); @@ -730,6 +743,7 @@ impl LedgerDB { if self .mint_config_store .check_mint_config_tx_nonce( + validated_mint_config_tx.mint_config_tx.prefix.token_id, &validated_mint_config_tx.mint_config_tx.prefix.nonce, db_transaction, )? diff --git a/ledger/db/src/ledger_trait.rs b/ledger/db/src/ledger_trait.rs index 20cf81230c..5d8f4b0142 100644 --- a/ledger/db/src/ledger_trait.rs +++ b/ledger/db/src/ledger_trait.rs @@ -101,15 +101,21 @@ pub trait Ledger: Send { /// Return the full map of TokenId -> ActiveMintConfigs. fn get_active_mint_configs_map(&self) -> Result, Error>; - /// Checks if the ledger contains a given MintConfigTx nonce. - /// If so, returns the index of the block in which it entered the ledger. - /// Ok(None) is returned when the nonce is not in the ledger. - fn check_mint_config_tx_nonce(&self, nonce: &[u8]) -> Result, Error>; + /// Checks if the ledger contains a given MintConfigTx nonce for a given + /// token id. If so, returns the index of the block in which it entered + /// the ledger. Ok(None) is returned when the nonce is not in the + /// ledger. + fn check_mint_config_tx_nonce( + &self, + token_id: u64, + nonce: &[u8], + ) -> Result, Error>; - /// Checks if the ledger contains a given MintTx nonce. + /// Checks if the ledger contains a given MintTx nonce for a given token id. /// If so, returns the index of the block in which it entered the ledger. /// Ok(None) is returned when the nonce is not in the ledger. - fn check_mint_tx_nonce(&self, nonce: &[u8]) -> Result, Error>; + fn check_mint_tx_nonce(&self, token_id: u64, nonce: &[u8]) + -> Result, Error>; /// Attempt to get an active mint configuration that is able to verify and /// accommodate a given MintTx. diff --git a/ledger/db/src/mint_config_store.rs b/ledger/db/src/mint_config_store.rs index 8e03a34430..0022ba34e5 100644 --- a/ledger/db/src/mint_config_store.rs +++ b/ledger/db/src/mint_config_store.rs @@ -27,8 +27,8 @@ use mc_util_serial::{decode, encode, Message}; // LMDB Database names. pub const ACTIVE_MINT_CONFIGS_BY_TOKEN_ID_DB_NAME: &str = "mint_config_store:active_mint_configs_by_token_id"; -pub const BLOCK_INDEX_BY_MINT_CONFIG_TX_NONCE_DB_NAME: &str = - "mint_config_store:block_index_by_mint_config_tx_nonce"; +pub const BLOCK_INDEX_BY_MINT_CONFIG_TX_NONCE_AND_TOKEN_ID_DB_NAME: &str = + "mint_config_store:block_index_by_mint_config_tx_nonce_and_token_id"; pub const VALIDATED_MINT_CONFIG_TXS_BY_BLOCK_DB_NAME: &str = "mint_config_store:validated_mint_config_txs_by_block"; @@ -189,7 +189,7 @@ pub struct MintConfigStore { active_mint_configs_by_token_id: Database, /// nonce -> block index - block_index_by_mint_config_tx_nonce: Database, + block_index_by_mint_config_tx_nonce_and_token_id: Database, /// block_index -> ValidatedMintConfigTxList validated_mint_config_txs_by_block: Database, @@ -201,8 +201,9 @@ impl MintConfigStore { Ok(MintConfigStore { active_mint_configs_by_token_id: env .open_db(Some(ACTIVE_MINT_CONFIGS_BY_TOKEN_ID_DB_NAME))?, - block_index_by_mint_config_tx_nonce: env - .open_db(Some(BLOCK_INDEX_BY_MINT_CONFIG_TX_NONCE_DB_NAME))?, + block_index_by_mint_config_tx_nonce_and_token_id: env.open_db(Some( + BLOCK_INDEX_BY_MINT_CONFIG_TX_NONCE_AND_TOKEN_ID_DB_NAME, + ))?, validated_mint_config_txs_by_block: env .open_db(Some(VALIDATED_MINT_CONFIG_TXS_BY_BLOCK_DB_NAME))?, }) @@ -215,7 +216,7 @@ impl MintConfigStore { DatabaseFlags::empty(), )?; env.create_db( - Some(BLOCK_INDEX_BY_MINT_CONFIG_TX_NONCE_DB_NAME), + Some(BLOCK_INDEX_BY_MINT_CONFIG_TX_NONCE_AND_TOKEN_ID_DB_NAME), DatabaseFlags::empty(), )?; env.create_db( @@ -251,41 +252,54 @@ impl MintConfigStore { for validated_mint_config_tx in validated_mint_config_txs { let mint_config_tx = &validated_mint_config_tx.mint_config_tx; - // All mint configurations must have the same token id. - if mint_config_tx - .prefix - .configs - .iter() - .any(|mint_config| mint_config.token_id != mint_config_tx.prefix.token_id) - { - return Err(Error::InvalidMintConfig( - "All mint configurations must have the same token id".to_string(), - )); - } + MintConfigStore::check_mint_config(mint_config_tx)?; - // MintConfigs -> ActiveMintConfigs - let active_mint_configs = ActiveMintConfigs::from(mint_config_tx); - - // Store in database - db_transaction.put( - self.block_index_by_mint_config_tx_nonce, - &mint_config_tx.prefix.nonce, - &block_index_bytes, - // ensures we do not overwrite a nonce that was already used - WriteFlags::NO_OVERWRITE, + self.write_block_index_by_nonce_and_token_id( + mint_config_tx, + db_transaction, + block_index_bytes, )?; - db_transaction.put( - self.active_mint_configs_by_token_id, - &u64_to_key_bytes(mint_config_tx.prefix.token_id), - &encode(&active_mint_configs), - WriteFlags::empty(), - )?; + self.write_active_mint_configs_by_token_id(mint_config_tx, db_transaction)?; } Ok(()) } + pub fn write_block_index_by_nonce_and_token_id( + &self, + mint_config_tx: &MintConfigTx, + db_transaction: &mut RwTransaction, + block_index_bytes: [u8; 8], + ) -> Result<(), Error> { + let mut combined_nonce_and_token_id = mint_config_tx.prefix.nonce.clone(); + combined_nonce_and_token_id + .extend_from_slice(&u64_to_key_bytes(mint_config_tx.prefix.token_id)); + db_transaction.put( + self.block_index_by_mint_config_tx_nonce_and_token_id, + &combined_nonce_and_token_id, + &block_index_bytes, + // ensures we do not overwrite a nonce that was already used + WriteFlags::NO_OVERWRITE, + )?; + Ok(()) + } + + fn write_active_mint_configs_by_token_id( + &self, + mint_config_tx: &MintConfigTx, + db_transaction: &mut RwTransaction, + ) -> Result<(), Error> { + let active_mint_configs = ActiveMintConfigs::from(mint_config_tx); + db_transaction.put( + self.active_mint_configs_by_token_id, + &u64_to_key_bytes(mint_config_tx.prefix.token_id), + &encode(&active_mint_configs), + WriteFlags::empty(), + )?; + Ok(()) + } + /// Get ValidatedMintConfigTxs in a given block. pub fn get_validated_mint_config_txs_by_block_index( &self, @@ -411,15 +425,34 @@ impl MintConfigStore { pub fn check_mint_config_tx_nonce( &self, + token_id: u64, nonce: &[u8], db_transaction: &impl Transaction, ) -> Result, Error> { - match db_transaction.get(self.block_index_by_mint_config_tx_nonce, &nonce) { + let combined_nonce_and_token_id = [nonce, &u64_to_key_bytes(token_id)].concat(); + match db_transaction.get( + self.block_index_by_mint_config_tx_nonce_and_token_id, + &combined_nonce_and_token_id, + ) { Ok(db_bytes) => Ok(Some(key_bytes_to_u64(db_bytes))), Err(lmdb::Error::NotFound) => Ok(None), Err(e) => Err(Error::Lmdb(e)), } } + + pub fn check_mint_config(mint_config_tx: &MintConfigTx) -> Result<(), Error> { + if mint_config_tx + .prefix + .configs + .iter() + .any(|mint_config| mint_config.token_id != mint_config_tx.prefix.token_id) + { + return Err(Error::InvalidMintConfig( + "All mint configurations must have the same token id".to_string(), + )); + } + Ok(()) + } } #[cfg(test)] @@ -523,7 +556,8 @@ pub mod tests { let mut rng: StdRng = SeedableRng::from_seed([1u8; 32]); let test_tx_1 = create_mint_config_tx(TokenId::from(1), &mut rng); - let mut test_tx_2 = create_mint_config_tx(TokenId::from(2), &mut rng); + let mut test_tx_2 = create_mint_config_tx(TokenId::from(1), &mut rng); + let mut test_tx_tkn_2 = create_mint_config_tx(TokenId::from(2), &mut rng); { let mut db_transaction = env.begin_rw_txn().unwrap(); @@ -537,6 +571,7 @@ pub mod tests { db_transaction.commit().unwrap(); } + // Retrying the same transaction should fail { let mut db_transaction = env.begin_rw_txn().unwrap(); assert_eq!( @@ -549,14 +584,14 @@ pub mod tests { ); db_transaction.commit().unwrap(); } - + // Retrying with the same nonce for the same token_id should fail. test_tx_2.prefix.nonce = test_tx_1.prefix.nonce.clone(); { let mut db_transaction = env.begin_rw_txn().unwrap(); assert_eq!( mint_config_store.write_validated_mint_config_txs( 2, - &[to_validated(&test_tx_1)], + &[to_validated(&test_tx_2)], &mut db_transaction ), Err(Error::Lmdb(lmdb::Error::KeyExist)) @@ -564,13 +599,27 @@ pub mod tests { db_transaction.commit().unwrap(); } + // Using the same nonce with different token_id should succeed. + test_tx_tkn_2.prefix.nonce = test_tx_1.prefix.nonce; + { + let mut db_transaction = env.begin_rw_txn().unwrap(); + mint_config_store + .write_validated_mint_config_txs( + 3, + &[to_validated(&test_tx_tkn_2)], + &mut db_transaction, + ) + .unwrap(); + db_transaction.commit().unwrap(); + } + // Sanity - change the nonce, we should then succeed. test_tx_2.prefix.nonce[0] = !test_tx_2.prefix.nonce[0]; { let mut db_transaction = env.begin_rw_txn().unwrap(); mint_config_store .write_validated_mint_config_txs( - 3, + 4, &[to_validated(&test_tx_2)], &mut db_transaction, ) @@ -1327,8 +1376,9 @@ pub mod tests { let token_id2 = TokenId::from(2); let test_tx_1 = create_mint_config_tx(token_id1, &mut rng); - let test_tx_2 = create_mint_config_tx(token_id2, &mut rng); + let mut test_tx_2 = create_mint_config_tx(token_id2, &mut rng); let test_tx_3 = create_mint_config_tx(token_id2, &mut rng); + test_tx_2.prefix.nonce = test_tx_1.prefix.nonce.clone(); { let mut db_transaction = env.begin_rw_txn().unwrap(); @@ -1346,19 +1396,26 @@ pub mod tests { let db_transaction = env.begin_ro_txn().unwrap(); assert_eq!( - mint_config_store - .check_mint_config_tx_nonce(&test_tx_1.prefix.nonce, &db_transaction), + mint_config_store.check_mint_config_tx_nonce( + *token_id1, + &test_tx_1.prefix.nonce, + &db_transaction + ), Ok(Some(0)), ); assert_eq!( - mint_config_store - .check_mint_config_tx_nonce(&test_tx_2.prefix.nonce, &db_transaction), + mint_config_store.check_mint_config_tx_nonce( + *token_id2, + &test_tx_2.prefix.nonce, + &db_transaction + ), Ok(Some(0)), ); assert_eq!( mint_config_store.check_mint_config_tx_nonce( + *token_id2, &test_tx_2.prefix.nonce[0..test_tx_2.prefix.nonce.len() - 1], &db_transaction ), @@ -1366,13 +1423,20 @@ pub mod tests { ); assert_eq!( - mint_config_store - .check_mint_config_tx_nonce(&test_tx_3.prefix.nonce, &db_transaction), + mint_config_store.check_mint_config_tx_nonce( + *token_id2, + &test_tx_3.prefix.nonce, + &db_transaction + ), Ok(None), ); assert_eq!( - mint_config_store.check_mint_config_tx_nonce(&[1, 2, 3], &db_transaction), + mint_config_store.check_mint_config_tx_nonce( + *token_id1, + &[1, 2, 3], + &db_transaction + ), Ok(None), ); } @@ -1393,20 +1457,29 @@ pub mod tests { let db_transaction = env.begin_ro_txn().unwrap(); assert_eq!( - mint_config_store - .check_mint_config_tx_nonce(&test_tx_1.prefix.nonce, &db_transaction), + mint_config_store.check_mint_config_tx_nonce( + *token_id1, + &test_tx_1.prefix.nonce, + &db_transaction + ), Ok(Some(0)), ); assert_eq!( - mint_config_store - .check_mint_config_tx_nonce(&test_tx_2.prefix.nonce, &db_transaction), + mint_config_store.check_mint_config_tx_nonce( + *token_id2, + &test_tx_2.prefix.nonce, + &db_transaction + ), Ok(Some(0)), ); assert_eq!( - mint_config_store - .check_mint_config_tx_nonce(&test_tx_3.prefix.nonce, &db_transaction), + mint_config_store.check_mint_config_tx_nonce( + *token_id2, + &test_tx_3.prefix.nonce, + &db_transaction + ), Ok(Some(1)), ); } diff --git a/ledger/db/src/mint_tx_store.rs b/ledger/db/src/mint_tx_store.rs index d605a47bf2..54d92a5a49 100644 --- a/ledger/db/src/mint_tx_store.rs +++ b/ledger/db/src/mint_tx_store.rs @@ -14,7 +14,8 @@ use mc_util_serial::{decode, encode, Message}; // LMDB Database names. pub const MINT_TXS_BY_BLOCK_DB_NAME: &str = "mint_tx_store:set_txs_by_block"; -pub const BLOCK_INDEX_BY_MINT_TX_NONCE_DB_NAME: &str = "mint_tx_store:block_index_by_mint_tx_nonce"; +pub const BLOCK_INDEX_BY_MINT_TX_NONCE_AND_TOKEN_ID_DB_NAME: &str = + "mint_tx_store:block_index_by_mint_tx_nonce_and_token_id"; /// A list of mint-txs that can be prost-encoded. This is needed since that's /// the only way to encode a Vec. @@ -30,7 +31,7 @@ pub struct MintTxStore { mint_txs_by_block: Database, /// block index by MintTx nonce. - block_index_by_mint_tx_nonce: Database, + block_index_by_mint_tx_nonce_and_token_id: Database, } impl MintTxStore { @@ -38,8 +39,8 @@ impl MintTxStore { pub fn new(env: &Environment) -> Result { Ok(MintTxStore { mint_txs_by_block: env.open_db(Some(MINT_TXS_BY_BLOCK_DB_NAME))?, - block_index_by_mint_tx_nonce: env - .open_db(Some(BLOCK_INDEX_BY_MINT_TX_NONCE_DB_NAME))?, + block_index_by_mint_tx_nonce_and_token_id: env + .open_db(Some(BLOCK_INDEX_BY_MINT_TX_NONCE_AND_TOKEN_ID_DB_NAME))?, }) } @@ -47,7 +48,7 @@ impl MintTxStore { pub fn create(env: &Environment) -> Result<(), Error> { env.create_db(Some(MINT_TXS_BY_BLOCK_DB_NAME), DatabaseFlags::empty())?; env.create_db( - Some(BLOCK_INDEX_BY_MINT_TX_NONCE_DB_NAME), + Some(BLOCK_INDEX_BY_MINT_TX_NONCE_AND_TOKEN_ID_DB_NAME), DatabaseFlags::empty(), )?; Ok(()) @@ -104,26 +105,45 @@ impl MintTxStore { new_total_minted, db_transaction, )?; - - // Ensure nonce uniqueness - db_transaction.put( - self.block_index_by_mint_tx_nonce, - &mint_tx.prefix.nonce, - &block_index_bytes, - // do not overwrite a nonce that was already used - WriteFlags::NO_OVERWRITE, + self.write_block_index_by_mint_tx_nonce_and_token_id( + mint_tx, + db_transaction, + block_index_bytes, )?; } Ok(()) } + pub fn write_block_index_by_mint_tx_nonce_and_token_id( + &self, + mint_tx: &MintTx, + db_transaction: &mut RwTransaction, + block_index_bytes: [u8; 8], + ) -> Result<(), Error> { + let mut combined_nonce_and_token_id = mint_tx.prefix.nonce.clone(); + combined_nonce_and_token_id.extend_from_slice(&u64_to_key_bytes(mint_tx.prefix.token_id)); + db_transaction.put( + self.block_index_by_mint_tx_nonce_and_token_id, + &combined_nonce_and_token_id, + &block_index_bytes, + // do not overwrite a nonce that was already used + WriteFlags::NO_OVERWRITE, + )?; + Ok(()) + } + pub fn check_mint_tx_nonce( &self, + token_id: u64, nonce: &[u8], db_transaction: &impl Transaction, ) -> Result, Error> { - match db_transaction.get(self.block_index_by_mint_tx_nonce, &nonce) { + let combined_nonce_and_token_id = [nonce, &u64_to_key_bytes(token_id)].concat(); + match db_transaction.get( + self.block_index_by_mint_tx_nonce_and_token_id, + &combined_nonce_and_token_id, + ) { Ok(db_bytes) => Ok(Some(key_bytes_to_u64(db_bytes))), Err(lmdb::Error::NotFound) => Ok(None), Err(e) => Err(Error::Lmdb(e)), @@ -405,6 +425,75 @@ mod tests { db_txn.commit().unwrap(); } + #[test] + fn write_mint_txs_duplicate_nonce() { + let (mint_config_store, mint_tx_store, env) = init_test_stores(); + let mut rng: StdRng = SeedableRng::from_seed([1u8; 32]); + let token_id1 = TokenId::from(1); + let token_id2 = TokenId::from(2); + + // Generate and store a mint configurations. + let (mint_config_tx1, signers1) = create_mint_config_tx_and_signers(token_id1, &mut rng); + let (mint_config_tx2, signers2) = create_mint_config_tx_and_signers(token_id2, &mut rng); + + let mut db_txn = env.begin_rw_txn().unwrap(); + mint_config_store + .write_validated_mint_config_txs( + 0, + &[ + to_validated(&mint_config_tx1), + to_validated(&mint_config_tx2), + ], + &mut db_txn, + ) + .unwrap(); + db_txn.commit().unwrap(); + + // Generate a mint tx that mints 1 token on block 0 + rng = SeedableRng::from_seed([1u8; 32]); + let mint_tx1 = create_mint_tx(token_id1, &signers1, 1, &mut rng); + + let mut db_txn = env.begin_rw_txn().unwrap(); + mint_tx_store + .write_mint_txs(0, &[mint_tx1.clone()], &mint_config_store, &mut db_txn) + .unwrap(); + db_txn.commit().unwrap(); + + // Trying again on block 0 should fail. + let mint_tx2 = create_mint_tx(token_id1, &signers1, 1, &mut rng); + let mut db_txn = env.begin_rw_txn().unwrap(); + assert_eq!( + mint_tx_store.write_mint_txs(0, &[mint_tx2.clone()], &mint_config_store, &mut db_txn), + Err(Error::Lmdb(lmdb::Error::KeyExist)) + ); + drop(db_txn); + + // But will succeed on block 1. + let mut db_txn = env.begin_rw_txn().unwrap(); + mint_tx_store + .write_mint_txs(1, &[mint_tx2], &mint_config_store, &mut db_txn) + .unwrap(); + db_txn.commit().unwrap(); + + // Trying with the same nonce on the same token should fail. + let mut db_txn = env.begin_rw_txn().unwrap(); + assert_eq!( + mint_tx_store.write_mint_txs(2, &[mint_tx1], &mint_config_store, &mut db_txn), + Err(Error::Lmdb(lmdb::Error::KeyExist)) + ); + drop(db_txn); + + // Generate similar tx as tx1 that have the same nonces for token2. + rng = SeedableRng::from_seed([1u8; 32]); + let mint_tx1_tkn2 = create_mint_tx(token_id2, &signers2, 1, &mut rng); + + //Trying with the same nonce on a different token should succeed. + let mut db_txn = env.begin_rw_txn().unwrap(); + mint_tx_store + .write_mint_txs(2, &[mint_tx1_tkn2], &mint_config_store, &mut db_txn) + .unwrap(); + db_txn.commit().unwrap(); + } #[test] fn write_mint_txs_works_when_some_signers_are_unknown() { let (mint_config_store, mint_tx_store, env) = init_test_stores(); @@ -598,26 +687,27 @@ mod tests { let db_txn = env.begin_ro_txn().unwrap(); assert_eq!( - mint_tx_store.check_mint_tx_nonce(&mint_tx1.prefix.nonce, &db_txn), + mint_tx_store.check_mint_tx_nonce(*token_id1, &mint_tx1.prefix.nonce, &db_txn), Ok(Some(0)) ); assert_eq!( - mint_tx_store.check_mint_tx_nonce(&mint_tx2.prefix.nonce, &db_txn), + mint_tx_store.check_mint_tx_nonce(*token_id1, &mint_tx2.prefix.nonce, &db_txn), Ok(Some(0)) ); assert_eq!( - mint_tx_store.check_mint_tx_nonce(&mint_tx3.prefix.nonce, &db_txn), + mint_tx_store.check_mint_tx_nonce(*token_id1, &mint_tx3.prefix.nonce, &db_txn), Ok(None) ); assert_eq!( mint_tx_store.check_mint_tx_nonce( + *token_id1, &mint_tx1.prefix.nonce[..mint_tx1.prefix.nonce.len() - 2], &db_txn ), Ok(None) ); assert_eq!( - mint_tx_store.check_mint_tx_nonce(&[1, 2, 3], &db_txn), + mint_tx_store.check_mint_tx_nonce(*token_id1, &[1, 2, 3], &db_txn), Ok(None) ); drop(db_txn); @@ -630,15 +720,15 @@ mod tests { let db_txn = env.begin_ro_txn().unwrap(); assert_eq!( - mint_tx_store.check_mint_tx_nonce(&mint_tx1.prefix.nonce, &db_txn), + mint_tx_store.check_mint_tx_nonce(*token_id1, &mint_tx1.prefix.nonce, &db_txn), Ok(Some(0)) ); assert_eq!( - mint_tx_store.check_mint_tx_nonce(&mint_tx2.prefix.nonce, &db_txn), + mint_tx_store.check_mint_tx_nonce(*token_id1, &mint_tx2.prefix.nonce, &db_txn), Ok(Some(0)) ); assert_eq!( - mint_tx_store.check_mint_tx_nonce(&mint_tx3.prefix.nonce, &db_txn), + mint_tx_store.check_mint_tx_nonce(*token_id1, &mint_tx3.prefix.nonce, &db_txn), Ok(Some(1)) ); } diff --git a/ledger/db/src/test_utils/mock_ledger.rs b/ledger/db/src/test_utils/mock_ledger.rs index f0b910252f..7cac131112 100644 --- a/ledger/db/src/test_utils/mock_ledger.rs +++ b/ledger/db/src/test_utils/mock_ledger.rs @@ -205,11 +205,19 @@ impl Ledger for MockLedger { unimplemented!() } - fn check_mint_config_tx_nonce(&self, _nonce: &[u8]) -> Result, Error> { + fn check_mint_config_tx_nonce( + &self, + _token_id: u64, + _nonce: &[u8], + ) -> Result, Error> { unimplemented!() } - fn check_mint_tx_nonce(&self, _nonce: &[u8]) -> Result, Error> { + fn check_mint_tx_nonce( + &self, + _token_id: u64, + _nonce: &[u8], + ) -> Result, Error> { unimplemented!() } diff --git a/ledger/migration/src/lib.rs b/ledger/migration/src/lib.rs index 1d31dfce52..7c202b444a 100644 --- a/ledger/migration/src/lib.rs +++ b/ledger/migration/src/lib.rs @@ -110,7 +110,29 @@ pub fn migrate(ledger_db_path: impl AsRef, logger: &Logger) { ); db_txn.commit().expect("Failed committing transaction"); } + // Version 2022_09_21 came after 2022_02_22 and introduced nonces unique to token_ids. + Err(MetadataStoreError::VersionIncompatible(2022_02_22, _)) => { + log::info!( + logger, + "Ledger db migrating from version 2022_02_22 to 2022_09_21..." + ); + MintConfigStore::create(&env).expect("Failed creating MintConfigStore"); + MintTxStore::create(&env).expect("Failed creating MintTxStore"); + + update_mint_stores_to_store_nonce_with_token_id(&env, logger) + .expect("Failed backfilling nonces"); + let mut db_txn = env.begin_rw_txn().expect("Failed starting rw transaction"); + metadata_store + .set_version(&mut db_txn, 2022_09_21) + .expect("Failed setting metadata version"); + log::info!( + logger, + "Ledger db migration complete, now at version: {:?}", + metadata_store.get_version(&db_txn), + ); + db_txn.commit().expect("Failed committing transaction"); + } // Don't know how to migrate. Err(err) => { panic!("Error while migrating: {:?}", err); @@ -254,3 +276,61 @@ fn backfill_empty_mint_stores(env: &Environment, logger: &Logger) -> Result<(), } Ok(db_txn.commit()?) } + +/// A utility function for converting nonces stored in mint_config_store and +/// mint_tx_store to include token_id. +fn update_mint_stores_to_store_nonce_with_token_id( + env: &Environment, + logger: &Logger, +) -> Result<(), Error> { + // Open pre-existing databases that has data we need. + let mint_config_store = MintConfigStore::new(env)?; + let mint_tx_store = MintTxStore::new(env)?; + let counts_db = env.open_db(Some(COUNTS_DB_NAME))?; + let mut db_txn = env.begin_rw_txn()?; + + let num_blocks = key_bytes_to_u64(db_txn.get(counts_db, &NUM_BLOCKS_KEY)?); + log::info!( + logger, + "Mint config store has {:?}", + mint_config_store.get_active_mint_configs_map(&db_txn)?; + ); + + let mut percents: u64 = 0; + for block_index in 0..num_blocks { + let block_index_bytes = u64_to_key_bytes(block_index); + let validated_mint_configs = + mint_config_store.get_validated_mint_config_txs_by_block_index(block_index, &db_txn)?; + for validated_mint_config_tx in validated_mint_configs { + let mint_config_tx = &validated_mint_config_tx.mint_config_tx; + + MintConfigStore::check_mint_config(mint_config_tx)?; + + mint_config_store.write_block_index_by_nonce_and_token_id( + mint_config_tx, + &mut db_txn, + block_index_bytes, + )?; + } + let mint_txs = mint_tx_store.get_mint_txs_by_block_index(block_index, &db_txn)?; + for mint_tx in mint_txs { + mint_tx_store.write_block_index_by_mint_tx_nonce_and_token_id( + &mint_tx, + &mut db_txn, + block_index_bytes, + )?; + } + + // Throttled logging. + let new_percents = block_index * 100 / num_blocks; + if new_percents != percents { + percents = new_percents; + log::info!( + logger, + "Backfilling dropped nonce mint stores: {}% complete", + percents + ); + } + } + Ok(db_txn.commit()?) +} diff --git a/mint-auditor/tests/compile_proto.sh b/mint-auditor/tests/compile_proto.sh index 9fba2678d1..37d880bb35 100644 --- a/mint-auditor/tests/compile_proto.sh +++ b/mint-auditor/tests/compile_proto.sh @@ -15,5 +15,6 @@ pip3 install grpcio grpcio-tools python3 -m grpc_tools.protoc -I$MC_API --python_out=. $MC_API/external.proto python3 -m grpc_tools.protoc -I$MC_API --python_out=. $MC_API/blockchain.proto +python3 -m grpc_tools.protoc -I$MC_API -I$CONSENSUS_API --python_out=. $CONSENSUS_API/consensus_common.proto python3 -m grpc_tools.protoc -I$MCD_API -I$CONSENSUS_API -I$MC_API --python_out=. --grpc_python_out=. $MCD_API/mobilecoind_api.proto python3 -m grpc_tools.protoc -I$MINT_AUDITOR_API --python_out=. --grpc_python_out=. $MINT_AUDITOR_API/mint_auditor.proto From 28fcf8455e90bd70df32d20d7713a9ac85e5e618 Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 7 Oct 2022 12:19:28 -0700 Subject: [PATCH 59/77] Make telemetry opt-in (#2193) (#2676) Make telemetry opt-in, with env.MC_TELEMETRY set to 1 or true Co-authored-by: Remoun Metyas --- mobilecoind/src/bin/main.rs | 12 ++------ util/telemetry/src/jaeger.rs | 54 ++++++++++++++++++++++++++++++++++++ util/telemetry/src/lib.rs | 48 +++----------------------------- 3 files changed, 60 insertions(+), 54 deletions(-) create mode 100644 util/telemetry/src/jaeger.rs diff --git a/mobilecoind/src/bin/main.rs b/mobilecoind/src/bin/main.rs index 346d8e4e29..57375a44d0 100644 --- a/mobilecoind/src/bin/main.rs +++ b/mobilecoind/src/bin/main.rs @@ -28,16 +28,8 @@ fn main() { let _sentry_guard = mc_common::sentry::init(); let (logger, _global_logger_guard) = create_app_logger(o!()); - // Telemetry is disabled if MC_TELEMETRY is set to "0" - let telemetry_enabled = !std::env::var("MC_TELEMETRY") - .map(|val| val == "0") - .unwrap_or(false); - - let _tracer = if telemetry_enabled { - Some(setup_default_tracer(env!("CARGO_PKG_NAME")).expect("Failed setting telemetry tracer")) - } else { - None - }; + let _tracer = + setup_default_tracer(env!("CARGO_PKG_NAME")).expect("Failed setting telemetry tracer"); let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); diff --git a/util/telemetry/src/jaeger.rs b/util/telemetry/src/jaeger.rs new file mode 100644 index 0000000000..31d6f7a0ea --- /dev/null +++ b/util/telemetry/src/jaeger.rs @@ -0,0 +1,54 @@ +use displaydoc::Display; +use opentelemetry::{sdk, trace::TraceError, KeyValue}; + +#[derive(Debug, Display)] +pub enum Error { + /// Trace error: {0} + Trace(TraceError), + + /// Get hostname error: {0} + GetHostname(std::io::Error), + + /// Failed converting hostname to string + HostnameToString, +} + +/// Set up a default tracer with no additional tags. +/// Telemetry is enabled iff env.MC_TELEMETRY is set to "1" or "true". +pub fn setup_default_tracer(service_name: &str) -> Result, Error> { + setup_default_tracer_with_tags(service_name, &[]) +} + +/// Set up a default tracer with the given extra tags. +/// Telemetry is enabled iff env.MC_TELEMETRY is set to "1" or "true". +pub fn setup_default_tracer_with_tags( + service_name: &str, + extra_tags: &[(&'static str, String)], +) -> Result, Error> { + let telemetry_enabled = std::env::var("MC_TELEMETRY") + .map(|val| val == "1" || val.to_lowercase() == "true") + .unwrap_or(false); + if !telemetry_enabled { + return Ok(None); + } + + let local_hostname = hostname::get().map_err(Error::GetHostname)?; + + let mut tags = vec![KeyValue::new( + "hostname", + local_hostname + .to_str() + .ok_or(Error::HostnameToString)? + .to_owned(), + )]; + for (key, value) in extra_tags.iter() { + tags.push(KeyValue::new(*key, value.clone())); + } + + opentelemetry_jaeger::new_pipeline() + .with_service_name(service_name) + .with_trace_config(sdk::trace::Config::default().with_resource(sdk::Resource::new(tags))) + .install_simple() + .map_err(Error::Trace) + .map(Some) +} diff --git a/util/telemetry/src/lib.rs b/util/telemetry/src/lib.rs index c895673d00..24a9914499 100644 --- a/util/telemetry/src/lib.rs +++ b/util/telemetry/src/lib.rs @@ -83,48 +83,8 @@ pub fn start_block_span( block_span_builder(tracer, span_name, block_index).start(tracer) } -cfg_if::cfg_if! { - if #[cfg(feature = "jaeger")] { - use displaydoc::Display; - use opentelemetry::{trace::TraceError, KeyValue, sdk}; +#[cfg(feature = "jaeger")] +mod jaeger; - #[derive(Debug, Display)] - pub enum Error { - /// Trace error: {0} - Trace(TraceError), - - /// Get hostname error: {0} - GetHostname(std::io::Error), - - /// Failed converting hostname to string - HostnameToString, - } - - pub fn setup_default_tracer_with_tags(service_name: &str, extra_tags: &[(&'static str, String)]) -> Result { - let local_hostname = hostname::get().map_err(Error::GetHostname)?; - - let mut tags = vec![KeyValue::new( - "hostname", - local_hostname - .to_str() - .ok_or(Error::HostnameToString)? - .to_owned(), - )]; - for (key, value) in extra_tags.iter() { - tags.push(KeyValue::new(*key, value.clone())); - } - - opentelemetry_jaeger::new_pipeline() - .with_service_name(service_name) - .with_trace_config( - sdk::trace::Config::default() - .with_resource(sdk::Resource::new(tags))) - .install_simple() - .map_err(Error::Trace) - } - - pub fn setup_default_tracer(service_name: &str) -> Result { - setup_default_tracer_with_tags(service_name, &[]) - } - } -} +#[cfg(feature = "jaeger")] +pub use jaeger::{setup_default_tracer, setup_default_tracer_with_tags, Error}; From 305fbc8c7c8964a284db89ddcc5fd35f2e83efdd Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 10 Oct 2022 12:05:15 -0700 Subject: [PATCH 60/77] Cherry-pick version bump (#2648) (#2679) * Make telemetry opt-in (#2193) Make telemetry opt-in, with env.MC_TELEMETRY set to 1 or true * Bump all crate versions to 2.1.0-pre0 (#2648) * Update missed versions * Update Cargo.lock Co-authored-by: Remoun Metyas --- Cargo.lock | 332 +++++++++--------- account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- .../android-bindings/publish.gradle | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- common/Cargo.toml | 2 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 ++--- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 +++--- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/report/Cargo.toml | 2 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 +++--- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/resolver/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 +++--- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- go-grpc-gateway/testing/Cargo.toml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 3 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 2 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/cli/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- wasm-test/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 182 files changed, 542 insertions(+), 541 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a5b8832e1..e33e46f35b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1574,7 +1574,7 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "go-grpc-gateway-testing" -version = "1.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2027,7 +2027,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "cbindgen", @@ -2214,7 +2214,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "criterion", "curve25519-dalek", @@ -2242,7 +2242,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2258,7 +2258,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -2273,7 +2273,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "anyhow", @@ -2312,7 +2312,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "bs58", "cargo-emit", @@ -2348,7 +2348,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -2391,7 +2391,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "bincode", @@ -2423,7 +2423,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2436,7 +2436,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2456,7 +2456,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -2467,7 +2467,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2477,7 +2477,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2502,7 +2502,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "backtrace", "binascii", @@ -2539,7 +2539,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "cookie", @@ -2568,7 +2568,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2579,7 +2579,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -2600,7 +2600,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2625,7 +2625,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "hex", @@ -2646,7 +2646,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2654,7 +2654,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "hex", @@ -2690,7 +2690,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2703,7 +2703,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2725,7 +2725,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2754,7 +2754,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "crossbeam-channel", "maplit", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "mc-common", @@ -2789,7 +2789,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "chrono", @@ -2851,7 +2851,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -2876,7 +2876,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2896,7 +2896,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "digest 0.10.3", @@ -2912,7 +2912,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2925,7 +2925,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -2934,7 +2934,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2942,7 +2942,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2951,7 +2951,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2959,7 +2959,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "blake2", "digest 0.10.3", @@ -2968,7 +2968,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -3001,7 +3001,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "displaydoc", @@ -3015,7 +3015,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3029,7 +3029,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -3050,7 +3050,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3061,7 +3061,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3074,7 +3074,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3086,7 +3086,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3097,7 +3097,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3108,7 +3108,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -3140,7 +3140,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3172,7 +3172,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "cookie", @@ -3196,7 +3196,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3235,7 +3235,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "criterion", @@ -3270,7 +3270,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3287,7 +3287,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3295,7 +3295,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3328,7 +3328,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3341,7 +3341,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-report" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3353,7 +3353,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "dirs", @@ -3410,7 +3410,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3426,7 +3426,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "grpcio", @@ -3447,7 +3447,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3476,7 +3476,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3502,7 +3502,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3525,7 +3525,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3538,7 +3538,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3592,7 +3592,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3608,7 +3608,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -3637,14 +3637,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3655,7 +3655,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -3672,7 +3672,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "lazy_static", "mc-common", @@ -3680,7 +3680,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3718,7 +3718,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3732,7 +3732,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -3751,7 +3751,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-util-serial", "prost", @@ -3760,7 +3760,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "binascii", @@ -3784,7 +3784,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "grpcio", @@ -3801,7 +3801,7 @@ dependencies = [ [[package]] name = "mc-fog-report-resolver" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-account-keys", "mc-attest-verifier", @@ -3816,7 +3816,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3852,7 +3852,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3862,7 +3862,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3875,7 +3875,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3883,7 +3883,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3930,7 +3930,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3951,7 +3951,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3962,7 +3962,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3977,7 +3977,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "chrono", "clap 3.1.18", @@ -4010,7 +4010,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4041,7 +4041,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4072,7 +4072,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "crc", "displaydoc", @@ -4092,7 +4092,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-common", "mc-util-uri", @@ -4100,7 +4100,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "grpcio", "mc-attest-core", @@ -4120,7 +4120,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "criterion", @@ -4155,7 +4155,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4173,7 +4173,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4181,7 +4181,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4203,7 +4203,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4216,7 +4216,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4235,7 +4235,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -4258,7 +4258,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4308,7 +4308,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "lazy_static", @@ -4334,7 +4334,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "dirs", @@ -4356,7 +4356,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "mc-api", @@ -4367,7 +4367,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4380,7 +4380,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4411,7 +4411,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4444,7 +4444,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -4458,7 +4458,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4523,7 +4523,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -4542,7 +4542,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4617,7 +4617,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4649,7 +4649,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "grpcio", "hex", @@ -4672,7 +4672,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cc", "lazy_static", @@ -4682,7 +4682,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4690,7 +4690,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4699,7 +4699,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4707,7 +4707,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4716,21 +4716,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4741,7 +4741,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4757,7 +4757,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4767,18 +4767,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-urts" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-common", "mc-sgx-build", @@ -4789,7 +4789,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4801,7 +4801,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-account-keys", "mc-api", @@ -4811,7 +4811,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-util-test-vector", "serde", @@ -4820,7 +4820,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4835,7 +4835,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4857,7 +4857,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -4899,7 +4899,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4916,7 +4916,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4943,7 +4943,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -4952,7 +4952,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4968,7 +4968,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4976,7 +4976,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "json", @@ -4984,7 +4984,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -4995,7 +4995,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -5006,7 +5006,7 @@ dependencies = [ [[package]] name = "mc-util-cli" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "mc-util-build-info", @@ -5014,7 +5014,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "binascii", @@ -5026,18 +5026,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-util-from-random" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5056,7 +5056,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -5090,7 +5090,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -5101,7 +5101,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5112,11 +5112,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-util-keyfile" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -5144,7 +5144,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5154,7 +5154,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -5163,7 +5163,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5171,7 +5171,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "chrono", "grpcio", @@ -5184,7 +5184,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "itertools", "mc-sgx-css", @@ -5192,7 +5192,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "generic-array", "prost", @@ -5202,7 +5202,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5215,7 +5215,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "prost", "serde", @@ -5224,7 +5224,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5235,7 +5235,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "itertools", @@ -5249,7 +5249,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "serde", "serde_json", @@ -5257,7 +5257,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -5266,7 +5266,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "displaydoc", @@ -5284,7 +5284,7 @@ dependencies = [ [[package]] name = "mc-wasm-test" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "getrandom 0.2.6", "mc-account-keys", @@ -5299,7 +5299,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5343,7 +5343,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 3de64701df..0d44c562d5 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index ab5873d6b7..0058228d01 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index 1a9ceb5937..0fed019fa2 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index cb091fdedd..b76b1b0a0c 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/android-bindings/lib-wrapper/android-bindings/publish.gradle b/android-bindings/lib-wrapper/android-bindings/publish.gradle index c08f8f86a6..27c3b4f37e 100644 --- a/android-bindings/lib-wrapper/android-bindings/publish.gradle +++ b/android-bindings/lib-wrapper/android-bindings/publish.gradle @@ -1,6 +1,6 @@ apply plugin: 'maven-publish' -version '2.0.0' +version '2.1.0-pre0' group 'com.mobilecoin' Properties properties = new Properties() diff --git a/api/Cargo.toml b/api/Cargo.toml index bfad2571fa..dd2f553ce3 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index 5c36d80913..c999191341 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index b00c716a99..f83de84d37 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index 61592600fa..9bae066d9f 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index 31e9fad637..7dc2a49818 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index 6b27d45e77..d36c1a841d 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index fa47333b4c..50a66fd8bb 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index d9156cb4b8..cdbc191a0d 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index 8366237bad..9cfd72a27b 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/common/Cargo.toml b/common/Cargo.toml index 381584d058..0ffc88a556 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/Cargo.toml b/connection/Cargo.toml index be7ed1d7b8..27ee1ec6e7 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index 6ce1cd342e..19a7972465 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index 4fc7cb0145..d6a8dc11fb 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index 08c79c5822..6bcf8f98fa 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index e70e778965..43a2144478 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index 18589a0fbf..f29f3f4558 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index 225ed96e4f..40f3370824 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index 979da3641f..d6d3e68132 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index 41128fcc59..de6540e516 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index 310a74b676..3d3f2afa6f 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-build" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-enclave-id" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-transaction-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index 40eb3279a3..c2faddc959 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index 801f318c85..cc90147732 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index c85d6ce4f8..6c58a3be4a 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index 773d9984cc..472a6974ab 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index d0e0ff0497..1f65f09d24 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index 3a4f4dfd4d..a9da751ded 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index 20d45a9de5..323e1bfe43 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index 8a8b2baa4d..70e5d1b7c2 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index 0db97cf986..54da7b4b88 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index cfc7e1b078..5a52c06ff3 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index dce40ce870..6187dc041f 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index 49e71e48c4..0e08de8d06 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index c6f83267cc..2e78f2e5f1 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index ce647f8e3e..15e6ae38b1 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index 526c75a53d..0e9a2931fd 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index ee113f1ba0..936005b2ac 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index 97421ed53a..42b32842ce 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index 16ee519524..a46a2548b6 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index 30c8e318a5..611ff7f9ea 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index dea5231a1f..6c0049c46e 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 85d9a3239c..1a5c6bea12 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index 8b35fbee25..cf15e8a402 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index ac556945f0..df93097f57 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index 006d7b5a64..f61379719b 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index 52dbfeee3a..078db50d14 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index eb4ddca521..cd290e759e 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 6b27ca7a4d..9951b6fa33 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index b36e8fa94b..9589b0a3ed 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index 44aff5e423..bb8000ecef 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index aa9f4e2824..39d65ab502 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index 4beff10247..548c1aa167 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index 94c845c4fd..43931dd840 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 3ff0c4be1a..ecdd3f3a86 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-build" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-transaction-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index 4c467d759b..819e562feb 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/report/Cargo.toml b/fog/ingest/report/Cargo.toml index 25d802fed0..63734ae0ba 100644 --- a/fog/ingest/report/Cargo.toml +++ b/fog/ingest/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-report" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2021" diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index a40190b105..1650df7e8d 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index 771978e329..b330f6c5f0 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index 3c225487be..2eaaf281a8 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index 8c58368893..d56dd1847d 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index 5d5d3267c8..72a5967819 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index 0c23932430..332aa4711a 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index 704fc5579f..389d339c12 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index 6101ffe6c9..d4e148266e 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 43ef170c1f..5e72f9fc4b 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-build" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-transaction-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index bdd22a9d48..e1c296acd6 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index cc189df9c3..75674ec864 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index 56608d4407..95b927621c 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index 48c33a1f35..b756af0ffe 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index 75a0929ef8..6bbb73717b 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index 1c48150acf..51cbd7c350 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index 8b0e0245db..81afe83b24 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index eb02c2a78e..fd6a004f5c 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index f96f422a89..6fcea2d857 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index bdd4935133..538da2a2e5 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index 9e22a2fcb3..98b4f5d5a4 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index e8907fb34f..395954013b 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index cce62e8831..7881780be2 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index 020de3abff..bf74a21d49 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/resolver/Cargo.toml b/fog/report/resolver/Cargo.toml index f90b2518c0..4ea199b650 100644 --- a/fog/report/resolver/Cargo.toml +++ b/fog/report/resolver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-resolver" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2021" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index 386d4f8ef5..ffa3484c8a 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index bd5cb5d7d7..2e6be6f78a 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index e528262e2c..a569bd781f 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index b5c0e4b4fc..2e7d614ce6 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index fda740f475..e5a5bce8cc 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index 896accfe8d..56ba76c934 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index b94621e052..d031ad00f6 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index a0cecb6976..cf769db31e 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index 454f750bfb..5d49be62ba 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 320401a057..6cd267d771 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index 6b82965c62..3adceeefa7 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index a7c2ccfacb..317e59a9fa 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index 26f7aae546..b1e5dbcfc2 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index f43d69e020..5d72c29580 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index 21f9e9daa6..3fc84f90d4 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index a43ef15f4f..af14a37bb9 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index 3a901d43bf..0f7de79c25 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index 1b01547107..5bb71db5b4 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index 761f75ec65..9505276270 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index 30cbe12a28..a1b4114911 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-build" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "2.0.0" +version = "2.1.0-pre0" [[package]] name = "mc-transaction-core" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "2.0.0" +version = "2.1.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index d815127eec..33381264f4 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index 89e77204f8..d0be89198b 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index 86dc878757..89a808a2d9 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index 6eb0d3a83f..2684cc4966 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/go-grpc-gateway/testing/Cargo.toml b/go-grpc-gateway/testing/Cargo.toml index 6e2b324bba..ee674a462b 100644 --- a/go-grpc-gateway/testing/Cargo.toml +++ b/go-grpc-gateway/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "go-grpc-gateway-testing" -version = "1.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index 99efda1360..85c22b2674 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index 8b23c06940..f4ea4e20e4 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index 37facd622d..4340ec56e0 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index 911b0ade79..a5b05178ff 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index c4c0580cae..c500c71372 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index 863d206819..0afce9ab7a 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index abad94d6d9..251019fe0b 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index db3a49476a..91bb0997a1 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" @@ -19,3 +19,4 @@ mc-util-build-grpc = { path = "../../util/build/grpc" } mc-util-build-script = { path = "../../util/build/script" } cargo-emit = "0.2.1" + diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index 56ed769180..0c530558f3 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index 2ed447165a..0c4a6b50a7 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index 7340022995..bb54f141e0 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/peers/Cargo.toml b/peers/Cargo.toml index 0516593a68..7c1aa0e947 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index 5e32e419a5..9b17174529 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index cb43586f7a..b3147c270c 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index 3cffacf195..2b4f6d14f0 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index 98c1f4059b..e6d2f2b7f3 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index 5603080798..6d1ee25a86 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index 52b3d939c8..f9901fb823 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index f4b483608b..f149412e75 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index 540075000d..42c1222d87 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index 45791c3f14..dd3e2d17f2 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index ba68d02349..106dcd222a 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index 2e9e01a707..1f69f01112 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index cf9f12fde2..6f1ff0ad5f 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index 7650c1e425..4705fb38e1 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index 917939ec96..c81eaeec3d 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index 66dee833b3..bb8b98707d 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index d1c13baf1d..61d531d1d8 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index 13c350881e..e8a666cf55 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index 67ca8ea187..af8a475fc4 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index 315e662db5..65b2ac8890 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "2.0.0" +version = "2.1.0-pre0" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index 6b337ddfc0..40ab13e43b 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index 4ce4c1a241..8c5dc7b391 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index c70370dab2..a46740ff4d 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index f067a8f064..b13f8a5217 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index 94e5abf61a..1cd0a247c3 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index d2957ef308..8cfc827b8f 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index 9eaaabd4c7..744c1bcbff 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 621137dd62..80eb5e67c2 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index e1c33e7e12..7b683f1725 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index ec30c7af01..c2dd30f130 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index ac4af2acc7..96af6f5fcf 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index d435bcad81..2dffd452c5 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index e7a1b2b0cf..8ea9434efd 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index 144ca34e31..1d0c02ef61 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index 7d8e07a37d..541ea4d0ca 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/cli/Cargo.toml b/util/cli/Cargo.toml index 0d7792a283..7e08942728 100644 --- a/util/cli/Cargo.toml +++ b/util/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-cli" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index 56e260d27b..2e2ecce7e3 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index 06d658a17f..34cfa8fb68 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index e99aca3737..53b245dff7 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index a26a812d57..ca4d15d402 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index b38ef16842..fb69dae743 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index 7a3c0592f2..542c77a15f 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index d7625aecb4..afd4e843d4 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 6904b9625b..796c1d23f3 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index 567168c080..51b24989c0 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index efe1c35a23..097964a0ed 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index 253b5553b4..c2ebd03ffd 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index 85df47cd00..72b702774e 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index d6086a57f5..d011f19bd3 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index e649efdfb2..3b172ba2a9 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index 9457ddb95a..91fc3cc3f3 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index ed936d832f..071a0738b6 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index 6f9bf7057e..fbf2a4624c 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index c3c819eb3d..7bc4a99335 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index 3b107043d3..280f764344 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index defc3c1efb..3510f44542 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index b4d23e4edd..013c00a6c5 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index 7780893bd3..437d9af158 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/wasm-test/Cargo.toml b/wasm-test/Cargo.toml index dfcaec247a..fded2120a6 100644 --- a/wasm-test/Cargo.toml +++ b/wasm-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-wasm-test" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2021" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index 3fe1f0be2d..52c256f0dc 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index 897bcbf858..579e87732e 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "2.0.0" +version = "2.1.0-pre0" authors = ["MobileCoin"] edition = "2018" From 47b4030feb4a8f0abfc3a4e7a0f5bc54a6106c0a Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 11 Oct 2022 12:45:42 -0600 Subject: [PATCH 61/77] improve fog ingest logging when unique constraint is violated (#2682) this doesn't happen very often, but when it did happen in testnet, we couldn't figure out why very easily and went database spelunking. we still don't know why, and in the future we want these details logged. --- fog/sql_recovery_db/src/lib.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fog/sql_recovery_db/src/lib.rs b/fog/sql_recovery_db/src/lib.rs index 66bc4ec2bf..e86eb527ca 100644 --- a/fog/sql_recovery_db/src/lib.rs +++ b/fog/sql_recovery_db/src/lib.rs @@ -588,10 +588,13 @@ impl SqlRecoveryDb { // errors. Err(Error::Orm(diesel::result::Error::DatabaseError( diesel::result::DatabaseErrorKind::UniqueViolation, - _, - ))) => Ok(AddBlockDataStatus { - block_already_scanned_with_this_key: true, - }), + details, + ))) => { + log::info!(self.logger, "Unique constraint violated when adding block {} for ingest invocation id {}: {:?}", block.index, ingest_invocation_id, details); + Ok(AddBlockDataStatus { + block_already_scanned_with_this_key: true, + }) + } Err(err) => Err(err), } } From c788fe6a8e6690f1e3d5ecbed0c542e5b76004d8 Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 12 Oct 2022 15:23:17 -0700 Subject: [PATCH 62/77] Cherry-pick 2.1.x Changelog (#2678) * Make telemetry opt-in (#2193) Make telemetry opt-in, with env.MC_TELEMETRY set to 1 or true * Bump all crate versions to 2.1.0-pre0 (#2648) * Changelog for 2.1.0 (#2649) * Bump all crate versions to 2.1.0-pre0 * Unified formatting * Style fix * Add 2.1 changes. * Update CHANGELOG.md to not promise overlays for multi-value arguments. * Note that telemetry will be opt-in for 2.1. Co-authored-by: Remoun Metyas --- CHANGELOG.md | 204 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b392391818..149f8e7bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,36 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The crates in this repository do not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) at this time. +## Unreleased + +## [2.1.0] + +### Added + +- Add `Chain-ID` gRPC metadata ([MCIP #49](https://github.com/mobilecoinfoundation/mcips/pull/49)) to provide additional runtime disambiguation between clients and servers. +- Add a required `--chain-id` command-line arguments to consensus and fog servers. +- Add an optional `--chain-id` command-line argument to `mobilecoind`. +- Support using environment variables to set values for nearly all command-line arguments. +- Update CI deployments to use zerossl instead of letsencrypt. +- Add a `--hash-tx-file` subcommand to print the hash of a `mint-tx` or `mint-config-tx` file. +- Add the current block info (fee map, block version, etc.) to the response message for `mobilecoind_api.GetNetworkStatus`. +- Make Jaeger telemetry opt-in using `MC_TELEMETRY=1`. + +### Fixes + +- Update `mc-consensus-mint-client` to check that public addresses for minting targets do not have a configured fog server. +- Update to `android-bindings` and `libmobilecoin` RNG APIs to assist in idempotent transactions. + +### Security + +- TOB-MCCT-4: Make minting nonces unique per-token. + + ## [2.0.0] - 2022-07-25 ### Fixed @@ -22,7 +48,15 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem ### Changed -- Update CI deployments to use zerossl instead of letsencrypt +- Updated SGX to 2.16 + +### Rust Dependencies + +- Updated `rust-toolchain` version to newer nightly + - enables use of [Generic Associated Types](https://github.com/rust-lang/rust/issues/44265) and [static async fn in traits](https://github.com/rust-lang/rust/issues/91611) +- Replaced `datatest` with a custom `test_with_data` macro. +- Replace `structopt` with `clap`. +- Updated `grpcio` from 0.9 to 0.10. ## [1.2.1] - UNRELEASED @@ -65,13 +99,15 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem - mobilecoind will now exit on startup when a ledger migration is necessary, unless the new `--ledger-db-migrate` command line argument is used, in which case it will migrate automatically. This flag does not do anything if the Ledger DB does not exist. - Bump SGX versions to 2.16. ([#1101], [#2018]) - Increase the maximum tombstone block for transactions to `20,160` from `100`. +- Lock enclave no-debug mode when building for IAS production. +- Update Rust toolchain to `nightly-2021-07-21`. #### Python - Bump `ipython` from 7.8.0 to 7.16.3 ([#1333]) - Bump `protobuf` from 3.10.0 to 3.15.0 ([#1477]) -#### Rust +#### Rust Dependencies - Upgrade rust toolchain to `nightly-2022-04-29` ([#1613], [#1888]) - Replace `datatest` with a custom `test_with_data` attribute macro ([#1556]) @@ -549,111 +585,111 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem ### Changed - - Updated TOS. - - Update IP restriction handling in mobilecoind to match TOS. +- Updated TOS. +- Update IP restriction handling in mobilecoind to match TOS. ## [1.1.0] - 2021-06-08 ### Added - - Mnemonics-based Key Derivation - - Dynamic Fees [rfcs/#1](https://github.com/mobilecoinfoundation/rfcs/#1) - - `consensus-service` now takes `--minimum-fee=` to configure minimum fees (nodes with different fees cannot attest to each other). - - `mobilecoind`'s `GenerateOptimizationTxRequest` API to takes a user-supplied fee. - - Authenticated fog details in public addresses - - Admin gRPC for `mobilecoind`. - - `mc-slam` load generation utility. - - `mc-sgx-css-dump` SIGSTRUCT (CSS) debug utility. - - `mobilecoind` can send change to a designated subaddress. - - `mobilecoind` support for load balancing (via forked grpcio). - - `mobilecoind` encrypts account key at rest. - - `watcher` app to keep track of Attestation Verification Reports from live machines. +- Mnemonics-based Key Derivation +- Dynamic Fees [rfcs/#1](https://github.com/mobilecoinfoundation/rfcs/#1) + - `consensus-service` now takes `--minimum-fee=` to configure minimum fees (nodes with different fees cannot attest to each other). + - `mobilecoind`'s `GenerateOptimizationTxRequest` API to takes a user-supplied fee. +- Authenticated fog details in public addresses +- Admin gRPC for `mobilecoind`. +- `mc-slam` load generation utility. +- `mc-sgx-css-dump` SIGSTRUCT (CSS) debug utility. +- `mobilecoind` can send change to a designated subaddress. +- `mobilecoind` support for load balancing (via forked grpcio). +- `mobilecoind` encrypts account key at rest. +- `watcher` app to keep track of Attestation Verification Reports from live machines. ### Changed - - Bump ISV SVN for consensus enclave to 2 - - Reduce minimum fee from 10mMOB to 400uMOB - - Parallelize HTTP transaction fetcher - - Optionally seed RNGs for mock attestation signer from `MC_SEED` env. - - Bump rust version to `nightly-2021-03-25` - - Update SGX to 2.13.3. - - Use `AWS_REGION` instead of `?region=`. - - Make enclave errors (to clients/peers) result in `PERMISSION_DENIED` to force reattestation. - - Fog hints now use AES256-GCM +- Bump ISV SVN for consensus enclave to 2 +- Reduce minimum fee from 10mMOB to 400uMOB +- Parallelize HTTP transaction fetcher +- Optionally seed RNGs for mock attestation signer from `MC_SEED` env. +- Bump rust version to `nightly-2021-03-25` +- Update SGX to 2.13.3. +- Use `AWS_REGION` instead of `?region=`. +- Make enclave errors (to clients/peers) result in `PERMISSION_DENIED` to force reattestation. +- Fog hints now use AES256-GCM #### Rust Dependencies - - Update `anyhow` to 1.0.39 - - Update `arc-swap` to 0.4.8 - - Update `arrayvec` to 0.5.2 - - Update `backtrace` to 0.3.55 - - Update `base64` to 0.12.3 - - Update `bigint` to 4.4.3 - - Update `blake2` to 0.9.1 - - Update `cc` to 1.0.66 - - Update `cfg-if` to 1.0.0 - - Update `cookie` to 0.14.3 - - Update `crossbeam-channel` to 0.5.0 - - Update `curve25519-dalek` to 4.0.0-pre.0 - - Update `datatest` to 0.6.4 - - Update `displaydoc` to 0.2.0 - - Update `fs_extra` to 1.2.0 - - Update `futures` to 0.3.8 - - Update `hmac` to 0.10.1 - - Update `indicatif` to 0.15.0 - - Update `libc` to 1.0.80 - - Update `mockall` to 0.8.3 - - Update `once_cell` to 1.5.2 - - Update `pem` to 0.8.2 - - Update `proc-macro2` to 1.0.24 - - Update `proptest` to 0.10.1 - - Update `protobuf` to 2.22.1 - - Update `rand_core` to 0.6.2 - - Update `rand_hc` to 0.3.0 - - Update `rand` to 0.8.3 - - Update `reqwest` to 0.10.6 - - Update `retry` to 1.2.0 - - Update `rocket` to 0.4.6 - - Update `semver` to 0.11.0 - - Update `serde_json` to 1.0.60 - - Update `serde` to 1.0.118 - - Update `serial_test` to 0.5.0 - - Update `sha2` to 0.9.3 - - Update `slog-stdlog` to 4.1.0 - - Update `slog-term` to 2.6.0 - - Update `structopt` to 0.3.21 - - Update `syn` to 1.0.45 - - Update `tempfile` to 3.2.0 - - Update `thiserr` to 1.0.24 - - Update `toml` to 0.5.7 - - Update `unicode-normalization` to 1.1.17 - - Update `version_check` to 0.9.3 - - Update `x25519-dalek` to 1.1.0 - - Update `zeroize` to 1.2.0 +- Update `anyhow` to 1.0.39 +- Update `arc-swap` to 0.4.8 +- Update `arrayvec` to 0.5.2 +- Update `backtrace` to 0.3.55 +- Update `base64` to 0.12.3 +- Update `bigint` to 4.4.3 +- Update `blake2` to 0.9.1 +- Update `cc` to 1.0.66 +- Update `cfg-if` to 1.0.0 +- Update `cookie` to 0.14.3 +- Update `crossbeam-channel` to 0.5.0 +- Update `curve25519-dalek` to 4.0.0-pre.0 +- Update `datatest` to 0.6.4 +- Update `displaydoc` to 0.2.0 +- Update `fs_extra` to 1.2.0 +- Update `futures` to 0.3.8 +- Update `hmac` to 0.10.1 +- Update `indicatif` to 0.15.0 +- Update `libc` to 1.0.80 +- Update `mockall` to 0.8.3 +- Update `once_cell` to 1.5.2 +- Update `pem` to 0.8.2 +- Update `proc-macro2` to 1.0.24 +- Update `proptest` to 0.10.1 +- Update `protobuf` to 2.22.1 +- Update `rand_core` to 0.6.2 +- Update `rand_hc` to 0.3.0 +- Update `rand` to 0.8.3 +- Update `reqwest` to 0.10.6 +- Update `retry` to 1.2.0 +- Update `rocket` to 0.4.6 +- Update `semver` to 0.11.0 +- Update `serde_json` to 1.0.60 +- Update `serde` to 1.0.118 +- Update `serial_test` to 0.5.0 +- Update `sha2` to 0.9.3 +- Update `slog-stdlog` to 4.1.0 +- Update `slog-term` to 2.6.0 +- Update `structopt` to 0.3.21 +- Update `syn` to 1.0.45 +- Update `tempfile` to 3.2.0 +- Update `thiserr` to 1.0.24 +- Update `toml` to 0.5.7 +- Update `unicode-normalization` to 1.1.17 +- Update `version_check` to 0.9.3 +- Update `x25519-dalek` to 1.1.0 +- Update `zeroize` to 1.2.0 #### Upstream Forks - - Unfork `bulletproofs` to unreleased 2.0.0 from github - - Fork `grpcio` to a 0.6.0 fork that supports cookies - - Fork `aes-gcm` 0.6.0 to support constant-time decrypt results +- Unfork `bulletproofs` to unreleased 2.0.0 from github +- Fork `grpcio` to a 0.6.0 fork that supports cookies +- Fork `aes-gcm` 0.6.0 to support constant-time decrypt results #### Python Dependencies - - Update `jinja` to 2.11.3 - - Update `pygments` to 2.7.4 +- Update `jinja` to 2.11.3 +- Update `pygments` to 2.7.4 ### Fixed - - Remove unnecessary limits on consensus request concurrency - - Readme fixes (thanks to contributors @hiqua, @petertodd) - - Fix monitor ID instability in `mobilecoind`. - - Normalize fog URL in public addresses before lookup - - Unified rustfmt +- Remove unnecessary limits on consensus request concurrency +- Readme fixes (thanks to contributors @hiqua, @petertodd) +- Fix monitor ID instability in `mobilecoind`. +- Normalize fog URL in public addresses before lookup +- Unified rustfmt ### Security - - Make encryption/decryption success able to be used from within a larger constant-time context for `mc-crypto-box`. - - Stricter EPID Pseudonym length test. (IoActive MC-03) +- Make encryption/decryption success able to be used from within a larger constant-time context for `mc-crypto-box`. +- Stricter EPID Pseudonym length test. (IoActive MC-03) ## [1.0.0] - 2020-11-24 From c372ea0f9dfe176c90d84480a50a120a21c66a6c Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 13 Oct 2022 12:24:55 -0600 Subject: [PATCH 63/77] Make fog-view load blocks from postgres in batches (#2707) * Make fog-view load blocks from postgres in batches These batches have a size which is configurable as a command line parameter. * fixup tests * add unit test for new function * address eran and remoun comments in db_fetcher * change parameter to a usize * rename per request * Update fog/sql_recovery_db/src/lib.rs Co-authored-by: Remoun Metyas Co-authored-by: Remoun Metyas --- fog/recovery_db_iface/src/lib.rs | 20 +++ fog/sql_recovery_db/src/lib.rs | 190 +++++++++++++++++++++++++++ fog/view/server/src/config.rs | 6 + fog/view/server/src/db_fetcher.rs | 114 +++++++++------- fog/view/server/src/server.rs | 18 ++- fog/view/server/tests/smoke_tests.rs | 1 + 6 files changed, 299 insertions(+), 50 deletions(-) diff --git a/fog/recovery_db_iface/src/lib.rs b/fog/recovery_db_iface/src/lib.rs index dfe98360cb..4a0f87b79c 100644 --- a/fog/recovery_db_iface/src/lib.rs +++ b/fog/recovery_db_iface/src/lib.rs @@ -256,6 +256,26 @@ pub trait RecoveryDb { block_index: u64, ) -> Result>, Self::Error>; + /// Get ETxOutRecords for a given ingress key from a block, and subsequent + /// blocks, up to some limit. (This is like a batch call to + /// get_tx_outs_by_block_and_key_retriable with lookahead, and makes + /// sense if there is high network latency.) + /// + /// Arguments: + /// * ingress_key: The ingress key we need ETxOutRecords from + /// * block_index: The first block we need ETxOutRecords from + /// * block_count: How many subsequent blocks to also request data for. + /// + /// Returns: + /// * The sequence of ETxOutRecord's, from consequecutive blocks starting + /// from block_index. Empty if not even the block_index'th block exists. + fn get_tx_outs_by_block_range_and_key( + &self, + ingress_key: CompressedRistrettoPublic, + block_index: u64, + block_count: usize, + ) -> Result>, Self::Error>; + /// Get the invocation id that published this block with this key. /// /// Note: This is only used by TESTS right now, but it is important to be diff --git a/fog/sql_recovery_db/src/lib.rs b/fog/sql_recovery_db/src/lib.rs index e86eb527ca..c72deae7df 100644 --- a/fog/sql_recovery_db/src/lib.rs +++ b/fog/sql_recovery_db/src/lib.rs @@ -935,6 +935,78 @@ impl SqlRecoveryDb { } } + /// Get ETxOutRecords for a given ingress key from a block, and subsequent + /// blocks, up to some limit. (This is like a batch call to + /// get_tx_outs_by_block_and_key_retriable with lookahead, and makes + /// sense if there is high network latency.) + /// + /// Arguments: + /// * ingress_key: The ingress key we need ETxOutRecords from + /// * block_index: The first block we need ETxOutRecords from + /// * block_count: How many subsequent blocks to also request data for. + /// + /// Returns: + /// * The sequence of ETxOutRecord's, from consequecutive blocks starting + /// from block_index. Empty if not even the block_index'th block exists. + fn get_tx_outs_by_block_range_and_key_retriable( + &self, + ingress_key: CompressedRistrettoPublic, + block_index: u64, + block_count: usize, + ) -> Result>, Error> { + let conn = self.pool.get()?; + + // The idea is: + // Similar to get_tx_outs_by_block_and_key_retriable, but now + // * we have a range of admissible block indices + // * we order by the block number + // * we also select over the block number so that sql gives us the block number + // + // This ensures that we can detect any gaps in the data + let key_bytes: &[u8] = ingress_key.as_ref(); + let query = { + use schema::ingested_blocks::dsl; + dsl::ingested_blocks + .filter(dsl::ingress_public_key.eq(key_bytes)) + .filter(dsl::block_number.ge(block_index as i64)) + .limit(block_count as i64) + .select((dsl::block_number, dsl::proto_ingested_block_data)) + .order(dsl::block_number.asc()) + }; + + // We will get one row for each hit in the table we found + let rows: Vec<(i64, Vec)> = query.load::<(i64, Vec)>(&conn)?; + + if rows.len() > block_count { + log::warn!( + self.logger, + "When querying, more responses than expected: {} > {}", + rows.len(), + block_count + ); + } + + // We want to iterate over the rows we got, make sure there are no gaps in block + // indices, and decode the TxOut's and return them. If there are gaps, + // we log at warn level, and short-circuit out of this, returning only + // whatever we managed to get. That will discard data that we got from + // the DB and we will request it again later, but there is no reason for + // there to be gaps, that's not how the system works, so it isn't + // important to optimize for that case. + + let mut result = Vec::new(); + for (idx, (block_number, proto)) in rows.into_iter().enumerate() { + if block_index + idx as u64 == block_number as u64 { + let proto = ProtoIngestedBlockData::decode(&*proto)?; + result.push(proto.e_tx_out_records); + } else { + log::warn!(self.logger, "When querying for block index {} and up to {} blocks on, the {}'th response has block_number {} which is not expected. Gaps in the data?", block_index, block_count, idx, block_number); + break; + } + } + Ok(result) + } + /// Get iid that produced data for given ingress key and a given block /// index. fn get_invocation_id_by_block_and_key_retriable( @@ -1349,6 +1421,30 @@ impl RecoveryDb for SqlRecoveryDb { }) } + /// Get ETxOutRecords for a given ingress key from a block, and subsequent + /// blocks, up to some limit. (This is like a batch call to + /// get_tx_outs_by_block_and_key with lookahead, and makes sense if + /// there is high network latency.) + /// + /// Arguments: + /// * ingress_key: The ingress key we need ETxOutRecords from + /// * block_index: The first block we need ETxOutRecords from + /// * block_count: How many subsequent blocks to also request data for. + /// + /// Returns: + /// * The sequence of ETxOutRecord's, from consequecutive blocks starting + /// from block_index. Empty if not even the block_index'th block exists. + fn get_tx_outs_by_block_range_and_key( + &self, + ingress_key: CompressedRistrettoPublic, + block_index: u64, + block_count: usize, + ) -> Result>, Self::Error> { + our_retry(self.get_retries(), || { + self.get_tx_outs_by_block_range_and_key_retriable(ingress_key, block_index, block_count) + }) + } + /// Get iid that produced data for given ingress key and a given block /// index. fn get_invocation_id_by_block_and_key( @@ -2289,6 +2385,100 @@ mod tests { assert_eq!(tx_outs, records2); } + #[test_with_logger] + fn test_get_tx_outs_by_block_range_and_key(logger: Logger) { + let mut rng: StdRng = SeedableRng::from_seed([123u8; 32]); + let db_test_context = test_utils::SqlRecoveryDbTestContext::new(logger); + let db = db_test_context.get_db_instance(); + + let ingress_key = CompressedRistrettoPublic::from(RistrettoPublic::from_random(&mut rng)); + db.new_ingress_key(&ingress_key, 122).unwrap(); + + let invoc_id1 = db + .new_ingest_invocation(None, &ingress_key, &random_kex_rng_pubkey(&mut rng), 122) + .unwrap(); + + let invoc_id2 = db + .new_ingest_invocation(None, &ingress_key, &random_kex_rng_pubkey(&mut rng), 123) + .unwrap(); + + let (block1, records1) = random_block(&mut rng, 122, 10); + db.add_block_data(&invoc_id1, &block1, 0, &records1) + .unwrap(); + + let (block2, records2) = random_block(&mut rng, 123, 10); + db.add_block_data(&invoc_id2, &block2, 0, &records2) + .unwrap(); + + // Get tx outs for a key we're not aware of or a block id we're not aware of + // should return empty vec + let batch_result = db + .get_tx_outs_by_block_range_and_key(ingress_key, 124, 2) + .unwrap(); + assert_eq!(batch_result.len(), 0); + + let batch_result = db + .get_tx_outs_by_block_range_and_key( + CompressedRistrettoPublic::from_random(&mut rng), + 123, + 2, + ) + .unwrap(); + assert_eq!(batch_result.len(), 0); + + // Getting tx outs in a batch should work as expected when requesting things + // that exist + let batch_results = db + .get_tx_outs_by_block_range_and_key(ingress_key, block1.index, 1) + .unwrap(); + assert_eq!(batch_results.len(), 1); + assert_eq!(batch_results[0], records1); + + let batch_results = db + .get_tx_outs_by_block_range_and_key(ingress_key, block2.index, 1) + .unwrap(); + assert_eq!(batch_results.len(), 1); + assert_eq!(batch_results[0], records2); + + let batch_results = db + .get_tx_outs_by_block_range_and_key(ingress_key, block1.index, 2) + .unwrap(); + assert_eq!(batch_results.len(), 2); + assert_eq!(batch_results[0], records1); + assert_eq!(batch_results[1], records2); + + let batch_results = db + .get_tx_outs_by_block_range_and_key(ingress_key, block2.index, 2) + .unwrap(); + assert_eq!(batch_results.len(), 1); + assert_eq!(batch_results[0], records2); + + let batch_results = db + .get_tx_outs_by_block_range_and_key(ingress_key, block1.index, 3) + .unwrap(); + assert_eq!(batch_results.len(), 2); + assert_eq!(batch_results[0], records1); + assert_eq!(batch_results[1], records2); + + let batch_results = db + .get_tx_outs_by_block_range_and_key(ingress_key, block2.index, 3) + .unwrap(); + assert_eq!(batch_results.len(), 1); + assert_eq!(batch_results[0], records2); + + // When there is a gap in the data, the gap should suppress any further results + // even if there are hits later in the range. + let batch_results = db + .get_tx_outs_by_block_range_and_key(ingress_key, block1.index - 1, 2) + .unwrap(); + assert_eq!(batch_results.len(), 0); + + let batch_results = db + .get_tx_outs_by_block_range_and_key(ingress_key, block1.index - 2, 3) + .unwrap(); + assert_eq!(batch_results.len(), 0); + } + #[test_with_logger] fn test_get_highest_block_index(logger: Logger) { let mut rng: StdRng = SeedableRng::from_seed([123u8; 32]); diff --git a/fog/view/server/src/config.rs b/fog/view/server/src/config.rs index 2b2579d847..2869054cb9 100644 --- a/fog/view/server/src/config.rs +++ b/fog/view/server/src/config.rs @@ -71,4 +71,10 @@ pub struct MobileAcctViewConfig { /// Postgres config #[clap(flatten)] pub postgres_config: SqlRecoveryDbConnectionConfig, + + /// How many blocks to request at once when requesting blocks from postgres + /// Increasing this may help if there is high network latency with postgres, + /// and should not much harm performance otherwise when loading the DB. + #[clap(long, default_value = "1000", env = "MC_BLOCK_QUERY_BATCH_SIZE")] + pub block_query_batch_size: usize, } diff --git a/fog/view/server/src/db_fetcher.rs b/fog/view/server/src/db_fetcher.rs index e969cf8d97..3d6a4d765c 100644 --- a/fog/view/server/src/db_fetcher.rs +++ b/fog/view/server/src/db_fetcher.rs @@ -78,6 +78,7 @@ impl DbFetcher { pub fn new( db: DB, readiness_indicator: ReadinessIndicator, + block_query_batch_size: usize, logger: Logger, ) -> Self { let stop_requested = Arc::new(AtomicBool::new(false)); @@ -102,6 +103,7 @@ impl DbFetcher { thread_shared_state, thread_num_queued_records_limiter, readiness_indicator, + block_query_batch_size, logger, ) }) @@ -172,6 +174,7 @@ struct DbFetcherThread { block_tracker: BlockTracker, num_queued_records_limiter: Arc<(Mutex, Condvar)>, readiness_indicator: ReadinessIndicator, + block_query_batch_size: usize, logger: Logger, } @@ -184,8 +187,13 @@ impl DbFetcherThread { shared_state: Arc>, num_queued_records_limiter: Arc<(Mutex, Condvar)>, readiness_indicator: ReadinessIndicator, + block_query_batch_size: usize, logger: Logger, ) { + assert!( + block_query_batch_size > 0, + "Block batch request size cannot be 0, this is a configuration error" + ); let thread = Self { db, stop_requested, @@ -193,6 +201,7 @@ impl DbFetcherThread { block_tracker: BlockTracker::new(logger.clone()), num_queued_records_limiter, readiness_indicator, + block_query_batch_size, logger, }; thread.run(); @@ -282,64 +291,69 @@ impl DbFetcherThread { // Attempt to load data for the next block. let get_tx_outs_by_block_result = { let _metrics_timer = counters::GET_TX_OUTS_BY_BLOCK_TIME.start_timer(); - self.db - .get_tx_outs_by_block_and_key(ingress_key, block_index) + self.db.get_tx_outs_by_block_range_and_key( + ingress_key, + block_index, + self.block_query_batch_size, + ) }; match get_tx_outs_by_block_result { - Ok(Some(tx_outs)) => { - let num_tx_outs = tx_outs.len(); + Ok(block_results) => { + if block_results.is_empty() { + continue; + }; - // Log log::info!( self.logger, - "ingress_key {:?} fetched {} tx outs for block {}", + "ingress_key {:?} fetched {} blocks starting with block {}", ingress_key, - num_tx_outs, + block_results.len(), block_index, ); - // Ingest has produced data for this block, we'd like to keep trying the - // next block on the next loop iteration. - may_have_more_work = true; - - // Mark that we are done fetching data for this block. - self.block_tracker.block_processed(ingress_key, block_index); - - // Store the fetched records so that they could be consumed by the enclave - // when its ready. - { - let mut state = self.shared_state(); - state.fetched_records.push(FetchedRecords { - ingress_key, - block_index, - records: tx_outs, - }); + if block_results.len() == self.block_query_batch_size { + // Ingest has produced as much block data as we asked for, + // we'd like to keep trying to download in the next loop iteration. + may_have_more_work = true; } - // Update metrics. - counters::BLOCKS_FETCHED_COUNT.inc(); - counters::TXOS_FETCHED_COUNT.inc_by(num_tx_outs as u64); - - // Block if we have queued up enough records for now. - // (Until the enclave thread drains the queue). - let (lock, condvar) = &*self.num_queued_records_limiter; - let mut num_queued_records = condvar - .wait_while(lock.lock().unwrap(), |num_queued_records| { - *num_queued_records > MAX_QUEUED_RECORDS - }) - .expect("condvar wait failed"); - *num_queued_records += num_tx_outs; - - counters::DB_FETCHER_NUM_QUEUED_RECORDS.set(*num_queued_records as i64); - } - Ok(None) => { - log::trace!( - self.logger, - "ingress_key {:?} block {} query missed, no new data yet", - ingress_key, - block_index - ); + for (idx, tx_outs) in block_results.into_iter().enumerate() { + // shadow block_index using the offset from enumerate + // block_index is now the index of these tx_outs + let block_index = block_index + idx as u64; + let num_tx_outs = tx_outs.len(); + + // Mark that we are done fetching data for this block. + self.block_tracker.block_processed(ingress_key, block_index); + + // Store the fetched records so that they could be consumed by the + // enclave when its ready. + { + let mut state = self.shared_state(); + state.fetched_records.push(FetchedRecords { + ingress_key, + block_index, + records: tx_outs, + }); + } + + // Update metrics. + counters::BLOCKS_FETCHED_COUNT.inc(); + counters::TXOS_FETCHED_COUNT.inc_by(num_tx_outs as u64); + + // Block if we have queued up enough records for now. + // (Until the enclave thread drains the queue). + let (lock, condvar) = &*self.num_queued_records_limiter; + let mut num_queued_records = condvar + .wait_while(lock.lock().unwrap(), |num_queued_records| { + *num_queued_records > MAX_QUEUED_RECORDS + }) + .expect("condvar wait failed"); + *num_queued_records += num_tx_outs; + + counters::DB_FETCHER_NUM_QUEUED_RECORDS.set(*num_queued_records as i64); + } } Err(err) => { log::warn!( @@ -351,6 +365,8 @@ impl DbFetcherThread { ); // We might have more work to do, we aren't sure because of the error may_have_more_work = true; + // Let's back off for one interval when there is an error + sleep(DB_POLL_INTERNAL); } } } @@ -380,7 +396,7 @@ mod tests { let mut rng: StdRng = SeedableRng::from_seed([123u8; 32]); let db_test_context = SqlRecoveryDbTestContext::new(logger.clone()); let db = db_test_context.get_db_instance(); - let db_fetcher = DbFetcher::new(db.clone(), Default::default(), logger); + let db_fetcher = DbFetcher::new(db.clone(), Default::default(), 1, logger); // Initially, our database starts empty. let ingress_keys = db_fetcher.get_highest_processed_block_context(); @@ -610,7 +626,7 @@ mod tests { let mut rng: StdRng = SeedableRng::from_seed([123u8; 32]); let db_test_context = SqlRecoveryDbTestContext::new(logger.clone()); let db = db_test_context.get_db_instance(); - let db_fetcher = DbFetcher::new(db.clone(), Default::default(), logger); + let db_fetcher = DbFetcher::new(db.clone(), Default::default(), 1, logger); // Register two ingress keys that have some overlap: // key_id1 starts at block 0, key2 starts at block 5. @@ -667,7 +683,7 @@ mod tests { let mut rng: StdRng = SeedableRng::from_seed([123u8; 32]); let db_test_context = SqlRecoveryDbTestContext::new(logger.clone()); let db = db_test_context.get_db_instance(); - let db_fetcher = DbFetcher::new(db.clone(), Default::default(), logger); + let db_fetcher = DbFetcher::new(db.clone(), Default::default(), 1, logger); // Register two ingress keys that have some overlap: // invoc_id1 starts at block 0, invoc_id2 starts at block 50. diff --git a/fog/view/server/src/server.rs b/fog/view/server/src/server.rs index 7a02758abe..366af553e6 100644 --- a/fog/view/server/src/server.rs +++ b/fog/view/server/src/server.rs @@ -71,6 +71,7 @@ where let readiness_indicator = ReadinessIndicator::default(); let db_poll_thread = DbPollThread::new( + config.clone(), enclave.clone(), recovery_db.clone(), readiness_indicator.clone(), @@ -210,6 +211,9 @@ where E: ViewEnclaveProxy, DB: RecoveryDb + Clone + Send + Sync + 'static, { + /// Config + config: MobileAcctViewConfig, + /// Enclave. enclave: E, @@ -247,6 +251,7 @@ where /// Initialize a new DbPollThread object. pub fn new( + config: MobileAcctViewConfig, enclave: E, db: DB, readiness_indicator: ReadinessIndicator, @@ -256,6 +261,7 @@ where let shared_state = Arc::new(Mutex::new(DbPollSharedState::default())); Self { + config, enclave, db, join_handle: None, @@ -275,6 +281,7 @@ where *shared_state = DbPollSharedState::default(); } + let thread_config = self.config.clone(); let thread_enclave = self.enclave.clone(); let thread_db = self.db.clone(); let thread_stop_requested = self.stop_requested.clone(); @@ -287,6 +294,7 @@ where .name(format!("DbPoll-{}", std::any::type_name::())) .spawn(move || { Self::thread_entrypoint( + thread_config, thread_enclave, thread_db, thread_stop_requested, @@ -310,6 +318,7 @@ where } fn thread_entrypoint( + config: MobileAcctViewConfig, enclave: E, db: DB, stop_requested: Arc, @@ -320,6 +329,7 @@ where log::debug!(logger, "Db poll thread started"); let mut worker = DbPollThreadWorker::new( + config, stop_requested, enclave, db, @@ -402,6 +412,7 @@ where DB: RecoveryDb + Clone + Send + Sync + 'static, { pub fn new( + config: MobileAcctViewConfig, stop_requested: Arc, enclave: E, db: DB, @@ -414,7 +425,12 @@ where enclave, db: db.clone(), shared_state, - db_fetcher: DbFetcher::new(db, readiness_indicator, logger.clone()), + db_fetcher: DbFetcher::new( + db, + readiness_indicator, + config.block_query_batch_size, + logger.clone(), + ), enclave_block_tracker: BlockTracker::new(logger.clone()), last_unblocked_at: Instant::now(), logger, diff --git a/fog/view/server/tests/smoke_tests.rs b/fog/view/server/tests/smoke_tests.rs index caca9c453c..c9edbdcfb6 100644 --- a/fog/view/server/tests/smoke_tests.rs +++ b/fog/view/server/tests/smoke_tests.rs @@ -77,6 +77,7 @@ fn get_test_environment( admin_listen_uri: Default::default(), client_auth_token_max_lifetime: Default::default(), postgres_config: Default::default(), + block_query_batch_size: 2, }; let enclave = SgxViewEnclave::new( From b152e173b32807ac2aaa3b0ccba25a7bc583dd94 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Thu, 13 Oct 2022 14:43:18 -0600 Subject: [PATCH 64/77] Nits from fog view db fetch pr (#2714) * fix nits from fog-view-db-fetch pull request * update changelog --- CHANGELOG.md | 2 ++ fog/recovery_db_iface/src/lib.rs | 6 +++--- fog/sql_recovery_db/src/lib.rs | 14 +++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 149f8e7bc6..dfe4cf1523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem - Add a `--hash-tx-file` subcommand to print the hash of a `mint-tx` or `mint-config-tx` file. - Add the current block info (fee map, block version, etc.) to the response message for `mobilecoind_api.GetNetworkStatus`. - Make Jaeger telemetry opt-in using `MC_TELEMETRY=1`. +- Add a `--block-query-batch-size` parameter to fog-view. This makes fog-view load more data at once from postgres, and helps it to start up faster even if there is high + network latency in the connection to postgres. This defaults to 1000 now, where previous behavior corresponds to a value of 1. ### Fixes diff --git a/fog/recovery_db_iface/src/lib.rs b/fog/recovery_db_iface/src/lib.rs index 4a0f87b79c..1f56ce9c59 100644 --- a/fog/recovery_db_iface/src/lib.rs +++ b/fog/recovery_db_iface/src/lib.rs @@ -264,11 +264,11 @@ pub trait RecoveryDb { /// Arguments: /// * ingress_key: The ingress key we need ETxOutRecords from /// * block_index: The first block we need ETxOutRecords from - /// * block_count: How many subsequent blocks to also request data for. + /// * block_count: How many consecutive blocks to also request data for. /// /// Returns: - /// * The sequence of ETxOutRecord's, from consequecutive blocks starting - /// from block_index. Empty if not even the block_index'th block exists. + /// * The sequence of ETxOutRecord's, from consecutive blocks starting from + /// block_index. Empty if not even the block_index'th block exists. fn get_tx_outs_by_block_range_and_key( &self, ingress_key: CompressedRistrettoPublic, diff --git a/fog/sql_recovery_db/src/lib.rs b/fog/sql_recovery_db/src/lib.rs index c72deae7df..75403eaf36 100644 --- a/fog/sql_recovery_db/src/lib.rs +++ b/fog/sql_recovery_db/src/lib.rs @@ -943,11 +943,11 @@ impl SqlRecoveryDb { /// Arguments: /// * ingress_key: The ingress key we need ETxOutRecords from /// * block_index: The first block we need ETxOutRecords from - /// * block_count: How many subsequent blocks to also request data for. + /// * block_count: How many consecutive blocks to also request data for. /// /// Returns: - /// * The sequence of ETxOutRecord's, from consequecutive blocks starting - /// from block_index. Empty if not even the block_index'th block exists. + /// * The sequence of ETxOutRecord's, from consecutive blocks starting from + /// block_index. Empty if not even the block_index'th block exists. fn get_tx_outs_by_block_range_and_key_retriable( &self, ingress_key: CompressedRistrettoPublic, @@ -975,7 +975,7 @@ impl SqlRecoveryDb { }; // We will get one row for each hit in the table we found - let rows: Vec<(i64, Vec)> = query.load::<(i64, Vec)>(&conn)?; + let rows: Vec<(i64, Vec)> = query.load(&conn)?; if rows.len() > block_count { log::warn!( @@ -1429,11 +1429,11 @@ impl RecoveryDb for SqlRecoveryDb { /// Arguments: /// * ingress_key: The ingress key we need ETxOutRecords from /// * block_index: The first block we need ETxOutRecords from - /// * block_count: How many subsequent blocks to also request data for. + /// * block_count: How many consecutive blocks to also request data for. /// /// Returns: - /// * The sequence of ETxOutRecord's, from consequecutive blocks starting - /// from block_index. Empty if not even the block_index'th block exists. + /// * The sequence of ETxOutRecord's, from consecutive blocks starting from + /// block_index. Empty if not even the block_index'th block exists. fn get_tx_outs_by_block_range_and_key( &self, ingress_key: CompressedRistrettoPublic, From a817229adb6c069f601796f400bd31e2c6b14a2f Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Wed, 19 Oct 2022 16:30:19 -0500 Subject: [PATCH 65/77] release/v2 - CI/CD - change testing token to 8192 (#2731) * change testing token to 8192 * fix token governers/signers key generation * fix token governers/signers key generation * minting config tx option is threshold, not token id * make token id and fee arguments --- .../mobilecoin-workflow-dev-deploy.yaml | 2 +- .../mobilecoin-workflow-dev-test.yaml | 10 +-- ...ilecoin-workflow-dev-update-consensus.yaml | 2 +- .internal-ci/test/mint-auditor-test.sh | 12 +++- .internal-ci/test/minting-config-tx-test.sh | 2 +- .internal-ci/util/generate_minting_keys.sh | 65 +++++++++++++++---- .internal-ci/util/generate_tokens_config.sh | 40 ++++++++---- .internal-ci/util/tokens.base.json | 2 +- mint-auditor/tests/integration_test.py | 10 ++- 9 files changed, 106 insertions(+), 39 deletions(-) diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml index 7983fe8c8a..5b2a2d3d62 100644 --- a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -206,7 +206,7 @@ jobs: env: MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.MINTING_TRUST_ROOT_PRIVATE }} run: | - .internal-ci/util/generate_minting_keys.sh + .internal-ci/util/generate_minting_keys.sh --token-id 8192 - name: Login to DockerHub if: inputs.minting_config_enabled == 'true' diff --git a/.github/workflows/mobilecoin-workflow-dev-test.yaml b/.github/workflows/mobilecoin-workflow-dev-test.yaml index 49abe15d29..8493e4483d 100644 --- a/.github/workflows/mobilecoin-workflow-dev-test.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-test.yaml @@ -255,7 +255,7 @@ jobs: rancher_token: ${{ secrets.RANCHER_TOKEN }} command: | /test/minting-config-tx-test.sh \ - --token-id 1 + --token-id 8192 - name: Test - Minting tx if: inputs.testing_1_2 == 'true' @@ -270,7 +270,7 @@ jobs: command: | /test/minting-tx-test.sh \ --key-dir ${{ env.DST_KEYS_DIR }} \ - --token-id 1 + --token-id 8192 - name: Test - mobilecoind-json integration if: inputs.testing_1_2 == 'true' @@ -298,7 +298,7 @@ jobs: rancher_token: ${{ secrets.RANCHER_TOKEN }} command: | /test/mint-auditor-test.sh \ - --token-id 1 + --token-id 8192 - name: Test - use drain_accounts to transfer id 1 balances to fog keys if: inputs.testing_1_2 == 'true' @@ -315,7 +315,7 @@ jobs: --src ${{ env.DST_KEYS_DIR }} \ --dst ${{ env.DST_FOG_KEYS_DIR }} \ --fee 1024 \ - --token-id 1 + --token-id 8192 - name: Test - fog-test-client token id 0 if: inputs.testing_1_2 == 'true' @@ -345,4 +345,4 @@ jobs: command: | /test/fog-test-client.sh \ --key-dir ${{ env.DST_FOG_KEYS_DIR }} \ - --token-id 1 + --token-id 8192 diff --git a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml index 530c20a361..5a387a65f5 100644 --- a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml @@ -90,7 +90,7 @@ jobs: env: MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.MINTING_TRUST_ROOT_PRIVATE }} run: | - .internal-ci/util/generate_minting_keys.sh + .internal-ci/util/generate_minting_keys.sh --token-id 8192 - name: Login to DockerHub if: inputs.minting_config_enabled == 'true' diff --git a/.internal-ci/test/mint-auditor-test.sh b/.internal-ci/test/mint-auditor-test.sh index 88f491ece5..e12cc5fd58 100755 --- a/.internal-ci/test/mint-auditor-test.sh +++ b/.internal-ci/test/mint-auditor-test.sh @@ -10,6 +10,7 @@ usage() { echo "Usage --token-id " echo " --token-id - token id to test" + echo " --token-fee - fee for token id" } is_set() @@ -30,10 +31,14 @@ do usage exit 0 ;; - --token-id ) + --token-id) token_id="${2}" shift 2 ;; + --token-fee) + token_fee="${2}" + shift 2 + ;; *) echo "${1} unknown option" usage @@ -43,6 +48,7 @@ do done is_set token_id +is_set token_fee is_set NAMESPACE @@ -94,6 +100,8 @@ python3 integration_test.py \ --mint-auditor-addr "mobilecoind-mint-auditor:7774" \ --mint-client-bin /usr/local/bin/mc-consensus-mint-client \ --node-url "mc://node1.${NAMESPACE}.development.mobilecoin.com/" \ - --mint-signing-key "${token_signer_key}" + --mint-signing-key "${token_signer_key}" \ + --token-id "${token_id}" \ + --token-fee "${token_fee}" popd >/dev/null || exit 1 diff --git a/.internal-ci/test/minting-config-tx-test.sh b/.internal-ci/test/minting-config-tx-test.sh index 3bdad0db12..a98e9c1d8b 100755 --- a/.internal-ci/test/minting-config-tx-test.sh +++ b/.internal-ci/test/minting-config-tx-test.sh @@ -53,7 +53,7 @@ mc-consensus-mint-client generate-and-submit-mint-config-tx \ --node "mc://node1.${NAMESPACE}.development.mobilecoin.com/" \ --signing-key "${governor_signer_key}" \ --token-id "${token_id}" \ - --config "1000000000:${token_id}:${token_signer_key}" \ + --config "1000000000:1:${token_signer_key}" \ --total-mint-limit 10000000000 echo "-- sleep and wait for tx/blocks to sync" diff --git a/.internal-ci/util/generate_minting_keys.sh b/.internal-ci/util/generate_minting_keys.sh index eb3ead90e8..18d287d109 100755 --- a/.internal-ci/util/generate_minting_keys.sh +++ b/.internal-ci/util/generate_minting_keys.sh @@ -9,35 +9,72 @@ set -e location=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +usage() +{ + echo "Usage:" + echo "${0} --token-id 8192" + echo " --token-id - id to generate keys for" +} + +is_set() +{ + var_name="${1}" + if [ -z "${!var_name}" ] + then + echo "${var_name} is not set." + usage + exit 1 + fi +} + +while (( "$#" )) +do + case "${1}" in + --help | -h) + usage + exit 0 + ;; + --token-id ) + token_id="${2}" + shift 2 + ;; + *) + break + ;; + esac +done + +is_set token_id + BASE_PATH="${BASE_PATH:-.tmp/seeds/minting}" mkdir -p "${BASE_PATH}" -# Token 1 governor keys +# Token governor keys # This key pair is used to validate MintConfigTxs -if [[ ! -f "${BASE_PATH}/minter1_governor.private.pem" ]] +if [[ ! -f "${BASE_PATH}/minter${token_id}_governor.private.pem" ]] then "${location}/generate_ed25519_keys.sh" \ - --public-out "${BASE_PATH}/minter1_governor.public.pem" \ - --private-out "${BASE_PATH}/minter1_governor.private.pem" + --public-out "${BASE_PATH}/minter${token_id}_governor.public.pem" \ + --private-out "${BASE_PATH}/minter${token_id}_governor.private.pem" else - echo "minter1_governor keys already exist" + echo "minter${token_id}_governor keys already exist" fi -sha256sum "${BASE_PATH}/minter1_governor.private.pem" -sha256sum "${BASE_PATH}/minter1_governor.public.pem" +sha256sum "${BASE_PATH}/minter${token_id}_governor.private.pem" +sha256sum "${BASE_PATH}/minter${token_id}_governor.public.pem" -# Token 1 signer keys +# Token signer keys # This key pair is used to validate MintTX if [[ ! -f "${BASE_PATH}/token_signer.private.pem" ]] then - echo "Writing token1_signer keys" + echo "Writing token${token_id}_signer keys" "${location}/generate_ed25519_keys.sh" \ - --public-out "${BASE_PATH}/token1_signer.public.pem" \ - --private-out "${BASE_PATH}/token1_signer.private.pem" + --public-out "${BASE_PATH}/token${token_id}_signer.public.pem" \ + --private-out "${BASE_PATH}/token${token_id}_signer.private.pem" else - echo "token1_signer keys already exist" + echo "token${token_id}_signer keys already exist" fi -sha256sum "${BASE_PATH}/token1_signer.private.pem" -sha256sum "${BASE_PATH}/token1_signer.public.pem" +sha256sum "${BASE_PATH}/token${token_id}_signer.private.pem" +sha256sum "${BASE_PATH}/token${token_id}_signer.public.pem" # Write minting trust root private key if its defined. if [[ -n "${MINTING_TRUST_ROOT_PRIVATE}" ]] diff --git a/.internal-ci/util/generate_tokens_config.sh b/.internal-ci/util/generate_tokens_config.sh index 7e2a05c5c1..7a28d8c7df 100755 --- a/.internal-ci/util/generate_tokens_config.sh +++ b/.internal-ci/util/generate_tokens_config.sh @@ -21,25 +21,41 @@ minting_path="${BASE_PATH}/seeds/minting" # check for required files exists "${location}/tokens.base.json" -exists "${minting_path}/minter1_governor.public.pem" -sha256sum "${minting_path}/minter1_governor.public.pem" - -exists "${minting_path}/minting_trust_root.private.pem" -sha256sum "${minting_path}/minting_trust_root.private.pem" - # Grab base json json=$(cat "${location}/tokens.base.json") +token_ids=$(echo "${json}" | jq -r '.tokens[].token_id') + +for id in ${token_ids} +do + if [[ ${id} -eq 0 ]] + then + echo "Found token_id 0 - nothing to do." + continue + fi -# Set minter1 pub keys and threshold -minter1_governor=$(cat "${minting_path}/minter1_governor.public.pem") -json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == 1) | .governors.signers) |= \"${minter1_governor}\"") -json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == 1) | .governors.threshold) |= 1") + echo "Token ID: ${id} - Checking for governor ed25519 keys" + exists "${minting_path}/minter${id}_governor.public.pem" + sha256sum "${minting_path}/minter8192_governor.public.pem" + + echo "Token ID: ${id} - Add governor signer pub keys and threshold to json" + minter_governor=$(cat "${minting_path}/minter${id}_governor.public.pem") + + json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == ${id}) | .governors.signers) |= \"${minter_governor}\"") + + json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == ${id}) | .governors.threshold) |= 1") +done #output unsigned tokens -echo "$json" | jq . > .tmp/tokens.json +echo "$json" | jq . > "${BASE_PATH}/tokens.json" + +echo "Checking for minting_trust_root ed25519 keys" +exists "${minting_path}/minting_trust_root.private.pem" +sha256sum "${minting_path}/minting_trust_root.private.pem" # Sign tokens file -echo "Signing tokens file" +echo "Signing the tokens file" mc-consensus-mint-client sign-governors --tokens "${BASE_PATH}/tokens.json" \ --signing-key "${minting_path}/minting_trust_root.private.pem" \ --output-json "${BASE_PATH}/tokens.signed.json" >/dev/null + +cat "${BASE_PATH}/tokens.signed.json" diff --git a/.internal-ci/util/tokens.base.json b/.internal-ci/util/tokens.base.json index a46c54e568..9cfc81dd98 100644 --- a/.internal-ci/util/tokens.base.json +++ b/.internal-ci/util/tokens.base.json @@ -6,7 +6,7 @@ "minimum_fee": 400000000 }, { - "token_id": 1, + "token_id": 8192, "minimum_fee": 1024, "governors": { "signers": "", diff --git a/mint-auditor/tests/integration_test.py b/mint-auditor/tests/integration_test.py index 2b49eb0a90..55951b0cf0 100644 --- a/mint-auditor/tests/integration_test.py +++ b/mint-auditor/tests/integration_test.py @@ -150,7 +150,7 @@ def run(self): try: b58_addr = self.mobilecoind_client.get_b58_public_address(monitor_id) logging.info(f"Minting to {b58_addr}") - token_id = 1 + token_id = self.args.token_id mint_amount = 10000 # Get the network block height and wait for the mint auditor to catch up @@ -180,7 +180,7 @@ def run(self): # Burn 300 tokens burn_amount = 300 - fee_amount = 1024 + fee_amount = self.args.token_fee utxos = self.mobilecoind_client.get_utxos(monitor_id, token_id) tx_proposal = self.mobilecoind_client.generate_burn_redemption_tx( monitor_id, @@ -265,6 +265,12 @@ def wait_for_mint_auditor_to_sync(self): parser.add_argument("--mint-signing-key", type=str, help="path to the mint signing private key file") + parser.add_argument("--token-id", + type=int, + help="token id to mint") + parser.add_argument("--token-fee", + type=int, + help="fee for specified token id") args = parser.parse_args() MintAuditorTest(args).run() From 72ff6ca3cff7b884e9113c4d8bc1192e66a942f1 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Thu, 20 Oct 2022 13:29:41 -0500 Subject: [PATCH 66/77] must specify fee now (#2737) --- .github/workflows/mobilecoin-workflow-dev-test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mobilecoin-workflow-dev-test.yaml b/.github/workflows/mobilecoin-workflow-dev-test.yaml index 8493e4483d..3eb8cf6436 100644 --- a/.github/workflows/mobilecoin-workflow-dev-test.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-test.yaml @@ -298,9 +298,9 @@ jobs: rancher_token: ${{ secrets.RANCHER_TOKEN }} command: | /test/mint-auditor-test.sh \ - --token-id 8192 + --token-id 8192 --token-fee 1024 - - name: Test - use drain_accounts to transfer id 1 balances to fog keys + - name: Test - use drain_accounts to transfer id 8192 balances to fog keys if: inputs.testing_1_2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: From ff04e9ed6b0a1a289fc6b96eb3a5b1841f7c5c47 Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 24 Oct 2022 09:39:30 -0700 Subject: [PATCH 67/77] Update to SGX 2.17.1, add INTEL-SA-00657 to known advisories list. (#2639) (#2759) * Update to SGX 2.17.1, add INTEL-SA-00657 to known advisories list. (#2639) * Update to SGX 2.17.1, add INTEL-SA-00657 to known advisories list. * Update relevant containers to v0.0.18 * Update CircleCI to also use v0.0.18 Conflicts: * ci.yml and dependent-repos.yml don't exist in release/v3 * Bump other containers. Fix AESM_VERSION in runtime container. * Only 'Install Rust' on MacOS --- .circleci/config.yml | 6 ++---- .github/workflows/mobilecoin-dev-cd.yaml | 2 +- .internal-ci/docker/Dockerfile.runtime-base | 2 +- .mobconf | 5 ++--- attest/verifier/README.md | 2 +- consensus/enclave/build.rs | 2 +- consensus/enclave/measurement/build.rs | 2 +- consensus/enclave/measurement/src/lib.rs | 2 +- consensus/enclave/trusted/build.rs | 2 +- consensus/service/BUILD.md | 6 +++--- crypto/ake/enclave/src/lib.rs | 11 ++++++++++- docker/install_sgx.sh | 6 +++--- fog/ingest/enclave/build.rs | 2 +- fog/ingest/enclave/measurement/build.rs | 2 +- fog/ingest/enclave/measurement/src/lib.rs | 2 +- fog/ingest/enclave/trusted/build.rs | 2 +- fog/ledger/enclave/build.rs | 2 +- fog/ledger/enclave/measurement/build.rs | 2 +- fog/ledger/enclave/measurement/src/lib.rs | 2 +- fog/ledger/enclave/trusted/build.rs | 2 +- fog/view/enclave/build.rs | 2 +- fog/view/enclave/measurement/build.rs | 2 +- fog/view/enclave/measurement/src/lib.rs | 2 +- fog/view/enclave/trusted/build.rs | 2 +- jenkins/build-pod.yaml | 2 +- mobilecoind/src/config.rs | 7 +++++-- ops/Dockerfile-consensus | 2 +- 27 files changed, 46 insertions(+), 37 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3722b17366..241f1d7972 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ version: 2.1 defaults: - builder-install: &builder-install gcr.io/mobilenode-211420/builder-install:1_29 + builder-install: &builder-install mobilecoin/builder-install:v0.0.18 android-bindings-builder: &android-bindings-builder gcr.io/mobilenode-211420/android-bindings-builder:1_4 default-xcode-version: &default-xcode-version "12.5.1" @@ -247,7 +247,6 @@ commands: command: | command -v rustup >/dev/null \ || curl https://sh.rustup.rs --tlsv1.2 -sSf | sh -s -- -y --default-toolchain stable - # Installs the toolchain specified in `rust-toolchain` "$HOME/.cargo/bin/rustup" show active-toolchain install-ci-deps: @@ -308,11 +307,10 @@ commands: - checkout - when: condition: { equal: [ << parameters.os >>, macos ] } - steps: [ restore-homebrew-cache ] + steps: [ restore-homebrew-cache, install-rust ] - when: condition: { equal: [ << parameters.os >>, linux ] } steps: [ enable-postgresql ] - - install-rust - restore-cargo-cache - env_setup - install-ci-deps: diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 6fce0d8872..1a86340cc4 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -60,7 +60,7 @@ jobs: build-rust-hardware-projects: runs-on: [self-hosted, Linux, large] container: - image: mobilecoin/rust-sgx-base:v0.0.14 + image: mobilecoin/rust-sgx-base:v0.0.18 env: ENCLAVE_SIGNING_KEY_PATH: ${{ github.workspace }}/.tmp/enclave_signing.pem MINTING_TRUST_ROOT_PUBLIC_KEY_PEM: ${{ github.workspace }}/.tmp/minting_trust_root.public.pem diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base index 8fff105b34..e463261aff 100644 --- a/.internal-ci/docker/Dockerfile.runtime-base +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -31,7 +31,7 @@ ENV LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" # libsgx-enclave-common libsgx-epid libsgx-launch libsgx-pce-logic libsgx-urts # sgx-aesm-service # Use `apt show -a sgx-aesm-service` to find version -ENV AESM_VERSION=2.17.100.3-focal1 +ENV AESM_VERSION=2.17.101.1-focal1 # Use `apt show -a libsgx-pce-logic` to find the version thats compatible with aesm. ENV PCE_LOGIC_VERSION=1.14.100.3-focal1 diff --git a/.mobconf b/.mobconf index 27dde1b5ce..ba51f7f940 100644 --- a/.mobconf +++ b/.mobconf @@ -1,4 +1,3 @@ [image] -dockerfile-version = v0.0.14 -target = builder-install -repository = mobilecoin +url = mobilecoin/builder-install +tag = v0.0.18 diff --git a/attest/verifier/README.md b/attest/verifier/README.md index e21919cffa..9929101d58 100644 --- a/attest/verifier/README.md +++ b/attest/verifier/README.md @@ -15,7 +15,7 @@ use mc_util_encodings::FromHex; let mut enclave_verifier = MrEnclaveVerifier::new(MrEnclave::from_hex("BEEFCAFEDEADBEEFCAFEBEEF")); // Whitelist the LVI hardening advisory (assume the BEEF... enclave is hardened) // Whitelist the MMIO hardening advisory (assume the enclave uses [out] and 8-byte aligned writes) -enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); +enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615", "INTEL-SA-00657"]); // Construct a new verifier using hard-coded IAS signing certificates let mut verifier = Verifier::default(); diff --git a/consensus/enclave/build.rs b/consensus/enclave/build.rs index 06f7cf9e95..c1b9662a22 100644 --- a/consensus/enclave/build.rs +++ b/consensus/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; fn main() { let env = Environment::default(); diff --git a/consensus/enclave/measurement/build.rs b/consensus/enclave/measurement/build.rs index 46e6771889..ec0030f1cc 100644 --- a/consensus/enclave/measurement/build.rs +++ b/consensus/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; const CONSENSUS_ENCLAVE_PRODUCT_ID: u16 = 1; const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 5; diff --git a/consensus/enclave/measurement/src/lib.rs b/consensus/enclave/measurement/src/lib.rs index 46c4b1f947..101a096e91 100644 --- a/consensus/enclave/measurement/src/lib.rs +++ b/consensus/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615", "INTEL-SA-00657"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/consensus/enclave/trusted/build.rs b/consensus/enclave/trusted/build.rs index c130d2d1e6..f9d4073658 100644 --- a/consensus/enclave/trusted/build.rs +++ b/consensus/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; fn main() { let env = Environment::default(); diff --git a/consensus/service/BUILD.md b/consensus/service/BUILD.md index 28df38409b..7f3e8d0054 100644 --- a/consensus/service/BUILD.md +++ b/consensus/service/BUILD.md @@ -97,7 +97,7 @@ Recommended SDK and package installation: ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.17.1/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.101.1.bin" wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list @@ -112,8 +112,8 @@ chmod +x ./sgx_linux_x64_driver_2.11.054c9c4c.bin ./sgx_linux_x64_driver_2.11.054c9c4c.bin # Install the SDK to /opt/intel/sgxsdk -chmod +x ./sgx_linux_x64_sdk_2.17.100.3.bin -./sgx_linux_x64_sdk_2.17.100.3.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.17.101.1.bin +./sgx_linux_x64_sdk_2.17.101.1.bin --prefix=/opt/intel apt install libsgx-uae-service sgx-aesm-service diff --git a/crypto/ake/enclave/src/lib.rs b/crypto/ake/enclave/src/lib.rs index 1c2600daa3..fb50e8688f 100644 --- a/crypto/ake/enclave/src/lib.rs +++ b/crypto/ake/enclave/src/lib.rs @@ -137,7 +137,16 @@ impl AkeEnclaveState { // INTEL-SA-00615: MMIO Stale Data is handled by using [out] parameters // in our ECALL/OCALL definitions (EDLs), and only performing direct // writes aligned to quadword (8B) boundaries (e.g. in ORAMStorage) - mr_enclave_verifier.allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); + // + // INTEL-SA-00657: xAPIC Stale Data is handled by ensuring reads in/out of the + // enclave are aligned to an 8-byte boundary, and performed in multiples + // of 8 bytes. In our codebase, this happens within the sgx_edger8r code-gen, so + // building against SGX 2.17.1 is sufficient hardening for now. + mr_enclave_verifier.allow_hardening_advisories(&[ + "INTEL-SA-00334", + "INTEL-SA-00615", + "INTEL-SA-00657", + ]); verifier .mr_enclave(mr_enclave_verifier) diff --git a/docker/install_sgx.sh b/docker/install_sgx.sh index 3960fe81f8..6d36462a33 100755 --- a/docker/install_sgx.sh +++ b/docker/install_sgx.sh @@ -24,7 +24,7 @@ cd /tmp ( . /etc/os-release - wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" + wget "https://download.01.org/intel-sgx/sgx-linux/2.17.1/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.101.1.bin" echo "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list ) @@ -59,8 +59,8 @@ apt-get install -yq --no-install-recommends \ # Install *after* pkg-config so that they get registered correctly. # pkg-config gets pulled in transitively via build-essential -chmod +x ./sgx_linux_x64_sdk_2.17.100.3.bin -./sgx_linux_x64_sdk_2.17.100.3.bin --prefix=/opt/intel +chmod +x ./sgx_linux_x64_sdk_2.17.101.1.bin +./sgx_linux_x64_sdk_2.17.101.1.bin --prefix=/opt/intel # Update .bashrc to source sgxsdk echo 'source /opt/intel/sgxsdk/environment' >> /root/.bashrc diff --git a/fog/ingest/enclave/build.rs b/fog/ingest/enclave/build.rs index 85b5ffa7c3..74602d387b 100644 --- a/fog/ingest/enclave/build.rs +++ b/fog/ingest/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; fn main() { let env = Environment::default(); diff --git a/fog/ingest/enclave/measurement/build.rs b/fog/ingest/enclave/measurement/build.rs index 67635f698e..98d4b976f4 100644 --- a/fog/ingest/enclave/measurement/build.rs +++ b/fog/ingest/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; const INGEST_ENCLAVE_PRODUCT_ID: u16 = 4; const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 4; diff --git a/fog/ingest/enclave/measurement/src/lib.rs b/fog/ingest/enclave/measurement/src/lib.rs index 5f0064d12a..a0c0f2aa1a 100644 --- a/fog/ingest/enclave/measurement/src/lib.rs +++ b/fog/ingest/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615", "INTEL-SA-00657"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/ingest/enclave/trusted/build.rs b/fog/ingest/enclave/trusted/build.rs index 1b47cb1d60..be28fee2b3 100644 --- a/fog/ingest/enclave/trusted/build.rs +++ b/fog/ingest/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/build.rs b/fog/ledger/enclave/build.rs index 8dc6e68629..dd3cee5a4b 100644 --- a/fog/ledger/enclave/build.rs +++ b/fog/ledger/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; fn main() { let env = Environment::default(); diff --git a/fog/ledger/enclave/measurement/build.rs b/fog/ledger/enclave/measurement/build.rs index 7702a6b013..fdc444e4f6 100644 --- a/fog/ledger/enclave/measurement/build.rs +++ b/fog/ledger/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; const LEDGER_ENCLAVE_PRODUCT_ID: u16 = 2; const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 4; diff --git a/fog/ledger/enclave/measurement/src/lib.rs b/fog/ledger/enclave/measurement/src/lib.rs index 7bf42f751b..d028d2b802 100644 --- a/fog/ledger/enclave/measurement/src/lib.rs +++ b/fog/ledger/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615", "INTEL-SA-00657"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/ledger/enclave/trusted/build.rs b/fog/ledger/enclave/trusted/build.rs index d71761f769..861254182f 100644 --- a/fog/ledger/enclave/trusted/build.rs +++ b/fog/ledger/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/build.rs b/fog/view/enclave/build.rs index 0df4b8bb9a..b99759aa90 100644 --- a/fog/view/enclave/build.rs +++ b/fog/view/enclave/build.rs @@ -12,7 +12,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; fn main() { let env = Environment::default(); diff --git a/fog/view/enclave/measurement/build.rs b/fog/view/enclave/measurement/build.rs index 77c9b28922..93b86ab54a 100644 --- a/fog/view/enclave/measurement/build.rs +++ b/fog/view/enclave/measurement/build.rs @@ -10,7 +10,7 @@ use std::{env::var, path::PathBuf}; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; const VIEW_ENCLAVE_PRODUCT_ID: u16 = 3; const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 4; diff --git a/fog/view/enclave/measurement/src/lib.rs b/fog/view/enclave/measurement/src/lib.rs index 94bb6d37fc..1abe9ea515 100644 --- a/fog/view/enclave/measurement/src/lib.rs +++ b/fog/view/enclave/measurement/src/lib.rs @@ -14,7 +14,7 @@ pub fn sigstruct() -> Signature { } pub const CONFIG_ADVISORIES: &[&str] = &[]; -pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615"]; +pub const HARDENING_ADVISORIES: &[&str] = &["INTEL-SA-00334", "INTEL-SA-00615", "INTEL-SA-00657"]; pub fn get_mr_signer_verifier(override_minimum_svn: Option) -> MrSignerVerifier { let signature = sigstruct(); diff --git a/fog/view/enclave/trusted/build.rs b/fog/view/enclave/trusted/build.rs index ad2076eca5..eb6367157e 100644 --- a/fog/view/enclave/trusted/build.rs +++ b/fog/view/enclave/trusted/build.rs @@ -14,7 +14,7 @@ const SGX_SIMULATION_LIBS: &[&str] = &["libsgx_urts_sim", "libsgx_epid_sim"]; // Changing this version is a breaking change, you must update the crate version // if you do. -const SGX_VERSION: &str = "2.17.100.3"; +const SGX_VERSION: &str = "2.17.101.1"; fn main() { let env = Environment::default(); diff --git a/jenkins/build-pod.yaml b/jenkins/build-pod.yaml index 0f56bcd0ec..347c98cdeb 100644 --- a/jenkins/build-pod.yaml +++ b/jenkins/build-pod.yaml @@ -20,7 +20,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: rust-builder-default - image: gcr.io/mobilenode-211420/builder-install:1_29 + image: mobilecoin/builder-install:v0.0.18 env: - name: PATH value: "/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/intel/sgxsdk/bin:/opt/intel/sgxsdk/bin/x64" diff --git a/mobilecoind/src/config.rs b/mobilecoind/src/config.rs index 693a48f31b..68aad89a39 100644 --- a/mobilecoind/src/config.rs +++ b/mobilecoind/src/config.rs @@ -176,8 +176,11 @@ impl Config { signature.product_id(), signature.version(), ); - mr_signer_verifier - .allow_hardening_advisories(&["INTEL-SA-00334", "INTEL-SA-00615"]); + mr_signer_verifier.allow_hardening_advisories(&[ + "INTEL-SA-00334", + "INTEL-SA-00615", + "INTEL-SA-00657", + ]); mr_signer_verifier }; diff --git a/ops/Dockerfile-consensus b/ops/Dockerfile-consensus index 601bf23abd..16c9bfc866 100644 --- a/ops/Dockerfile-consensus +++ b/ops/Dockerfile-consensus @@ -21,7 +21,7 @@ RUN apt-get update -q -q && \ RUN source /etc/os-release && \ wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_driver_2.11.054c9c4c.bin" && \ - wget "https://download.01.org/intel-sgx/sgx-linux/2.17/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.100.3.bin" && \ + wget "https://download.01.org/intel-sgx/sgx-linux/2.17.1/distro/ubuntu${VERSION_ID}-server/sgx_linux_x64_sdk_2.17.101.1.bin" && \ echo "deb [arch=amd64 signed-by=/usr/local/share/apt-keyrings/intel-sgx-archive-keyring.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu/ ${UBUNTU_CODENAME} main" > /etc/apt/sources.list.d/intel-sgx.list RUN mkdir -p /usr/local/share/apt-keyrings && \ From 1cbf9f545f854a67fb194ac37ebe4842a608d17a Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 24 Oct 2022 11:45:01 -0700 Subject: [PATCH 68/77] Bump versions to 3.0.0-pre0 (#2760) --- Cargo.lock | 332 +++++++++--------- account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- .../android-bindings/publish.gradle | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- common/Cargo.toml | 2 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 ++--- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 +++--- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/report/Cargo.toml | 2 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 +++--- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/resolver/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 +++--- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- go-grpc-gateway/testing/Cargo.toml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 2 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 2 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/cli/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- wasm-test/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 182 files changed, 541 insertions(+), 541 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e33e46f35b..89923b6807 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1574,7 +1574,7 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "go-grpc-gateway-testing" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2027,7 +2027,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "cbindgen", @@ -2214,7 +2214,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "criterion", "curve25519-dalek", @@ -2242,7 +2242,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2258,7 +2258,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -2273,7 +2273,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "anyhow", @@ -2312,7 +2312,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "bs58", "cargo-emit", @@ -2348,7 +2348,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -2391,7 +2391,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "bincode", @@ -2423,7 +2423,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2436,7 +2436,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2456,7 +2456,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -2467,7 +2467,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2477,7 +2477,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2502,7 +2502,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "backtrace", "binascii", @@ -2539,7 +2539,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "cookie", @@ -2568,7 +2568,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2579,7 +2579,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -2600,7 +2600,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2625,7 +2625,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "hex", @@ -2646,7 +2646,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2654,7 +2654,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "hex", @@ -2690,7 +2690,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2703,7 +2703,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2725,7 +2725,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2754,7 +2754,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "crossbeam-channel", "maplit", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "mc-common", @@ -2789,7 +2789,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "chrono", @@ -2851,7 +2851,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -2876,7 +2876,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2896,7 +2896,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "digest 0.10.3", @@ -2912,7 +2912,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2925,7 +2925,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -2934,7 +2934,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2942,7 +2942,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2951,7 +2951,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2959,7 +2959,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "blake2", "digest 0.10.3", @@ -2968,7 +2968,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -3001,7 +3001,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "displaydoc", @@ -3015,7 +3015,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3029,7 +3029,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -3050,7 +3050,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3061,7 +3061,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3074,7 +3074,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3086,7 +3086,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3097,7 +3097,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3108,7 +3108,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -3140,7 +3140,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3172,7 +3172,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "cookie", @@ -3196,7 +3196,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3235,7 +3235,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "criterion", @@ -3270,7 +3270,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3287,7 +3287,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3295,7 +3295,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3328,7 +3328,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3341,7 +3341,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-report" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3353,7 +3353,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "dirs", @@ -3410,7 +3410,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3426,7 +3426,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "grpcio", @@ -3447,7 +3447,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3476,7 +3476,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3502,7 +3502,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3525,7 +3525,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3538,7 +3538,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3592,7 +3592,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3608,7 +3608,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -3637,14 +3637,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3655,7 +3655,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -3672,7 +3672,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "lazy_static", "mc-common", @@ -3680,7 +3680,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3718,7 +3718,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3732,7 +3732,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -3751,7 +3751,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-util-serial", "prost", @@ -3760,7 +3760,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "binascii", @@ -3784,7 +3784,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "grpcio", @@ -3801,7 +3801,7 @@ dependencies = [ [[package]] name = "mc-fog-report-resolver" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-account-keys", "mc-attest-verifier", @@ -3816,7 +3816,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3852,7 +3852,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3862,7 +3862,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3875,7 +3875,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3883,7 +3883,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3930,7 +3930,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3951,7 +3951,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3962,7 +3962,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3977,7 +3977,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "chrono", "clap 3.1.18", @@ -4010,7 +4010,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4041,7 +4041,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4072,7 +4072,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "crc", "displaydoc", @@ -4092,7 +4092,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-common", "mc-util-uri", @@ -4100,7 +4100,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "grpcio", "mc-attest-core", @@ -4120,7 +4120,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "criterion", @@ -4155,7 +4155,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4173,7 +4173,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4181,7 +4181,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4203,7 +4203,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4216,7 +4216,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4235,7 +4235,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-account-keys", @@ -4258,7 +4258,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4308,7 +4308,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "lazy_static", @@ -4334,7 +4334,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "dirs", @@ -4356,7 +4356,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "mc-api", @@ -4367,7 +4367,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4380,7 +4380,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4411,7 +4411,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4444,7 +4444,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -4458,7 +4458,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4523,7 +4523,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "futures", @@ -4542,7 +4542,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4617,7 +4617,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4649,7 +4649,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "grpcio", "hex", @@ -4672,7 +4672,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cc", "lazy_static", @@ -4682,7 +4682,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4690,7 +4690,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4699,7 +4699,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4707,7 +4707,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4716,21 +4716,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4741,7 +4741,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4757,7 +4757,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4767,18 +4767,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-urts" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-common", "mc-sgx-build", @@ -4789,7 +4789,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4801,7 +4801,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-account-keys", "mc-api", @@ -4811,7 +4811,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-util-test-vector", "serde", @@ -4820,7 +4820,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4835,7 +4835,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "hex", "mc-account-keys", @@ -4857,7 +4857,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -4899,7 +4899,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4916,7 +4916,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4943,7 +4943,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -4952,7 +4952,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4968,7 +4968,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4976,7 +4976,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "json", @@ -4984,7 +4984,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -4995,7 +4995,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -5006,7 +5006,7 @@ dependencies = [ [[package]] name = "mc-util-cli" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "mc-util-build-info", @@ -5014,7 +5014,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "binascii", @@ -5026,18 +5026,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-util-from-random" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5056,7 +5056,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -5090,7 +5090,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "grpcio", @@ -5101,7 +5101,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5112,11 +5112,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-util-keyfile" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "clap 3.1.18", @@ -5144,7 +5144,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5154,7 +5154,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -5163,7 +5163,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5171,7 +5171,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "chrono", "grpcio", @@ -5184,7 +5184,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "itertools", "mc-sgx-css", @@ -5192,7 +5192,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "generic-array", "prost", @@ -5202,7 +5202,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "hex", @@ -5215,7 +5215,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "prost", "serde", @@ -5224,7 +5224,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5235,7 +5235,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "itertools", @@ -5249,7 +5249,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "serde", "serde_json", @@ -5257,7 +5257,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -5266,7 +5266,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "displaydoc", @@ -5284,7 +5284,7 @@ dependencies = [ [[package]] name = "mc-wasm-test" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "getrandom 0.2.6", "mc-account-keys", @@ -5299,7 +5299,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5343,7 +5343,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 0d44c562d5..77e784c103 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index 0058228d01..ad5e676449 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index 0fed019fa2..f1df662524 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index b76b1b0a0c..df7c817e90 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/android-bindings/lib-wrapper/android-bindings/publish.gradle b/android-bindings/lib-wrapper/android-bindings/publish.gradle index 27c3b4f37e..9de1eaa333 100644 --- a/android-bindings/lib-wrapper/android-bindings/publish.gradle +++ b/android-bindings/lib-wrapper/android-bindings/publish.gradle @@ -1,6 +1,6 @@ apply plugin: 'maven-publish' -version '2.1.0-pre0' +version '3.0.0-pre0' group 'com.mobilecoin' Properties properties = new Properties() diff --git a/api/Cargo.toml b/api/Cargo.toml index dd2f553ce3..8e6377a0af 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index c999191341..11494a6b23 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index f83de84d37..7b9b18e625 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index 9bae066d9f..b428c5c464 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index 7dc2a49818..36297da794 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index d36c1a841d..2e091090f2 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index 50a66fd8bb..4008f8c351 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index cdbc191a0d..10531c3c2e 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index 9cfd72a27b..f9289153d7 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/common/Cargo.toml b/common/Cargo.toml index 0ffc88a556..dc62467d15 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/Cargo.toml b/connection/Cargo.toml index 27ee1ec6e7..0449108909 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index 19a7972465..beb34f09d2 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index d6a8dc11fb..619c2247d0 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index 6bcf8f98fa..bcb2996e26 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index 43a2144478..f9728e5c8c 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index f29f3f4558..4b0cac63dc 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index 40f3370824..e013f472d0 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index d6d3e68132..124eebe7af 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index de6540e516..5a202dcf2f 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index 3d3f2afa6f..d7f3dee3d8 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-build" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-enclave-id" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-transaction-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index c2faddc959..ce0c3528fb 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index cc90147732..82eef00ced 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index 6c58a3be4a..6ebbc2bce5 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index 472a6974ab..6df64bb08d 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index 1f65f09d24..acd3877fa3 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index a9da751ded..26582cd432 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index 323e1bfe43..c559dbe52c 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index 70e5d1b7c2..7b2eb29782 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index 54da7b4b88..dae167fb2e 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index 5a52c06ff3..935edd2aea 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index 6187dc041f..6fef22bca9 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index 0e08de8d06..3fe8f83b6d 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index 2e78f2e5f1..2b2fb4c650 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index 15e6ae38b1..7f9c5264da 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index 0e9a2931fd..02f5445f13 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index 936005b2ac..4d2a3f1254 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index 42b32842ce..b9f18ef6a2 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index a46a2548b6..2ce8dc128b 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index 611ff7f9ea..df0e2578e4 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index 6c0049c46e..e386ecdf8f 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 1a5c6bea12..42d88536e2 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index cf15e8a402..980ba6c7e9 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index df93097f57..4c5a38e08c 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index f61379719b..5a5f30e4a4 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index 078db50d14..90727265af 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index cd290e759e..e2cc4304cc 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 9951b6fa33..522e9a11c6 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index 9589b0a3ed..bc532e94da 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index bb8000ecef..80f45aeb15 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index 39d65ab502..b3b92b61f8 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index 548c1aa167..7e644bef51 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index 43931dd840..2889f011ed 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index ecdd3f3a86..4fc3af2fc1 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-build" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-transaction-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index 819e562feb..6ec654115d 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/report/Cargo.toml b/fog/ingest/report/Cargo.toml index 63734ae0ba..bd46908776 100644 --- a/fog/ingest/report/Cargo.toml +++ b/fog/ingest/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-report" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2021" diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index 1650df7e8d..1c8c6e84e1 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index b330f6c5f0..5504319674 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index 2eaaf281a8..703f7a9528 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index d56dd1847d..4a5bce5af9 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index 72a5967819..2d06a15fc4 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index 332aa4711a..3f775f73c9 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index 389d339c12..9cfae1273c 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index d4e148266e..5e3344d004 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 5e72f9fc4b..00313fc9b0 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-build" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-transaction-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index e1c296acd6..c42b8d21eb 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index 75674ec864..7bffa13b1f 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index 95b927621c..56edb7702c 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index b756af0ffe..838be85f42 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index 6bbb73717b..c93f2f03ef 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index 51cbd7c350..80a9726604 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index 81afe83b24..7a461e7b07 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index fd6a004f5c..1761115f19 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 6fcea2d857..71adf2d233 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index 538da2a2e5..2186b95b52 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index 98b4f5d5a4..5be25fcadc 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index 395954013b..eaa9557c34 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index 7881780be2..c6eddc07f8 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index bf74a21d49..653bc4a78d 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/resolver/Cargo.toml b/fog/report/resolver/Cargo.toml index 4ea199b650..63de7b0b67 100644 --- a/fog/report/resolver/Cargo.toml +++ b/fog/report/resolver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-resolver" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2021" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index ffa3484c8a..b4ea718a55 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index 2e6be6f78a..1fe74b451a 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index a569bd781f..2db33550b8 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index 2e7d614ce6..5153c8c2f4 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index e5a5bce8cc..536fc5ecf0 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index 56ba76c934..63cfc57043 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index d031ad00f6..46260b1dea 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index cf769db31e..4c48820477 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index 5d49be62ba..d7344013cd 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 6cd267d771..62a423a6a2 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index 3adceeefa7..1540363edf 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index 317e59a9fa..4fb012fc7b 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index b1e5dbcfc2..9e17f55232 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index 5d72c29580..794fc3b2f9 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index 3fc84f90d4..c505a76e01 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index af14a37bb9..0deb35d2ff 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index 0f7de79c25..3125b40eea 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index 5bb71db5b4..504747cc1c 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index 9505276270..b0594ba918 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index a1b4114911..1d6a531d6b 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-build" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-debug-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-sgx-panic-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" [[package]] name = "mc-transaction-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index 33381264f4..6140d94db0 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index d0be89198b..0bd288289c 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index 89a808a2d9..c385bce196 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index 2684cc4966..f27680bf82 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/go-grpc-gateway/testing/Cargo.toml b/go-grpc-gateway/testing/Cargo.toml index ee674a462b..b3ff0ebcc3 100644 --- a/go-grpc-gateway/testing/Cargo.toml +++ b/go-grpc-gateway/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "go-grpc-gateway-testing" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index 85c22b2674..bb7fa14913 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index f4ea4e20e4..4f013cbf9d 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index 4340ec56e0..2d6280d5cc 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index a5b05178ff..a0ee5143a3 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index c500c71372..94af389ef0 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index 0afce9ab7a..93632aa14d 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index 251019fe0b..3cf230fb65 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index 91bb0997a1..4085fcde7b 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index 0c530558f3..c32bfb0c49 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index 0c4a6b50a7..c730427074 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index bb54f141e0..0a39f3caa1 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/peers/Cargo.toml b/peers/Cargo.toml index 7c1aa0e947..465f5a95c1 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index 9b17174529..c029aba117 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index b3147c270c..d2167fe9cd 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index 2b4f6d14f0..01e7e42c76 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index e6d2f2b7f3..3e2e9106a3 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index 6d1ee25a86..d97d43affe 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index f9901fb823..1dabd4dfdc 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index f149412e75..e78f64fceb 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index 42c1222d87..8d95840d5c 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index dd3e2d17f2..2494eadd44 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index 106dcd222a..09ebb7e30b 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index 1f69f01112..3de30f72f8 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index 6f1ff0ad5f..607bb439b8 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index 4705fb38e1..9f75796653 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index c81eaeec3d..2ea63a4529 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index bb8b98707d..89660de260 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index 61d531d1d8..96a50cb79f 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index e8a666cf55..9462416289 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index af8a475fc4..3268183463 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index 65b2ac8890..b1ba09a170 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "2.1.0-pre0" +version = "3.0.0-pre0" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index 40ab13e43b..f7bcbfb924 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index 8c5dc7b391..baeef8ad0b 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index a46740ff4d..46bd48c4ca 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index b13f8a5217..2f824db1a8 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index 1cd0a247c3..64a8515ad6 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index 8cfc827b8f..b836ff332b 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index 744c1bcbff..f1995fbba4 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 80eb5e67c2..0509330c3c 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index 7b683f1725..419f3328fb 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index c2dd30f130..1b39331b0b 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index 96af6f5fcf..529db4a400 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index 2dffd452c5..a389850536 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index 8ea9434efd..ae2be60a0d 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index 1d0c02ef61..fd309dcdcc 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index 541ea4d0ca..a51de66f84 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/cli/Cargo.toml b/util/cli/Cargo.toml index 7e08942728..463620d1bb 100644 --- a/util/cli/Cargo.toml +++ b/util/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-cli" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index 2e2ecce7e3..f24932b6d9 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index 34cfa8fb68..b51de8b943 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index 53b245dff7..6e0e3634c7 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index ca4d15d402..83794c022c 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index fb69dae743..3d07b16511 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index 542c77a15f..46e2b62581 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index afd4e843d4..8a69173c53 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 796c1d23f3..94d86467c5 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index 51b24989c0..78222d6e9e 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index 097964a0ed..c2c95bf194 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index c2ebd03ffd..70a2093d47 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index 72b702774e..8d8682096d 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index d011f19bd3..745fc96590 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index 3b172ba2a9..f1334b1a72 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index 91fc3cc3f3..b2953d4c2d 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index 071a0738b6..876893630c 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index fbf2a4624c..f382db4873 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index 7bc4a99335..c7b1931580 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index 280f764344..110597f2c3 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index 3510f44542..7a8448c1df 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index 013c00a6c5..2b285df40e 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index 437d9af158..bd1f8c3d42 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/wasm-test/Cargo.toml b/wasm-test/Cargo.toml index fded2120a6..2d1d689983 100644 --- a/wasm-test/Cargo.toml +++ b/wasm-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-wasm-test" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2021" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index 52c256f0dc..6b35e1a2f1 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index 579e87732e..73dc41425f 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "2.1.0-pre0" +version = "3.0.0-pre0" authors = ["MobileCoin"] edition = "2018" From 0502872d23b552cb4759c3e5c1f102539d819394 Mon Sep 17 00:00:00 2001 From: James Cape Date: Mon, 24 Oct 2022 11:45:17 -0700 Subject: [PATCH 69/77] Update CHANGELOG.md for 3.0.0 (#2761) * Bump versions to 3.0.0-pre0 * Update CHANGELOG.md for 3.0.0 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfe4cf1523..ebe4f0ece8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem ## Unreleased -## [2.1.0] +## [3.0.0] ### Added @@ -31,6 +31,7 @@ The crates in this repository do not adhere to [Semantic Versioning](https://sem ### Security - TOB-MCCT-4: Make minting nonces unique per-token. +- Build with SGX SDK 2.17.1 to mitigate and account for INTEL-SA-00657. ## [2.0.0] - 2022-07-25 From 532c32d3ca230cb445a5cb2d7a6a5885704f967a Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Mon, 24 Oct 2022 14:17:35 -0500 Subject: [PATCH 70/77] release/v3.0 - CI/CD - CD on PR (#2762) * CD on PR * disable CD on dependabot generated PRs --- .github/workflows/mobilecoin-dev-cd.yaml | 358 ++++++++++-------- .github/workflows/mobilecoin-dev-delete.yaml | 2 +- .../mobilecoin-dispatch-dev-delete.yaml | 3 +- .../mobilecoin-dispatch-dev-deploy.yaml | 17 +- .../mobilecoin-dispatch-dev-test.yaml | 21 +- ...ilecoin-dispatch-dev-update-consensus.yaml | 3 +- .../mobilecoin-workflow-dev-deploy.yaml | 76 ++-- .../mobilecoin-workflow-dev-reset.yaml | 7 - .../mobilecoin-workflow-dev-test.yaml | 124 ++---- ...ilecoin-workflow-dev-update-consensus.yaml | 2 +- .internal-ci/util/metadata.sh | 98 ++--- 11 files changed, 353 insertions(+), 358 deletions(-) diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 1a86340cc4..e0eec0e08a 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -2,29 +2,43 @@ # # MobileCoin Core projects - Build, deploy to development. -name: mobilecoin-dev-cd +name: Mobilecoin CD env: CHART_REPO: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public DOCKER_ORG: mobilecoin - PREVIOUS_RELEASE: v1.1.3-dev + RELEASE_1X_TAG: v1.1.3-dev on: + pull_request: + branches: + - master + - main + - release/* + paths-ignore: + - '**.md' push: branches: + - master + - main - feature/* - release/* tags: - v[0-9]+* + paths-ignore: + - '**.md' # don't run more than one at a time for a branch/tag -concurrency: mobilecoin-dev-cd-${{ github.ref }} +concurrency: + group: mobilecoin-dev-cd-${{ github.head_ref || github.ref }} + cancel-in-progress: true jobs: ############################################ # Generate environment information ############################################ generate-metadata: + if: github.actor != 'dependabot[bot]' name: 👾 Environment Info 👾 runs-on: [self-hosted, Linux, small] outputs: @@ -33,7 +47,7 @@ jobs: docker_tag: ${{ steps.meta.outputs.docker_tag }} docker_org: ${{ env.DOCKER_ORG }} chart_repo: ${{ env.CHART_REPO }} - previous_release: ${{ env.PREVIOUS_RELEASE }} + release_1x_tag: ${{ env.RELEASE_1X_TAG }} steps: - name: Checkout @@ -58,6 +72,7 @@ jobs: # Build binaries ######################################### build-rust-hardware-projects: + if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, large] container: image: mobilecoin/rust-sgx-base:v0.0.18 @@ -171,6 +186,7 @@ jobs: path: rust_build_artifacts/ build-go-projects: + if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, large] container: image: golang:1.16.4 @@ -219,6 +235,7 @@ jobs: # Create/Refresh base runtime image ######################################## docker-base: + if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, small] steps: - name: Checkout @@ -228,7 +245,7 @@ jobs: - name: Generate Docker Tags if: "! contains(github.event.head_commit.message, '[skip docker]')" id: docker_meta - uses: docker/metadata-action@v3 + uses: docker/metadata-action@v4 with: images: ${{ env.DOCKER_ORG }}/runtime-base flavor: | @@ -238,11 +255,11 @@ jobs: - name: Set up Docker Buildx if: "! contains(github.event.head_commit.message, '[skip docker]')" - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub if: "! contains(github.event.head_commit.message, '[skip docker]')" - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -250,7 +267,7 @@ jobs: - name: Publish to DockerHub if: "! contains(github.event.head_commit.message, '[skip docker]')" id: docker_publish_dockerhub - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v3 with: build-args: | REPO_ORG=${{ env.DOCKER_ORG }} @@ -264,6 +281,7 @@ jobs: # Build/Publish public artifacts ######################################### docker: + if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, small] needs: - build-go-projects @@ -305,18 +323,18 @@ jobs: - name: Generate Docker Tags if: "! contains(github.event.head_commit.message, '[skip docker]')" id: docker_meta - uses: docker/metadata-action@v3 + uses: docker/metadata-action@v4 with: images: ${{ env.DOCKER_ORG }}/${{ matrix.image }} tags: ${{ needs.generate-metadata.outputs.docker_tag }} - name: Set up Docker Buildx if: "! contains(github.event.head_commit.message, '[skip docker]')" - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub if: "! contains(github.event.head_commit.message, '[skip docker]')" - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -324,7 +342,7 @@ jobs: - name: Publish to DockerHub if: "! contains(github.event.head_commit.message, '[skip docker]')" id: docker_publish_dockerhub - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v3 with: build-args: | REPO_ORG=${{ env.DOCKER_ORG }} @@ -339,6 +357,7 @@ jobs: tags: ${{ steps.docker_meta.outputs.tags }} charts: + if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, small] needs: - docker @@ -378,6 +397,7 @@ jobs: # Reset existing namespace ################################# dev-reset: + if: github.actor != 'dependabot[bot]' needs: - generate-metadata uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml @@ -392,174 +412,186 @@ jobs: LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} ####################################### -# Deploy previous release to namespace +# Deploy 1.x release to namespace ####################################### - previous-release-deploy: - runs-on: [self-hosted, Linux, small] + deploy-v1-bv0-release: + if: github.actor != 'dependabot[bot]' + uses: ./.github/workflows/mobilecoin-workflow-dev-deploy.yaml needs: - dev-reset - generate-metadata - steps: - - name: Deploy Release - if: "! contains(github.event.head_commit.message, '[skip previous-release-deploy]')" - uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 - with: - workflow: mobilecoin-dispatch-dev-deploy - token: ${{ secrets.ACTIONS_TOKEN }} - wait-for-completion: true - wait-for-completion-timeout: 30m - wait-for-completion-interval: 30s - display-workflow-run-url-interval: 30s - inputs: | - { - "block_version": "0", - "chart_repo": "${{ needs.generate-metadata.outputs.chart_repo }}", - "docker_image_org": "${{ needs.generate-metadata.outputs.docker_org }}", - "minting_config_enabled": "false", - "ingest_color": "blue", - "namespace": "${{ needs.generate-metadata.outputs.namespace }}", - "version": "${{ needs.generate-metadata.outputs.previous_release }}", - "client_auth_enabled": "false", - "use_static_wallet_seeds": "true" - } - - previous-release-test: - runs-on: [self-hosted, Linux, small] + with: + block_version: "0" + chart_repo: ${{ needs.generate-metadata.outputs.chart_repo }} + docker_image_org: ${{ needs.generate-metadata.outputs.docker_org }} + ingest_color: blue + minting_config_enabled: false + namespace: ${{ needs.generate-metadata.outputs.namespace }} + version: ${{ needs.generate-metadata.outputs.release_1x_tag }} + secrets: + CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + FOG_KEYS_SEED: ${{ secrets.DEV_FOG_KEYS_SEED }} + FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} + FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} + FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} + IAS_KEY: ${{ secrets.DEV_IAS_KEY }} + IAS_SPID: ${{ secrets.DEV_IAS_SPID }} + INITIAL_KEYS_SEED: ${{ secrets.DEV_INITIAL_KEYS_SEED }} + IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} + MNEMONIC_FOG_KEYS_SEED: ${{ secrets.DEV_MNEMONIC_FOG_KEYS_SEED }} + MNEMONIC_KEYS_SEED: ${{ secrets.DEV_MNEMONIC_KEYS_SEED }} + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + + test-v1-bv0-release: + if: github.actor != 'dependabot[bot]' + uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml needs: - - previous-release-deploy + - deploy-v1-bv0-release - generate-metadata - steps: - - name: Run MobileCoin integration tests - if: "! contains(github.event.head_commit.message, '[skip previous-release-test]')" - uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 - with: - workflow: mobilecoin-dispatch-dev-test - token: ${{ secrets.ACTIONS_TOKEN }} - wait-for-completion: true - wait-for-completion-timeout: 30m - wait-for-completion-interval: 30s - display-workflow-run-url-interval: 30s - inputs: | - { - "ingest_color": "blue", - "namespace": "${{ needs.generate-metadata.outputs.namespace }}", - "fog_distribution": "true", - "testing_1_1": "true", - "testing_1_2": "false", - "client_auth_enabled": "false" - } + with: + fog_distribution: true + ingest_color: blue + namespace: ${{ needs.generate-metadata.outputs.namespace }} + testing_block_v0: true + testing_block_v2: false + secrets: + CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} + FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} ############################################### -# Deploy current version to namespace block v0 +# Deploy current version to namespace block v2 ############################################### - current-release-v0-deploy: - runs-on: [self-hosted, Linux, small] + deploy-current-bv0-release: + if: github.actor != 'dependabot[bot]' + uses: ./.github/workflows/mobilecoin-workflow-dev-deploy.yaml needs: - - previous-release-test - - generate-metadata + - test-v1-bv0-release - charts - steps: - - name: Deploy Release - if: "! contains(github.event.head_commit.message, '[skip current-release-v0-deploy]')" - uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 - with: - workflow: mobilecoin-dispatch-dev-deploy - token: ${{ secrets.ACTIONS_TOKEN }} - wait-for-completion: true - wait-for-completion-timeout: 30m - wait-for-completion-interval: 30s - display-workflow-run-url-interval: 30s - inputs: | - { - "block_version": "0", - "chart_repo": "${{ needs.generate-metadata.outputs.chart_repo }}", - "docker_image_org": "${{ needs.generate-metadata.outputs.docker_org }}", - "minting_config_enabled": "true", - "ingest_color": "green", - "namespace": "${{ needs.generate-metadata.outputs.namespace }}", - "version": "${{ needs.generate-metadata.outputs.tag }}", - "client_auth_enabled": "false", - "use_static_wallet_seeds": "true" - } - - current-release-v0-test: - runs-on: [self-hosted, Linux, small] + - generate-metadata + with: + block_version: "0" + chart_repo: ${{ needs.generate-metadata.outputs.chart_repo }} + docker_image_org: ${{ needs.generate-metadata.outputs.docker_org }} + ingest_color: green + minting_config_enabled: true + namespace: ${{ needs.generate-metadata.outputs.namespace }} + version: ${{ needs.generate-metadata.outputs.tag }} + secrets: + CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + FOG_KEYS_SEED: ${{ secrets.DEV_FOG_KEYS_SEED }} + FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} + FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} + FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} + IAS_KEY: ${{ secrets.DEV_IAS_KEY }} + IAS_SPID: ${{ secrets.DEV_IAS_SPID }} + INITIAL_KEYS_SEED: ${{ secrets.DEV_INITIAL_KEYS_SEED }} + IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} + MNEMONIC_FOG_KEYS_SEED: ${{ secrets.DEV_MNEMONIC_FOG_KEYS_SEED }} + MNEMONIC_KEYS_SEED: ${{ secrets.DEV_MNEMONIC_KEYS_SEED }} + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + + test-current-bv0-release: + if: github.actor != 'dependabot[bot]' + uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml needs: - - current-release-v0-deploy + - deploy-current-bv0-release - generate-metadata - steps: - - name: Run MobileCoin integration tests - if: "! contains(github.event.head_commit.message, '[skip current-release-v0-test]')" - uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 - with: - workflow: mobilecoin-dispatch-dev-test - token: ${{ secrets.ACTIONS_TOKEN }} - wait-for-completion: true - wait-for-completion-timeout: 30m - wait-for-completion-interval: 30s - display-workflow-run-url-interval: 30s - inputs: | - { - "namespace": "${{ needs.generate-metadata.outputs.namespace }}", - "ingest_color": "green", - "fog_distribution": "false", - "testing_1_1": "true", - "testing_1_2": "false", - "client_auth_enabled": "false" - } + with: + fog_distribution: false + ingest_color: green + namespace: ${{ needs.generate-metadata.outputs.namespace }} + testing_block_v0: true + testing_block_v2: false + + secrets: + CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} + FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} ################################################# -# Update current consensus to namespace block v1 +# Update current consensus to namespace block v3 ################################################# - current-release-v2-update: - runs-on: [self-hosted, Linux, small] + update-current-to-bv2: + if: github.actor != 'dependabot[bot]' + uses: ./.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml needs: - - current-release-v0-test + - test-current-bv0-release - generate-metadata - steps: - - name: Update consensus config - if: "! contains(github.event.head_commit.message, '[skip current-release-v2-update]')" - uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 - with: - workflow: mobilecoin-dispatch-dev-update-consensus - token: ${{ secrets.ACTIONS_TOKEN }} - wait-for-completion: true - wait-for-completion-timeout: 30m - wait-for-completion-interval: 30s - display-workflow-run-url-interval: 30s - inputs: | - { - "block_version": "2", - "client_auth_enabled": "false", - "minting_config_enabled": "true", - "docker_image_org": "${{ needs.generate-metadata.outputs.docker_org }}", - "chart_repo": "${{ needs.generate-metadata.outputs.chart_repo }}", - "namespace": "${{ needs.generate-metadata.outputs.namespace }}", - "version": "${{ needs.generate-metadata.outputs.tag }}" - } - - current-release-v2-test: - runs-on: [self-hosted, Linux, small] + with: + block_version: "2" + chart_repo: ${{ needs.generate-metadata.outputs.chart_repo }} + docker_image_org: ${{ needs.generate-metadata.outputs.docker_org }} + minting_config_enabled: true + namespace: ${{ needs.generate-metadata.outputs.namespace }} + version: ${{ needs.generate-metadata.outputs.tag }} + secrets: + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} + FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} + IAS_KEY: ${{ secrets.DEV_IAS_KEY }} + IAS_SPID: ${{ secrets.DEV_IAS_SPID }} + IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + + test-current-bv2-release: + if: github.actor != 'dependabot[bot]' + uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml needs: - - current-release-v2-update + - update-current-to-bv2 - generate-metadata - steps: - - name: Run MobileCoin integration tests - if: "! contains(github.event.head_commit.message, '[skip current-release-v2-test]')" - uses: mobilecoinofficial/gha-workflow-dispatch@v2.1.3 - with: - workflow: mobilecoin-dispatch-dev-test - token: ${{ secrets.ACTIONS_TOKEN }} - wait-for-completion: true - wait-for-completion-timeout: 30m - wait-for-completion-interval: 30s - display-workflow-run-url-interval: 30s - inputs: | - { - "namespace": "${{ needs.generate-metadata.outputs.namespace }}", - "ingest_color": "green", - "fog_distribution": "false", - "testing_1_1": "true", - "testing_1_2": "true", - "client_auth_enabled": "false" - } + with: + fog_distribution: false + ingest_color: green + namespace: ${{ needs.generate-metadata.outputs.namespace }} + testing_block_v0: false + testing_block_v2: true + secrets: + CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} + FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + + cleanup-on-pr: + if: | + github.actor != 'dependabot[bot]' && + github.event_name == 'pull_request' + needs: + - test-current-bv2-release + - generate-metadata + uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml + with: + namespace: ${{ needs.generate-metadata.outputs.namespace }} + delete_namespace: true + secrets: + RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} + RANCHER_URL: ${{ secrets.RANCHER_URL }} + RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + diff --git a/.github/workflows/mobilecoin-dev-delete.yaml b/.github/workflows/mobilecoin-dev-delete.yaml index 10ddc4c06d..ece72018cc 100644 --- a/.github/workflows/mobilecoin-dev-delete.yaml +++ b/.github/workflows/mobilecoin-dev-delete.yaml @@ -2,7 +2,7 @@ # # MobileCoin Core projects - Delete development namespaces when branch is removed. -name: mobilecoin-dev-delete +name: Mobilecoin Dev Clean Up on: delete: {} diff --git a/.github/workflows/mobilecoin-dispatch-dev-delete.yaml b/.github/workflows/mobilecoin-dispatch-dev-delete.yaml index a7d655f54b..0fcd7a1e2a 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-delete.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-delete.yaml @@ -2,7 +2,7 @@ # # MobileCoin Core projects - Dispatch (manual) Job - Delete target dev env components and optionally the k8s namespace. -name: mobilecoin-dispatch-dev-delete +name: (Manual) Delete a Dev Namespace on: workflow_dispatch: @@ -19,6 +19,7 @@ on: jobs: reset: + name: Reset Dev Namespace - ${{ inputs.namespace }} uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml with: namespace: ${{ inputs.namespace }} diff --git a/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml b/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml index c9cb6ad695..a286445ef1 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml @@ -2,7 +2,7 @@ # # MobileCoin Core projects - Dispatch (manual) Job - Deploy core apps to the development namespace. -name: mobilecoin-dispatch-dev-deploy +name: (Manual) Deploy to Dev Namespace on: workflow_dispatch: @@ -52,6 +52,21 @@ on: default: false jobs: + list-values: + name: 👾 Environment Info - ${{ github.event.inputs.namespace }} - ${{ github.event.inputs.version }} 👾 + runs-on: [self-hosted, Linux, small] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: 👾 Print Environment Details 👾 + env: + CHART_REPO: ${{ github.event.inputs.chart_repo }} + NAMESPACE: ${{ github.event.inputs.namespace }} + VERSION: ${{ github.event.inputs.version }} + run: | + .internal-ci/util/print_details.sh + deploy: uses: ./.github/workflows/mobilecoin-workflow-dev-deploy.yaml with: diff --git a/.github/workflows/mobilecoin-dispatch-dev-test.yaml b/.github/workflows/mobilecoin-dispatch-dev-test.yaml index bfef097326..8695182dbf 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-test.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-test.yaml @@ -2,7 +2,7 @@ # # MobileCoin Core projects - Dispatch (manual) Job - Run integration tests in a development namespace. -name: mobilecoin-dispatch-dev-test +name: (Manual) Run Tests in Dev Namespace on: workflow_dispatch: @@ -20,14 +20,19 @@ on: description: "Run fog-distribution test" type: boolean required: false + default: false + testing_block_v0: + description: "Run block v0 tests" + type: boolean + required: false default: true - testing_1_1: - description: "Run v1.1.x tests (block_version 0)" + testing_block_v2: + description: "Run block v2 tests" type: boolean required: false default: true - testing_1_2: - description: "Run v1.2.x tests (block_version 0/2)" + testing_block_v3: + description: "Run block v3 tests" type: boolean required: false default: true @@ -39,13 +44,15 @@ on: jobs: test: + name: Test ${{ github.event.inputs.namespace }} - ${{ github.event.inputs.ingest_color }} uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml with: namespace: ${{ github.event.inputs.namespace }} ingest_color: ${{ github.event.inputs.ingest_color }} fog_distribution: ${{ github.event.inputs.fog_distribution == 'true' && 'true' || 'false' }} - testing_1_1 : ${{ github.event.inputs.testing_1_1 == 'true' && 'true' || 'false' }} - testing_1_2: ${{ github.event.inputs.testing_1_2 == 'true' && 'true' || 'false' }} + testing_block_v0 : ${{ github.event.inputs.testing_block_v0 == 'true' && 'true' || 'false' }} + testing_block_v2: ${{ github.event.inputs.testing_block_v2 == 'true' && 'true' || 'false' }} + testing_block_v3: ${{ github.event.inputs.testing_block_v3 == 'true' && 'true' || 'false' }} secrets: RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} RANCHER_URL: ${{ secrets.RANCHER_URL }} diff --git a/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml b/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml index e7a22a9d21..09f50f84ea 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml @@ -2,7 +2,7 @@ # # MobileCoin Core projects - Dispatch (manual) Job - Update consensus nodes in a development namespace. -name: mobilecoin-dispatch-dev-update-consensus +name: (Manual) Upgrade Consensus Config in Dev Namespace on: workflow_dispatch: @@ -43,6 +43,7 @@ on: jobs: update-consensus-block-version: + name: Update Consensus Block Version - ${{ github.event.inputs.namespace }} - ${{ github.event.inputs.block_version }} uses: ./.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml with: namespace: ${{ github.event.inputs.namespace }} diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml index 5b2a2d3d62..ec11508508 100644 --- a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -100,31 +100,10 @@ on: description: "static wallet seed" required: false -jobs: - list-values: - name: 👾 Environment Info 👾 - runs-on: [self-hosted, Linux, small] - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: List input values - run: | - echo namespace ${{ inputs.namespace }} - echo version ${{ inputs.version }} - echo docker_image_org ${{ inputs.docker_image_org }} - echo ingest_color ${{ inputs.ingest_color }} - echo minting_config_enabled ${{ inputs.minting_config_enabled }} - echo chart_repo ${{ inputs.chart_repo }} - - - name: 👾 Print Environment Details 👾 - env: - CHART_REPO: ${{ inputs.chart_repo }} - NAMESPACE: ${{ inputs.namespace }} - VERSION: ${{ inputs.version }} - run: | - .internal-ci/util/print_details.sh +env: + FLIPSIDE: ${{ inputs.ingest_color == 'blue' && 'green' || 'blue' }} +jobs: # Reset consensus nodes between releases - if there's existing data, we'll # restore from S3. reset-releases: @@ -210,7 +189,7 @@ jobs: - name: Login to DockerHub if: inputs.minting_config_enabled == 'true' - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -343,12 +322,36 @@ jobs: rancher_url: ${{ secrets.RANCHER_URL }} rancher_token: ${{ secrets.RANCHER_TOKEN }} - fog-ingest-deploy: + fog-services-deploy: needs: - postgresql-deploy - consensus-deploy runs-on: [self-hosted, Linux, small] steps: + - name: Deploy fog-services + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: ${{ inputs.chart_repo }} + chart_name: fog-services + chart_version: ${{ inputs.version }} + chart_wait_timeout: 10m + # Set orderedReady for compatibility with 1.1.3 chart - remove after 1.2.x + chart_set: | + --set=image.org=${{ inputs.docker_image_org }} + --set=global.certManagerClusterIssuer=zerossl-prod-http + --set=fogLedger.podManagementPolicy=OrderedReady + release_name: fog-services + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + fog-ingest-deploy: + needs: + - fog-services-deploy + runs-on: [self-hosted, Linux, small] + steps: - name: Deploy fog-ingest uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: @@ -387,27 +390,12 @@ jobs: rancher_url: ${{ secrets.RANCHER_URL }} rancher_token: ${{ secrets.RANCHER_TOKEN }} - fog-services-deploy: - needs: - - postgresql-deploy - - consensus-deploy - runs-on: [self-hosted, Linux, small] - steps: - - name: Deploy fog-services + - name: Delete retired flipside ingest (if exists) uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: - action: helm-deploy - chart_repo: ${{ inputs.chart_repo }} - chart_name: fog-services - chart_version: ${{ inputs.version }} - chart_wait_timeout: 10m - # Set orderedReady for compatibility with 1.1.3 chart - remove after 1.2.x - chart_set: | - --set=image.org=${{ inputs.docker_image_org }} - --set=global.certManagerClusterIssuer=zerossl-prod-http - --set=fogLedger.podManagementPolicy=OrderedReady - release_name: fog-services + action: helm-release-delete namespace: ${{ inputs.namespace }} + release_name: fog-ingest-${{ env.FLIPSIDE }} rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} rancher_url: ${{ secrets.RANCHER_URL }} rancher_token: ${{ secrets.RANCHER_TOKEN }} diff --git a/.github/workflows/mobilecoin-workflow-dev-reset.yaml b/.github/workflows/mobilecoin-workflow-dev-reset.yaml index 0de06eed91..c6f1ce5f88 100644 --- a/.github/workflows/mobilecoin-workflow-dev-reset.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-reset.yaml @@ -36,13 +36,6 @@ on: required: true jobs: - list-values: - runs-on: [self-hosted, Linux, small] - steps: - - name: values - run: | - echo namespace ${{ inputs.namespace }} - reset-releases: runs-on: [self-hosted, Linux, small] strategy: diff --git a/.github/workflows/mobilecoin-workflow-dev-test.yaml b/.github/workflows/mobilecoin-workflow-dev-test.yaml index 3eb8cf6436..dbe25ec82b 100644 --- a/.github/workflows/mobilecoin-workflow-dev-test.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-test.yaml @@ -37,7 +37,6 @@ # - All tests run with in the kubernetes namespace context so we can reach internally hosted endpoints, # like mobilecoind. (CBB: add full-service?) # -# CBB: make tests work if client_auth_token is enabled. Will require generating the auth tokens. name: mobilecoin-workflow-dev-test @@ -57,13 +56,13 @@ on: type: string required: false default: 'true' - testing_1_1: - description: "Run v1.1.x tests (block_version 0)" + testing_block_v0: + description: "Run block v0 tests" type: string required: false default: 'true' - testing_1_2: - description: "Run v1.2.x tests (block_version 0/2" + testing_block_v2: + description: "Run block v2 tests" type: string required: false default: 'true' @@ -88,21 +87,16 @@ on: required: false jobs: - list-values: - runs-on: [self-hosted, Linux, small] - steps: - - name: values - run: | - echo namespace ${{ inputs.namespace }} - echo ingest_color ${{ inputs.ingest_color }} - echo fog_distribution ${{ inputs.fog_distribution }} - echo testing_1_1 ${{ inputs.testing_1_1 }} - echo testing_1_2 ${{ inputs.testing_1_2 }} - - setup-environment: + cd-integration-tests: runs-on: [self-hosted, Linux, small] env: FOG_REPORT_SIGNING_CA_CERT_PATH: .tmp/fog_report_signing_ca_cert.pem + SRC_KEYS_DIR: /tmp/sample_data/keys + SRC_FOG_KEYS_DIR: /tmp/sample_data/fog_keys + V2_DST_KEYS_DIR: /tmp/2-testing/keys + V2_DST_FOG_KEYS_DIR: /tmp/2-testing/fog_keys + START_KEYS: '494' + END_KEYS: '499' steps: - name: Checkout uses: actions/checkout@v3 @@ -134,12 +128,6 @@ jobs: FOG_REPORT_URL="fog://fog.${{ inputs.namespace }}.development.mobilecoin.com:443" \ /util/generate_origin_data.sh - fog-distribution: - name: fog-distribution ${{ inputs.fog_distribution == 'true' && '(run)' || '(skipped)' }} - runs-on: [self-hosted, Linux, small] - needs: - - setup-environment - steps: - name: Test - fog-distribution if: inputs.fog_distribution == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 @@ -153,14 +141,8 @@ jobs: command: | /test/fog-distribution-test.sh - testing-1-1: - name: testing-1-1 ${{ inputs.testing_1_1 == 'true' && '(run)' || '(skipped)' }} - runs-on: [self-hosted, Linux, small] - needs: - - fog-distribution - steps: - - name: Test - fog-test-client - if: inputs.testing_1_1 == 'true' + - name: Test - block-v0 - fog-test-client + if: inputs.testing_block_v0 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -182,9 +164,8 @@ jobs: --fog-view fog-view://${{ secrets.CLIENT_AUTH_USER_VALUE }}fog.${{ inputs.namespace }}.development.mobilecoin.com:443 \ --fog-ledger fog-ledger://${{ secrets.CLIENT_AUTH_USER_VALUE }}fog.${{ inputs.namespace }}.development.mobilecoin.com:443 - - - name: Test - mobilecoind-grpc (previously Wallet Integration) - if: inputs.testing_1_1 == 'true' + - name: Test - block-v0 - mobilecoind-grpc (previously Wallet Integration) + if: inputs.testing_block_v0 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -196,21 +177,8 @@ jobs: command: | /test/mobilecoind-integration-test.sh - testing-1-2: - name: Testing for v1.2.x ${{ inputs.testing_1_2 == 'true' && '(run)' || '(skipped)' }} - runs-on: [self-hosted, Linux, small] - needs: - - testing-1-1 - env: - SRC_KEYS_DIR: /tmp/sample_data/keys - SRC_FOG_KEYS_DIR: /tmp/sample_data/fog_keys - DST_KEYS_DIR: /tmp/1.2-testing/keys - DST_FOG_KEYS_DIR: /tmp/1.2-testing/fog_keys - START_KEYS: '494' - END_KEYS: '499' - steps: - - name: Copy subset of non-fog keys - if: inputs.testing_1_2 == 'true' + - name: Setup - block-v2 - Copy subset of non-fog keys + if: inputs.testing_block_v2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -222,12 +190,12 @@ jobs: command: | /util/copy_account_keys.sh \ --src ${{ env.SRC_KEYS_DIR }} \ - --dst ${{ env.DST_KEYS_DIR }} \ + --dst ${{ env.V2_DST_KEYS_DIR }} \ --start ${{ env.START_KEYS }} \ --end ${{ env.END_KEYS }} - - name: Copy subset of fog keys - if: inputs.testing_1_2 == 'true' + - name: Setup - block-v2 - Copy subset of fog keys + if: inputs.testing_block_v2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -239,12 +207,12 @@ jobs: command: | /util/copy_account_keys.sh \ --src ${{ env.SRC_FOG_KEYS_DIR }} \ - --dst ${{ env.DST_FOG_KEYS_DIR }} \ + --dst ${{ env.V2_DST_FOG_KEYS_DIR }} \ --start ${{ env.START_KEYS }} \ --end ${{ env.END_KEYS }} - - name: Test - Minting config tx - if: inputs.testing_1_2 == 'true' + - name: Test - block-v2 - Minting config tx + if: inputs.testing_block_v2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -257,8 +225,8 @@ jobs: /test/minting-config-tx-test.sh \ --token-id 8192 - - name: Test - Minting tx - if: inputs.testing_1_2 == 'true' + - name: Test - block-v2 - Minting tx + if: inputs.testing_block_v2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -269,11 +237,11 @@ jobs: rancher_token: ${{ secrets.RANCHER_TOKEN }} command: | /test/minting-tx-test.sh \ - --key-dir ${{ env.DST_KEYS_DIR }} \ + --key-dir ${{ env.V2_DST_KEYS_DIR }} \ --token-id 8192 - - name: Test - mobilecoind-json integration - if: inputs.testing_1_2 == 'true' + - name: Test - block-v2 - mobilecoind-json integration + if: inputs.testing_block_v2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -284,24 +252,10 @@ jobs: rancher_token: ${{ secrets.RANCHER_TOKEN }} command: | /test/mobilecoind-json-integration-test.sh \ - --key-dir ${{ env.DST_KEYS_DIR }} - - - name: Test - mint-auditor - if: inputs.testing_1_2 == 'true' - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: toolbox-exec - ingest_color: ${{ inputs.ingest_color }} - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} - command: | - /test/mint-auditor-test.sh \ - --token-id 8192 --token-fee 1024 + --key-dir ${{ env.V2_DST_KEYS_DIR }} - - name: Test - use drain_accounts to transfer id 8192 balances to fog keys - if: inputs.testing_1_2 == 'true' + - name: Test - block-v2 - use drain_accounts to transfer id 1 balances to fog keys + if: inputs.testing_block_v2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -312,13 +266,13 @@ jobs: rancher_token: ${{ secrets.RANCHER_TOKEN }} command: | /util/drain_accounts.sh \ - --src ${{ env.DST_KEYS_DIR }} \ - --dst ${{ env.DST_FOG_KEYS_DIR }} \ + --src ${{ env.V2_DST_KEYS_DIR }} \ + --dst ${{ env.V2_DST_FOG_KEYS_DIR }} \ --fee 1024 \ --token-id 8192 - - name: Test - fog-test-client token id 0 - if: inputs.testing_1_2 == 'true' + - name: Test - block-v2 - fog-test-client token id 0 + if: inputs.testing_block_v2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -329,11 +283,11 @@ jobs: rancher_token: ${{ secrets.RANCHER_TOKEN }} command: | /test/fog-test-client.sh \ - --key-dir ${{ env.DST_FOG_KEYS_DIR }} \ + --key-dir ${{ env.V2_DST_FOG_KEYS_DIR }} \ --token-id 0 - - name: Test - fog-test-client token id 1 - if: inputs.testing_1_2 == 'true' + - name: Test - block-v2 - fog-test-client token id 1 + if: inputs.testing_block_v2 == 'true' uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -344,5 +298,5 @@ jobs: rancher_token: ${{ secrets.RANCHER_TOKEN }} command: | /test/fog-test-client.sh \ - --key-dir ${{ env.DST_FOG_KEYS_DIR }} \ + --key-dir ${{ env.V2_DST_FOG_KEYS_DIR }} \ --token-id 8192 diff --git a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml index 5a387a65f5..ea887ba164 100644 --- a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml @@ -94,7 +94,7 @@ jobs: - name: Login to DockerHub if: inputs.minting_config_enabled == 'true' - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.internal-ci/util/metadata.sh b/.internal-ci/util/metadata.sh index 07cd692064..340196d73e 100755 --- a/.internal-ci/util/metadata.sh +++ b/.internal-ci/util/metadata.sh @@ -32,9 +32,17 @@ is_set GITHUB_SHA # Make sure prefix is less that 18 characters or k8s limits. namespace_prefix="mc" -branch="${GITHUB_REF_NAME}" sha="sha-${GITHUB_SHA:0:8}" +# Set branch name. Where we get this ref is different for branch, pull_request or delete event +branch="${GITHUB_REF_NAME}" + +# Override branch name with head when event is a PR +if [[ -n "${GITHUB_HEAD_REF}" ]] +then + branch="${GITHUB_HEAD_REF}" +fi + # Override branch with delete ref if set. if [[ -n "${DELETE_REF_NAME}" ]] then @@ -73,48 +81,41 @@ case "${GITHUB_REF_TYPE}" in is_set tag is_set docker_tag ;; + # Branches and pull requests will set type as branch. + # Don't filter on "valid" branches, rely on workflows to filter out their accepted events. branch) - # Check for valid branches. Using case if we want add more or split branch types later. - case "${branch}" in - release/*|feature/*) - # All branch builds will just have a "dummy" tag. - version="v0" - - echo "Clean up branch. Remove feature|deploy|release prefix and replace ._/ with -" - normalized_branch="$(normalize_ref_name "${branch}")" - - # Check and truncate branch name if total tag length exceeds the 63 character K8s label value limit. - label_limit=63 - version_len=${#version} - sha_len=${#sha} - run_number_len=${#GITHUB_RUN_NUMBER} - # number of separators in tag - dots=3 - - cutoff=$((label_limit - version_len - sha_len - run_number_len - dots)) - - if [[ ${#normalized_branch} -gt ${cutoff} ]] - then - cut_branch=$(echo "${normalized_branch}" | cut -c -${cutoff}) - echo "Your branch name ${normalized_branch} + metadata exceeds the maximum length for K8s identifiers, truncating to ${cut_branch}" - normalized_branch="${cut_branch}" - fi - - echo "Before: '${branch}'" - echo "After: '${normalized_branch}'" - - # Set artifact tag - tag="${version}-${normalized_branch}.${GITHUB_RUN_NUMBER}.${sha}" - # Set docker metadata action compatible tag - docker_tag="type=raw,value=${tag}" - # Set namespace from normalized branch value - namespace="${namespace_prefix}-${normalized_branch}" - ;; - *) - echo "Branch: ${branch} is not a release/ or feature/ branch" - exit 1 - ;; - esac + # All branch builds will just have a "dummy" tag. + version="v0" + + echo "Clean up branch. Remove feature|deploy|release prefix and replace ._/ with -" + normalized_branch="$(normalize_ref_name "${branch}")" + + # Check and truncate branch name if total tag length exceeds the 63 character K8s label value limit. + label_limit=63 + version_len=${#version} + sha_len=${#sha} + run_number_len=${#GITHUB_RUN_NUMBER} + # number of separators in tag + dots=3 + + cutoff=$((label_limit - version_len - sha_len - run_number_len - dots)) + + if [[ ${#normalized_branch} -gt ${cutoff} ]] + then + cut_branch=$(echo "${normalized_branch}" | cut -c -${cutoff}) + echo "Your branch name ${normalized_branch} + metadata exceeds the maximum length for K8s identifiers, truncating to ${cut_branch}" + normalized_branch="${cut_branch}" + fi + + echo "Before: '${branch}'" + echo "After: '${normalized_branch}'" + + # Set artifact tag + tag="${version}-${normalized_branch}.${GITHUB_RUN_NUMBER}.${sha}" + # Set docker metadata action compatible tag + docker_tag="type=raw,value=${tag}" + # Set namespace from normalized branch value + namespace="${namespace_prefix}-${normalized_branch}" ;; *) echo "${GITHUB_REF_TYPE} is an unknown GitHub Reference Type" @@ -122,8 +123,11 @@ case "${GITHUB_REF_TYPE}" in ;; esac -echo "::set-output name=version::${version}" -echo "::set-output name=namespace::${namespace}" -echo "::set-output name=sha::${sha}" -echo "::set-output name=tag::${tag}" -echo "::set-output name=docker_tag::${docker_tag}" +# Set GHA output vars +cat <> "${GITHUB_OUTPUT}" +version=${version} +namespace=${namespace} +sha=${sha} +tag=${tag} +docker_tag=${docker_tag} +EOF From 9617d7a916b3947a328706271f06a4e2faa46644 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Mon, 24 Oct 2022 16:28:06 -0500 Subject: [PATCH 71/77] set runtime sgx package version to 2.17.100.3-focal1 (#2765) --- .internal-ci/docker/Dockerfile.runtime-base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.internal-ci/docker/Dockerfile.runtime-base b/.internal-ci/docker/Dockerfile.runtime-base index e463261aff..8fff105b34 100644 --- a/.internal-ci/docker/Dockerfile.runtime-base +++ b/.internal-ci/docker/Dockerfile.runtime-base @@ -31,7 +31,7 @@ ENV LD_LIBRARY_PATH="/opt/intel/sgx-aesm-service/aesm" # libsgx-enclave-common libsgx-epid libsgx-launch libsgx-pce-logic libsgx-urts # sgx-aesm-service # Use `apt show -a sgx-aesm-service` to find version -ENV AESM_VERSION=2.17.101.1-focal1 +ENV AESM_VERSION=2.17.100.3-focal1 # Use `apt show -a libsgx-pce-logic` to find the version thats compatible with aesm. ENV PCE_LOGIC_VERSION=1.14.100.3-focal1 From fd1b3ae2808ee2b9a923e814753c4ff71b42084b Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Tue, 25 Oct 2022 17:30:47 -0500 Subject: [PATCH 72/77] V3 - CI/CD - Fix docker tags (#2770) * Fix multiline docker tags * fix version creation --- .github/workflows/mobilecoin-dev-cd.yaml | 8 ++++---- .internal-ci/util/metadata.sh | 22 +++++++++++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index e0eec0e08a..146f8321ed 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -187,7 +187,7 @@ jobs: build-go-projects: if: github.actor != 'dependabot[bot]' - runs-on: [self-hosted, Linux, large] + runs-on: [self-hosted, Linux, small] container: image: golang:1.16.4 steps: @@ -326,7 +326,8 @@ jobs: uses: docker/metadata-action@v4 with: images: ${{ env.DOCKER_ORG }}/${{ matrix.image }} - tags: ${{ needs.generate-metadata.outputs.docker_tag }} + tags: | + ${{ needs.generate-metadata.outputs.docker_tag }} - name: Set up Docker Buildx if: "! contains(github.event.head_commit.message, '[skip docker]')" @@ -580,7 +581,7 @@ jobs: cleanup-on-pr: if: | github.actor != 'dependabot[bot]' && - github.event_name == 'pull_request' + (github.event_name == 'pull_request' || github.ref_type == 'tag') needs: - test-current-bv2-release - generate-metadata @@ -594,4 +595,3 @@ jobs: RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - diff --git a/.internal-ci/util/metadata.sh b/.internal-ci/util/metadata.sh index 340196d73e..8a7ea4a3a9 100755 --- a/.internal-ci/util/metadata.sh +++ b/.internal-ci/util/metadata.sh @@ -13,7 +13,8 @@ is_set() var_name="${1}" if [ -z "${!var_name}" ]; then - error_exit "${var_name} is not set." + echo "${var_name} is not set." + exit 1 fi } @@ -64,17 +65,20 @@ case "${GITHUB_REF_TYPE}" in echo "Found pre-release tag." # set artifact tag tag="${version}" - docker_tag="type=raw,value=${version},priority=20%0Atype=raw,value=${version}.${GITHUB_RUN_NUMBER}.${sha},priority=10" else echo "Found release tag." # set artifact tag tag="${version}-dev" - #set docker metadata action compatible tag. Short tag + metadata tag. - docker_tag="type=raw,value=${version}-dev,priority=20%0Atype=raw,value=${version}-dev.${GITHUB_RUN_NUMBER}.${sha},priority=10" fi - normalized_tag=$(normalize_ref_name "${tag}") + # Set docker metadata action compatible tag. Short tag + metadata tag. + docker_tag=$(cat << EOF +type=raw,value=${version},priority=20 +type=raw,value=${version}.${GITHUB_RUN_NUMBER}.${sha},priority=10 +EOF +) + normalized_tag=$(normalize_ref_name "${tag}") namespace="${namespace_prefix}-${normalized_tag}" # just make sure we have these set to avoid weird edge cases. @@ -124,10 +128,14 @@ case "${GITHUB_REF_TYPE}" in esac # Set GHA output vars -cat <> "${GITHUB_OUTPUT}" +cat <> "${GITHUB_OUTPUT}" version=${version} namespace=${namespace} sha=${sha} tag=${tag} -docker_tag=${docker_tag} +docker_tag< Date: Tue, 25 Oct 2022 16:18:43 -0700 Subject: [PATCH 73/77] Bump enclave security versions. (#2773) --- consensus/enclave/measurement/build.rs | 2 +- fog/ingest/enclave/measurement/build.rs | 2 +- fog/ledger/enclave/measurement/build.rs | 2 +- fog/view/enclave/measurement/build.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/consensus/enclave/measurement/build.rs b/consensus/enclave/measurement/build.rs index ec0030f1cc..c37fb0ef8c 100644 --- a/consensus/enclave/measurement/build.rs +++ b/consensus/enclave/measurement/build.rs @@ -13,7 +13,7 @@ use std::{env::var, path::PathBuf}; const SGX_VERSION: &str = "2.17.101.1"; const CONSENSUS_ENCLAVE_PRODUCT_ID: u16 = 1; -const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 5; +const CONSENSUS_ENCLAVE_SECURITY_VERSION: u16 = 6; const CONSENSUS_ENCLAVE_NAME: &str = "consensus-enclave"; const CONSENSUS_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/ingest/enclave/measurement/build.rs b/fog/ingest/enclave/measurement/build.rs index 98d4b976f4..d6ed832505 100644 --- a/fog/ingest/enclave/measurement/build.rs +++ b/fog/ingest/enclave/measurement/build.rs @@ -13,7 +13,7 @@ use std::{env::var, path::PathBuf}; const SGX_VERSION: &str = "2.17.101.1"; const INGEST_ENCLAVE_PRODUCT_ID: u16 = 4; -const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 4; +const INGEST_ENCLAVE_SECURITY_VERSION: u16 = 5; const INGEST_ENCLAVE_NAME: &str = "ingest-enclave"; const INGEST_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/ledger/enclave/measurement/build.rs b/fog/ledger/enclave/measurement/build.rs index fdc444e4f6..b907e7e725 100644 --- a/fog/ledger/enclave/measurement/build.rs +++ b/fog/ledger/enclave/measurement/build.rs @@ -13,7 +13,7 @@ use std::{env::var, path::PathBuf}; const SGX_VERSION: &str = "2.17.101.1"; const LEDGER_ENCLAVE_PRODUCT_ID: u16 = 2; -const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 4; +const LEDGER_ENCLAVE_SECURITY_VERSION: u16 = 5; const LEDGER_ENCLAVE_NAME: &str = "ledger-enclave"; const LEDGER_ENCLAVE_DIR: &str = "../trusted"; diff --git a/fog/view/enclave/measurement/build.rs b/fog/view/enclave/measurement/build.rs index 93b86ab54a..7134810cc9 100644 --- a/fog/view/enclave/measurement/build.rs +++ b/fog/view/enclave/measurement/build.rs @@ -13,7 +13,7 @@ use std::{env::var, path::PathBuf}; const SGX_VERSION: &str = "2.17.101.1"; const VIEW_ENCLAVE_PRODUCT_ID: u16 = 3; -const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 4; +const VIEW_ENCLAVE_SECURITY_VERSION: u16 = 5; const VIEW_ENCLAVE_NAME: &str = "view-enclave"; const VIEW_ENCLAVE_DIR: &str = "../trusted"; From b22e993dc97b025b2282ff68c53c86a0e85d9591 Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 26 Oct 2022 11:48:01 -0700 Subject: [PATCH 74/77] Bump all versions to 3.0.0 (#2780) --- Cargo.lock | 332 +++++++++--------- account-keys/Cargo.toml | 2 +- account-keys/slip10/Cargo.toml | 2 +- admin-http-gateway/Cargo.toml | 2 +- android-bindings/Cargo.toml | 2 +- .../android-bindings/publish.gradle | 2 +- api/Cargo.toml | 2 +- attest/ake/Cargo.toml | 2 +- attest/api/Cargo.toml | 2 +- attest/core/Cargo.toml | 2 +- attest/enclave-api/Cargo.toml | 2 +- attest/net/Cargo.toml | 2 +- attest/trusted/Cargo.toml | 2 +- attest/untrusted/Cargo.toml | 2 +- attest/verifier/Cargo.toml | 2 +- common/Cargo.toml | 2 +- connection/Cargo.toml | 2 +- connection/test-utils/Cargo.toml | 2 +- consensus/api/Cargo.toml | 2 +- consensus/enclave/Cargo.toml | 2 +- consensus/enclave/api/Cargo.toml | 2 +- consensus/enclave/edl/Cargo.toml | 2 +- consensus/enclave/impl/Cargo.toml | 2 +- consensus/enclave/measurement/Cargo.toml | 2 +- consensus/enclave/mock/Cargo.toml | 2 +- consensus/enclave/trusted/Cargo.lock | 90 ++--- consensus/enclave/trusted/Cargo.toml | 2 +- consensus/mint-client/Cargo.toml | 2 +- consensus/scp/Cargo.toml | 2 +- consensus/scp/play/Cargo.toml | 2 +- consensus/service/Cargo.toml | 2 +- consensus/service/config/Cargo.toml | 2 +- crypto/ake/enclave/Cargo.toml | 2 +- crypto/box/Cargo.toml | 2 +- crypto/digestible/Cargo.toml | 2 +- crypto/digestible/derive/Cargo.toml | 2 +- crypto/digestible/derive/test/Cargo.toml | 2 +- crypto/digestible/signature/Cargo.toml | 2 +- crypto/digestible/test-utils/Cargo.toml | 2 +- crypto/hashes/Cargo.toml | 2 +- crypto/keys/Cargo.toml | 2 +- crypto/message-cipher/Cargo.toml | 2 +- crypto/multisig/Cargo.toml | 2 +- crypto/noise/Cargo.toml | 2 +- crypto/rand/Cargo.toml | 2 +- crypto/sig/Cargo.toml | 2 +- crypto/x509/test-vectors/Cargo.toml | 2 +- crypto/x509/utils/Cargo.toml | 2 +- enclave-boundary/Cargo.toml | 2 +- fog/api/Cargo.toml | 2 +- fog/distribution/Cargo.toml | 2 +- fog/enclave_connection/Cargo.toml | 2 +- fog/ingest/client/Cargo.toml | 2 +- fog/ingest/enclave/Cargo.toml | 2 +- fog/ingest/enclave/api/Cargo.toml | 2 +- fog/ingest/enclave/edl/Cargo.toml | 2 +- fog/ingest/enclave/impl/Cargo.toml | 2 +- fog/ingest/enclave/measurement/Cargo.toml | 2 +- fog/ingest/enclave/trusted/Cargo.lock | 102 +++--- fog/ingest/enclave/trusted/Cargo.toml | 2 +- fog/ingest/report/Cargo.toml | 2 +- fog/ingest/server/Cargo.toml | 2 +- fog/kex_rng/Cargo.toml | 2 +- fog/ledger/connection/Cargo.toml | 2 +- fog/ledger/enclave/Cargo.toml | 2 +- fog/ledger/enclave/api/Cargo.toml | 2 +- fog/ledger/enclave/edl/Cargo.toml | 2 +- fog/ledger/enclave/impl/Cargo.toml | 2 +- fog/ledger/enclave/measurement/Cargo.toml | 2 +- fog/ledger/enclave/trusted/Cargo.lock | 100 +++--- fog/ledger/enclave/trusted/Cargo.toml | 2 +- fog/ledger/server/Cargo.toml | 2 +- fog/ledger/test_infra/Cargo.toml | 2 +- fog/load_testing/Cargo.toml | 2 +- fog/ocall_oram_storage/edl/Cargo.toml | 2 +- fog/ocall_oram_storage/testing/Cargo.toml | 2 +- fog/ocall_oram_storage/trusted/Cargo.toml | 2 +- fog/ocall_oram_storage/untrusted/Cargo.toml | 2 +- fog/overseer/server/Cargo.toml | 2 +- fog/recovery_db_iface/Cargo.toml | 2 +- fog/report/api/Cargo.toml | 2 +- fog/report/api/test-utils/Cargo.toml | 2 +- fog/report/cli/Cargo.toml | 2 +- fog/report/connection/Cargo.toml | 2 +- fog/report/resolver/Cargo.toml | 2 +- fog/report/server/Cargo.toml | 2 +- fog/report/types/Cargo.toml | 2 +- fog/report/validation/Cargo.toml | 2 +- fog/report/validation/test-utils/Cargo.toml | 2 +- fog/sample-paykit/Cargo.toml | 2 +- fog/sig/Cargo.toml | 2 +- fog/sig/authority/Cargo.toml | 2 +- fog/sig/report/Cargo.toml | 2 +- fog/sql_recovery_db/Cargo.toml | 2 +- fog/test-client/Cargo.toml | 2 +- fog/test_infra/Cargo.toml | 2 +- fog/types/Cargo.toml | 2 +- fog/uri/Cargo.toml | 2 +- fog/view/connection/Cargo.toml | 2 +- fog/view/enclave/Cargo.toml | 2 +- fog/view/enclave/api/Cargo.toml | 2 +- fog/view/enclave/edl/Cargo.toml | 2 +- fog/view/enclave/impl/Cargo.toml | 2 +- fog/view/enclave/measurement/Cargo.toml | 2 +- fog/view/enclave/trusted/Cargo.lock | 104 +++--- fog/view/enclave/trusted/Cargo.toml | 2 +- fog/view/load-test/Cargo.toml | 2 +- fog/view/protocol/Cargo.toml | 2 +- fog/view/server/Cargo.toml | 2 +- go-grpc-gateway/testing/Cargo.toml | 2 +- ledger/db/Cargo.toml | 2 +- ledger/distribution/Cargo.toml | 2 +- ledger/from-archive/Cargo.toml | 2 +- ledger/migration/Cargo.toml | 2 +- ledger/sync/Cargo.toml | 2 +- libmobilecoin/Cargo.toml | 2 +- mint-auditor/Cargo.toml | 2 +- mint-auditor/api/Cargo.toml | 2 +- mobilecoind-json/Cargo.toml | 2 +- mobilecoind/Cargo.toml | 2 +- mobilecoind/api/Cargo.toml | 2 +- peers/Cargo.toml | 2 +- peers/test-utils/Cargo.toml | 2 +- sgx/alloc/Cargo.toml | 2 +- sgx/build/Cargo.toml | 2 +- sgx/compat-edl/Cargo.toml | 2 +- sgx/compat/Cargo.toml | 2 +- sgx/css-dump/Cargo.toml | 2 +- sgx/css/Cargo.toml | 2 +- sgx/debug-edl/Cargo.toml | 2 +- sgx/debug/Cargo.toml | 2 +- sgx/enclave-id/Cargo.toml | 2 +- sgx/panic-edl/Cargo.toml | 2 +- sgx/panic/Cargo.toml | 2 +- sgx/report-cache/api/Cargo.toml | 2 +- sgx/report-cache/untrusted/Cargo.toml | 2 +- sgx/service/Cargo.toml | 2 +- sgx/slog-edl/Cargo.toml | 2 +- sgx/slog/Cargo.toml | 2 +- sgx/sync/Cargo.toml | 2 +- sgx/types/Cargo.toml | 2 +- sgx/urts/Cargo.toml | 2 +- test-vectors/account-keys/Cargo.toml | 2 +- test-vectors/b58-encodings/Cargo.toml | 2 +- test-vectors/definitions/Cargo.toml | 2 +- test-vectors/memos/Cargo.toml | 2 +- test-vectors/tx-out-records/Cargo.toml | 2 +- transaction/core/Cargo.toml | 2 +- transaction/core/test-utils/Cargo.toml | 2 +- transaction/std/Cargo.toml | 2 +- util/b58-decoder/Cargo.toml | 2 +- util/build/enclave/Cargo.toml | 2 +- util/build/grpc/Cargo.toml | 2 +- util/build/info/Cargo.toml | 2 +- util/build/script/Cargo.toml | 2 +- util/build/sgx/Cargo.toml | 2 +- util/cli/Cargo.toml | 2 +- util/encodings/Cargo.toml | 2 +- util/ffi/Cargo.toml | 2 +- util/from-random/Cargo.toml | 2 +- util/generate-sample-ledger/Cargo.toml | 2 +- util/grpc-admin-tool/Cargo.toml | 2 +- util/grpc-token-generator/Cargo.toml | 2 +- util/grpc/Cargo.toml | 2 +- util/host-cert/Cargo.toml | 2 +- util/keyfile/Cargo.toml | 2 +- util/lmdb/Cargo.toml | 2 +- util/logger-macros/Cargo.toml | 2 +- util/metered-channel/Cargo.toml | 2 +- util/metrics/Cargo.toml | 2 +- util/parse/Cargo.toml | 2 +- util/repr-bytes/Cargo.toml | 2 +- util/seeded-ed25519-key-gen/Cargo.toml | 2 +- util/serial/Cargo.toml | 2 +- util/telemetry/Cargo.toml | 2 +- util/test-helper/Cargo.toml | 2 +- util/test-vector/Cargo.toml | 2 +- util/test-with-data/Cargo.toml | 2 +- util/uri/Cargo.toml | 2 +- wasm-test/Cargo.toml | 2 +- watcher/Cargo.toml | 2 +- watcher/api/Cargo.toml | 2 +- 182 files changed, 541 insertions(+), 541 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89923b6807..91314be94f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1574,7 +1574,7 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "go-grpc-gateway-testing" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2027,7 +2027,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libmobilecoin" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "cbindgen", @@ -2214,7 +2214,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "criterion", "curve25519-dalek", @@ -2242,7 +2242,7 @@ dependencies = [ [[package]] name = "mc-account-keys-slip10" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -2258,7 +2258,7 @@ dependencies = [ [[package]] name = "mc-admin-http-gateway" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -2273,7 +2273,7 @@ dependencies = [ [[package]] name = "mc-android-bindings" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "anyhow", @@ -2312,7 +2312,7 @@ dependencies = [ [[package]] name = "mc-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "bs58", "cargo-emit", @@ -2348,7 +2348,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "aes-gcm", @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "mc-attest-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "cargo-emit", @@ -2391,7 +2391,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "bincode", @@ -2423,7 +2423,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -2436,7 +2436,7 @@ dependencies = [ [[package]] name = "mc-attest-net" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -2456,7 +2456,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -2467,7 +2467,7 @@ dependencies = [ [[package]] name = "mc-attest-untrusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-attest-core", "mc-attest-verifier", @@ -2477,7 +2477,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -2502,7 +2502,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "backtrace", "binascii", @@ -2539,7 +2539,7 @@ dependencies = [ [[package]] name = "mc-connection" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "cookie", @@ -2568,7 +2568,7 @@ dependencies = [ [[package]] name = "mc-connection-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-connection", "mc-consensus-enclave-api", @@ -2579,7 +2579,7 @@ dependencies = [ [[package]] name = "mc-consensus-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "futures", @@ -2600,7 +2600,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2625,7 +2625,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "hex", @@ -2646,7 +2646,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -2654,7 +2654,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "hex", @@ -2690,7 +2690,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-measurement" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -2703,7 +2703,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-mock" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-account-keys", "mc-attest-core", @@ -2725,7 +2725,7 @@ dependencies = [ [[package]] name = "mc-consensus-mint-client" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -2754,7 +2754,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "maplit", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "mc-consensus-scp-play" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "mc-common", @@ -2789,7 +2789,7 @@ dependencies = [ [[package]] name = "mc-consensus-service" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "chrono", @@ -2851,7 +2851,7 @@ dependencies = [ [[package]] name = "mc-consensus-service-config" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "clap 3.1.18", @@ -2876,7 +2876,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "digest 0.10.3", @@ -2896,7 +2896,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "digest 0.10.3", @@ -2912,7 +2912,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -2925,7 +2925,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "proc-macro2", "quote", @@ -2934,7 +2934,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive-test" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-digestible-test-utils", @@ -2942,7 +2942,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -2951,7 +2951,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "serde_json", @@ -2959,7 +2959,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "blake2", "digest 0.10.3", @@ -2968,7 +2968,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -3001,7 +3001,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "displaydoc", @@ -3015,7 +3015,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -3029,7 +3029,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "aes-gcm", @@ -3050,7 +3050,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.6", @@ -3061,7 +3061,7 @@ dependencies = [ [[package]] name = "mc-crypto-sig" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3074,7 +3074,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-test-vectors" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3086,7 +3086,7 @@ dependencies = [ [[package]] name = "mc-crypto-x509-utils" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-crypto-keys", @@ -3097,7 +3097,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -3108,7 +3108,7 @@ dependencies = [ [[package]] name = "mc-fog-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -3140,7 +3140,7 @@ dependencies = [ [[package]] name = "mc-fog-distribution" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "crossbeam-channel", @@ -3172,7 +3172,7 @@ dependencies = [ [[package]] name = "mc-fog-enclave-connection" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "cookie", @@ -3196,7 +3196,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-client" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "assert_cmd", "clap 3.1.18", @@ -3235,7 +3235,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "criterion", @@ -3270,7 +3270,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3287,7 +3287,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3295,7 +3295,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aligned-cmov", "mc-account-keys", @@ -3328,7 +3328,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-measurement" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3341,7 +3341,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-report" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3353,7 +3353,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-server" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "dirs", @@ -3410,7 +3410,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "digest 0.10.3", "displaydoc", @@ -3426,7 +3426,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-connection" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "grpcio", @@ -3447,7 +3447,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3476,7 +3476,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -3502,7 +3502,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -3525,7 +3525,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-measurement" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -3538,7 +3538,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-server" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3592,7 +3592,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-test-infra" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-attest-core", "mc-attest-enclave-api", @@ -3608,7 +3608,7 @@ dependencies = [ [[package]] name = "mc-fog-load-testing" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -3637,14 +3637,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-testing" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aligned-cmov", "mc-fog-ocall-oram-storage-trusted", @@ -3655,7 +3655,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "aligned-cmov", @@ -3672,7 +3672,7 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-untrusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "lazy_static", "mc-common", @@ -3680,7 +3680,7 @@ dependencies = [ [[package]] name = "mc-fog-overseer-server" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3718,7 +3718,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3732,7 +3732,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "futures", @@ -3751,7 +3751,7 @@ dependencies = [ [[package]] name = "mc-fog-report-api-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-util-serial", "prost", @@ -3760,7 +3760,7 @@ dependencies = [ [[package]] name = "mc-fog-report-cli" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "binascii", @@ -3784,7 +3784,7 @@ dependencies = [ [[package]] name = "mc-fog-report-connection" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "grpcio", @@ -3801,7 +3801,7 @@ dependencies = [ [[package]] name = "mc-fog-report-resolver" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-account-keys", "mc-attest-verifier", @@ -3816,7 +3816,7 @@ dependencies = [ [[package]] name = "mc-fog-report-server" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -3852,7 +3852,7 @@ dependencies = [ [[package]] name = "mc-fog-report-types" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-attest-core", "mc-crypto-digestible", @@ -3862,7 +3862,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3875,7 +3875,7 @@ dependencies = [ [[package]] name = "mc-fog-report-validation-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-account-keys", "mc-fog-report-validation", @@ -3883,7 +3883,7 @@ dependencies = [ [[package]] name = "mc-fog-sample-paykit" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "clap 3.1.18", @@ -3930,7 +3930,7 @@ dependencies = [ [[package]] name = "mc-fog-sig" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -3951,7 +3951,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-keys", "mc-util-from-random", @@ -3962,7 +3962,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-report" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -3977,7 +3977,7 @@ dependencies = [ [[package]] name = "mc-fog-sql-recovery-db" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "chrono", "clap 3.1.18", @@ -4010,7 +4010,7 @@ dependencies = [ [[package]] name = "mc-fog-test-client" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4041,7 +4041,7 @@ dependencies = [ [[package]] name = "mc-fog-test-infra" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "digest 0.10.3", @@ -4072,7 +4072,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "crc", "displaydoc", @@ -4092,7 +4092,7 @@ dependencies = [ [[package]] name = "mc-fog-uri" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-common", "mc-util-uri", @@ -4100,7 +4100,7 @@ dependencies = [ [[package]] name = "mc-fog-view-connection" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "grpcio", "mc-attest-core", @@ -4120,7 +4120,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "criterion", @@ -4155,7 +4155,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4173,7 +4173,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -4181,7 +4181,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -4203,7 +4203,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-measurement" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-attest-core", @@ -4216,7 +4216,7 @@ dependencies = [ [[package]] name = "mc-fog-view-load-test" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4235,7 +4235,7 @@ dependencies = [ [[package]] name = "mc-fog-view-protocol" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-account-keys", @@ -4258,7 +4258,7 @@ dependencies = [ [[package]] name = "mc-fog-view-server" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4308,7 +4308,7 @@ dependencies = [ [[package]] name = "mc-ledger-db" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "lazy_static", @@ -4334,7 +4334,7 @@ dependencies = [ [[package]] name = "mc-ledger-distribution" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "dirs", @@ -4356,7 +4356,7 @@ dependencies = [ [[package]] name = "mc-ledger-from-archive" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "mc-api", @@ -4367,7 +4367,7 @@ dependencies = [ [[package]] name = "mc-ledger-migration" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "lmdb-rkv", @@ -4380,7 +4380,7 @@ dependencies = [ [[package]] name = "mc-ledger-sync" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4411,7 +4411,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -4444,7 +4444,7 @@ dependencies = [ [[package]] name = "mc-mint-auditor-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "futures", @@ -4458,7 +4458,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "clap 3.1.18", @@ -4523,7 +4523,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "futures", @@ -4542,7 +4542,7 @@ dependencies = [ [[package]] name = "mc-mobilecoind-json" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -4617,7 +4617,7 @@ dependencies = [ [[package]] name = "mc-peers" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "displaydoc", @@ -4649,7 +4649,7 @@ dependencies = [ [[package]] name = "mc-peers-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "grpcio", "hex", @@ -4672,7 +4672,7 @@ dependencies = [ [[package]] name = "mc-sgx-build" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cc", "lazy_static", @@ -4682,7 +4682,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-types", @@ -4690,7 +4690,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -4699,7 +4699,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "sha2 0.10.2", @@ -4707,7 +4707,7 @@ dependencies = [ [[package]] name = "mc-sgx-css-dump" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "hex_fmt", @@ -4716,21 +4716,21 @@ dependencies = [ [[package]] name = "mc-sgx-debug-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-panic-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4741,7 +4741,7 @@ dependencies = [ [[package]] name = "mc-sgx-report-cache-untrusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -4757,7 +4757,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -4767,18 +4767,18 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-types" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-urts" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-common", "mc-sgx-build", @@ -4789,7 +4789,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-account-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "hex", "mc-account-keys", @@ -4801,7 +4801,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-b58-encodings" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-account-keys", "mc-api", @@ -4811,7 +4811,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-definitions" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-util-test-vector", "serde", @@ -4820,7 +4820,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-memos" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "hex", "mc-account-keys", @@ -4835,7 +4835,7 @@ dependencies = [ [[package]] name = "mc-test-vectors-tx-out-records" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "hex", "mc-account-keys", @@ -4857,7 +4857,7 @@ dependencies = [ [[package]] name = "mc-transaction-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -4899,7 +4899,7 @@ dependencies = [ [[package]] name = "mc-transaction-core-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-account-keys", "mc-crypto-keys", @@ -4916,7 +4916,7 @@ dependencies = [ [[package]] name = "mc-transaction-std" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "assert_matches", "cfg-if 1.0.0", @@ -4943,7 +4943,7 @@ dependencies = [ [[package]] name = "mc-util-b58-decoder" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "hex", @@ -4952,7 +4952,7 @@ dependencies = [ [[package]] name = "mc-util-build-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cargo_metadata 0.14.2", @@ -4968,7 +4968,7 @@ dependencies = [ [[package]] name = "mc-util-build-grpc" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-util-build-script", "protoc-grpcio", @@ -4976,7 +4976,7 @@ dependencies = [ [[package]] name = "mc-util-build-info" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "json", @@ -4984,7 +4984,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -4995,7 +4995,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cc", @@ -5006,7 +5006,7 @@ dependencies = [ [[package]] name = "mc-util-cli" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "mc-util-build-info", @@ -5014,7 +5014,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "binascii", @@ -5026,18 +5026,18 @@ dependencies = [ [[package]] name = "mc-util-ffi" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-util-from-random" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "rand_core 0.6.3", ] [[package]] name = "mc-util-generate-sample-ledger" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "hex", @@ -5056,7 +5056,7 @@ dependencies = [ [[package]] name = "mc-util-grpc" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "clap 3.1.18", @@ -5090,7 +5090,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-admin-tool" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "grpcio", @@ -5101,7 +5101,7 @@ dependencies = [ [[package]] name = "mc-util-grpc-token-generator" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "hex", @@ -5112,11 +5112,11 @@ dependencies = [ [[package]] name = "mc-util-host-cert" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-util-keyfile" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "clap 3.1.18", @@ -5144,7 +5144,7 @@ dependencies = [ [[package]] name = "mc-util-lmdb" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "lmdb-rkv", @@ -5154,7 +5154,7 @@ dependencies = [ [[package]] name = "mc-util-logger-macros" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "proc-macro2", "quote", @@ -5163,7 +5163,7 @@ dependencies = [ [[package]] name = "mc-util-metered-channel" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "crossbeam-channel", "mc-util-metrics", @@ -5171,7 +5171,7 @@ dependencies = [ [[package]] name = "mc-util-metrics" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "chrono", "grpcio", @@ -5184,7 +5184,7 @@ dependencies = [ [[package]] name = "mc-util-parse" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "itertools", "mc-sgx-css", @@ -5192,7 +5192,7 @@ dependencies = [ [[package]] name = "mc-util-repr-bytes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "generic-array", "prost", @@ -5202,7 +5202,7 @@ dependencies = [ [[package]] name = "mc-util-seeded-ed25519-key-gen" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "hex", @@ -5215,7 +5215,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "prost", "serde", @@ -5224,7 +5224,7 @@ dependencies = [ [[package]] name = "mc-util-telemetry" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "displaydoc", @@ -5235,7 +5235,7 @@ dependencies = [ [[package]] name = "mc-util-test-helper" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "itertools", @@ -5249,7 +5249,7 @@ dependencies = [ [[package]] name = "mc-util-test-vector" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "serde", "serde_json", @@ -5257,7 +5257,7 @@ dependencies = [ [[package]] name = "mc-util-test-with-data" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "proc-macro2", "quote", @@ -5266,7 +5266,7 @@ dependencies = [ [[package]] name = "mc-util-uri" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "displaydoc", @@ -5284,7 +5284,7 @@ dependencies = [ [[package]] name = "mc-wasm-test" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "getrandom 0.2.6", "mc-account-keys", @@ -5299,7 +5299,7 @@ dependencies = [ [[package]] name = "mc-watcher" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "clap 3.1.18", "displaydoc", @@ -5343,7 +5343,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "serde", diff --git a/account-keys/Cargo.toml b/account-keys/Cargo.toml index 77e784c103..13f20f34f9 100644 --- a/account-keys/Cargo.toml +++ b/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/account-keys/slip10/Cargo.toml b/account-keys/slip10/Cargo.toml index ad5e676449..5a9e848373 100644 --- a/account-keys/slip10/Cargo.toml +++ b/account-keys/slip10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-account-keys-slip10" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/admin-http-gateway/Cargo.toml b/admin-http-gateway/Cargo.toml index f1df662524..d1a2d43a8d 100644 --- a/admin-http-gateway/Cargo.toml +++ b/admin-http-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-admin-http-gateway" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/android-bindings/Cargo.toml b/android-bindings/Cargo.toml index df7c817e90..7eb5164694 100644 --- a/android-bindings/Cargo.toml +++ b/android-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-android-bindings" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/android-bindings/lib-wrapper/android-bindings/publish.gradle b/android-bindings/lib-wrapper/android-bindings/publish.gradle index 9de1eaa333..2f046c46f4 100644 --- a/android-bindings/lib-wrapper/android-bindings/publish.gradle +++ b/android-bindings/lib-wrapper/android-bindings/publish.gradle @@ -1,6 +1,6 @@ apply plugin: 'maven-publish' -version '3.0.0-pre0' +version '3.0.0' group 'com.mobilecoin' Properties properties = new Properties() diff --git a/api/Cargo.toml b/api/Cargo.toml index 8e6377a0af..0f5e2daa26 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/attest/ake/Cargo.toml b/attest/ake/Cargo.toml index 11494a6b23..a31bd0b1f9 100644 --- a/attest/ake/Cargo.toml +++ b/attest/ake/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-ake" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/api/Cargo.toml b/attest/api/Cargo.toml index 7b9b18e625..1136b1b01d 100644 --- a/attest/api/Cargo.toml +++ b/attest/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] license = "MIT/Apache-2.0" edition = "2018" diff --git a/attest/core/Cargo.toml b/attest/core/Cargo.toml index b428c5c464..df7171f247 100644 --- a/attest/core/Cargo.toml +++ b/attest/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-core" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/enclave-api/Cargo.toml b/attest/enclave-api/Cargo.toml index 36297da794..5add4fbaa3 100644 --- a/attest/enclave-api/Cargo.toml +++ b/attest/enclave-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/attest/net/Cargo.toml b/attest/net/Cargo.toml index 2e091090f2..875e7c48f4 100644 --- a/attest/net/Cargo.toml +++ b/attest/net/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-net" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/attest/trusted/Cargo.toml b/attest/trusted/Cargo.toml index 4008f8c351..b0e3d57e56 100644 --- a/attest/trusted/Cargo.toml +++ b/attest/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-trusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/untrusted/Cargo.toml b/attest/untrusted/Cargo.toml index 10531c3c2e..d778f7023d 100644 --- a/attest/untrusted/Cargo.toml +++ b/attest/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-untrusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/attest/verifier/Cargo.toml b/attest/verifier/Cargo.toml index f9289153d7..e8ea58d7e5 100644 --- a/attest/verifier/Cargo.toml +++ b/attest/verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-attest-verifier" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/common/Cargo.toml b/common/Cargo.toml index dc62467d15..b677b289b6 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-common" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/Cargo.toml b/connection/Cargo.toml index 0449108909..a11fe17848 100644 --- a/connection/Cargo.toml +++ b/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/connection/test-utils/Cargo.toml b/connection/test-utils/Cargo.toml index beb34f09d2..8f4dd11849 100644 --- a/connection/test-utils/Cargo.toml +++ b/connection/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-connection-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/api/Cargo.toml b/consensus/api/Cargo.toml index 619c2247d0..daf6c0b134 100644 --- a/consensus/api/Cargo.toml +++ b/consensus/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/consensus/enclave/Cargo.toml b/consensus/enclave/Cargo.toml index bcb2996e26..9298f0d884 100644 --- a/consensus/enclave/Cargo.toml +++ b/consensus/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/api/Cargo.toml b/consensus/enclave/api/Cargo.toml index f9728e5c8c..e1d420e6ec 100644 --- a/consensus/enclave/api/Cargo.toml +++ b/consensus/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/consensus/enclave/edl/Cargo.toml b/consensus/enclave/edl/Cargo.toml index 4b0cac63dc..027ab60916 100644 --- a/consensus/enclave/edl/Cargo.toml +++ b/consensus/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "consensus_enclave_edl" diff --git a/consensus/enclave/impl/Cargo.toml b/consensus/enclave/impl/Cargo.toml index e013f472d0..725543f9c1 100644 --- a/consensus/enclave/impl/Cargo.toml +++ b/consensus/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/consensus/enclave/measurement/Cargo.toml b/consensus/enclave/measurement/Cargo.toml index 124eebe7af..85c58cf969 100644 --- a/consensus/enclave/measurement/Cargo.toml +++ b/consensus/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-measurement" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Consensus Enclave - Application Code" diff --git a/consensus/enclave/mock/Cargo.toml b/consensus/enclave/mock/Cargo.toml index 5a202dcf2f..59b32af762 100644 --- a/consensus/enclave/mock/Cargo.toml +++ b/consensus/enclave/mock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-mock" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/enclave/trusted/Cargo.lock b/consensus/enclave/trusted/Cargo.lock index d7f3dee3d8..ffc7840248 100644 --- a/consensus/enclave/trusted/Cargo.lock +++ b/consensus/enclave/trusted/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "cargo-emit", @@ -688,7 +688,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "bitflags", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "hex", @@ -803,7 +803,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "hex", @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "mc-consensus-enclave-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "lazy_static", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "digest", @@ -893,7 +893,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "digest", @@ -907,7 +907,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -920,7 +920,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "proc-macro2", "quote", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -938,7 +938,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "blake2", "digest", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-crypto-message-cipher" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "displaydoc", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -996,7 +996,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "aes-gcm", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1061,11 +1061,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-build" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cc", "lazy_static", @@ -1075,7 +1075,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1088,7 +1088,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "sha2", @@ -1096,29 +1096,29 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-enclave-id" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-panic-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1129,7 +1129,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1137,7 +1137,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1147,14 +1147,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1162,11 +1162,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-transaction-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -1198,7 +1198,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1209,7 +1209,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cc", @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "binascii", @@ -1232,14 +1232,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "generic-array", "prost", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "prost", "serde", diff --git a/consensus/enclave/trusted/Cargo.toml b/consensus/enclave/trusted/Cargo.toml index ce0c3528fb..e3049d7aff 100644 --- a/consensus/enclave/trusted/Cargo.toml +++ b/consensus/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-enclave-trusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Consensus Service's internal enclave entry point." diff --git a/consensus/mint-client/Cargo.toml b/consensus/mint-client/Cargo.toml index 82eef00ced..3b9c6c0a9a 100644 --- a/consensus/mint-client/Cargo.toml +++ b/consensus/mint-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-mint-client" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/scp/Cargo.toml b/consensus/scp/Cargo.toml index 6ebbc2bce5..da2e9e8bf1 100644 --- a/consensus/scp/Cargo.toml +++ b/consensus/scp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2021" description = "Stellar Consensus Protocol" diff --git a/consensus/scp/play/Cargo.toml b/consensus/scp/play/Cargo.toml index 6df64bb08d..ccf111b118 100644 --- a/consensus/scp/play/Cargo.toml +++ b/consensus/scp/play/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-scp-play" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/Cargo.toml b/consensus/service/Cargo.toml index acd3877fa3..b65bae4c7e 100644 --- a/consensus/service/Cargo.toml +++ b/consensus/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/consensus/service/config/Cargo.toml b/consensus/service/config/Cargo.toml index 26582cd432..226f4c5863 100644 --- a/consensus/service/config/Cargo.toml +++ b/consensus/service/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-consensus-service-config" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/ake/enclave/Cargo.toml b/crypto/ake/enclave/Cargo.toml index c559dbe52c..b3a2dd04c5 100644 --- a/crypto/ake/enclave/Cargo.toml +++ b/crypto/ake/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-ake-enclave" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/box/Cargo.toml b/crypto/box/Cargo.toml index 7b2eb29782..0dc86274b5 100644 --- a/crypto/box/Cargo.toml +++ b/crypto/box/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-box" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/Cargo.toml b/crypto/digestible/Cargo.toml index dae167fb2e..434e9ac6ff 100644 --- a/crypto/digestible/Cargo.toml +++ b/crypto/digestible/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/Cargo.toml b/crypto/digestible/derive/Cargo.toml index 935edd2aea..a716d553f5 100644 --- a/crypto/digestible/derive/Cargo.toml +++ b/crypto/digestible/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/derive/test/Cargo.toml b/crypto/digestible/derive/test/Cargo.toml index 6fef22bca9..e7383cc952 100644 --- a/crypto/digestible/derive/test/Cargo.toml +++ b/crypto/digestible/derive/test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-derive-test" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/digestible/signature/Cargo.toml b/crypto/digestible/signature/Cargo.toml index 3fe8f83b6d..9f20fef7ce 100644 --- a/crypto/digestible/signature/Cargo.toml +++ b/crypto/digestible/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-signature" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Digestible Signatures" diff --git a/crypto/digestible/test-utils/Cargo.toml b/crypto/digestible/test-utils/Cargo.toml index 2b2fb4c650..24f1b881cc 100644 --- a/crypto/digestible/test-utils/Cargo.toml +++ b/crypto/digestible/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-digestible-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/hashes/Cargo.toml b/crypto/hashes/Cargo.toml index 7f9c5264da..d2644161e1 100644 --- a/crypto/hashes/Cargo.toml +++ b/crypto/hashes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-hashes" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/keys/Cargo.toml b/crypto/keys/Cargo.toml index 02f5445f13..5ffa3ebbd8 100644 --- a/crypto/keys/Cargo.toml +++ b/crypto/keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-keys" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Diffie-Hellman Key Exchange and Digital Signatures" diff --git a/crypto/message-cipher/Cargo.toml b/crypto/message-cipher/Cargo.toml index 4d2a3f1254..7223b48a04 100644 --- a/crypto/message-cipher/Cargo.toml +++ b/crypto/message-cipher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-message-cipher" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/multisig/Cargo.toml b/crypto/multisig/Cargo.toml index b9f18ef6a2..1f552c0546 100644 --- a/crypto/multisig/Cargo.toml +++ b/crypto/multisig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-multisig" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin multi-signature implementations" diff --git a/crypto/noise/Cargo.toml b/crypto/noise/Cargo.toml index 2ce8dc128b..6709e8dbd7 100644 --- a/crypto/noise/Cargo.toml +++ b/crypto/noise/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-noise" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/rand/Cargo.toml b/crypto/rand/Cargo.toml index df0e2578e4..1be71fedd9 100644 --- a/crypto/rand/Cargo.toml +++ b/crypto/rand/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-rand" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/crypto/sig/Cargo.toml b/crypto/sig/Cargo.toml index e386ecdf8f..53609308dd 100644 --- a/crypto/sig/Cargo.toml +++ b/crypto/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-sig" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/crypto/x509/test-vectors/Cargo.toml b/crypto/x509/test-vectors/Cargo.toml index 42d88536e2..30e5f32c11 100644 --- a/crypto/x509/test-vectors/Cargo.toml +++ b/crypto/x509/test-vectors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-test-vectors" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Utilities for generating certificates and chains for unit tests" diff --git a/crypto/x509/utils/Cargo.toml b/crypto/x509/utils/Cargo.toml index 980ba6c7e9..722ece61f7 100644 --- a/crypto/x509/utils/Cargo.toml +++ b/crypto/x509/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-crypto-x509-utils" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Verification of X509 certificate chains" diff --git a/enclave-boundary/Cargo.toml b/enclave-boundary/Cargo.toml index 4c5a38e08c..a52dfa587f 100644 --- a/enclave-boundary/Cargo.toml +++ b/enclave-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-enclave-boundary" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/api/Cargo.toml b/fog/api/Cargo.toml index 5a5f30e4a4..863bb072aa 100644 --- a/fog/api/Cargo.toml +++ b/fog/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/distribution/Cargo.toml b/fog/distribution/Cargo.toml index 90727265af..3a8da177d9 100644 --- a/fog/distribution/Cargo.toml +++ b/fog/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-distribution" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/enclave_connection/Cargo.toml b/fog/enclave_connection/Cargo.toml index e2cc4304cc..75bb5309e3 100644 --- a/fog/enclave_connection/Cargo.toml +++ b/fog/enclave_connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-enclave-connection" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/client/Cargo.toml b/fog/ingest/client/Cargo.toml index 522e9a11c6..707e948793 100644 --- a/fog/ingest/client/Cargo.toml +++ b/fog/ingest/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-client" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/Cargo.toml b/fog/ingest/enclave/Cargo.toml index bc532e94da..6d8005363e 100644 --- a/fog/ingest/enclave/Cargo.toml +++ b/fog/ingest/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/api/Cargo.toml b/fog/ingest/enclave/api/Cargo.toml index 80f45aeb15..604157ae45 100644 --- a/fog/ingest/enclave/api/Cargo.toml +++ b/fog/ingest/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/edl/Cargo.toml b/fog/ingest/enclave/edl/Cargo.toml index b3b92b61f8..2ec62eed38 100644 --- a/fog/ingest/enclave/edl/Cargo.toml +++ b/fog/ingest/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "ingest_enclave_edl" diff --git a/fog/ingest/enclave/impl/Cargo.toml b/fog/ingest/enclave/impl/Cargo.toml index 7e644bef51..36b9783bd2 100644 --- a/fog/ingest/enclave/impl/Cargo.toml +++ b/fog/ingest/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ingest/enclave/measurement/Cargo.toml b/fog/ingest/enclave/measurement/Cargo.toml index 2889f011ed..9f45d2f6c8 100644 --- a/fog/ingest/enclave/measurement/Cargo.toml +++ b/fog/ingest/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-measurement" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ingest Enclave - Measurement" diff --git a/fog/ingest/enclave/trusted/Cargo.lock b/fog/ingest/enclave/trusted/Cargo.lock index 4fc3af2fc1..382bb10ac4 100644 --- a/fog/ingest/enclave/trusted/Cargo.lock +++ b/fog/ingest/enclave/trusted/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "cargo-emit", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "bitflags", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -747,7 +747,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -758,7 +758,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -802,7 +802,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "digest", @@ -822,7 +822,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "digest", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "proc-macro2", "quote", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "blake2", "digest", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "aes-gcm", @@ -932,7 +932,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -971,7 +971,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -979,7 +979,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "mc-fog-ingest-enclave-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "digest", "displaydoc", @@ -1054,14 +1054,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "aligned-cmov", @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1099,7 +1099,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "crc", "displaydoc", @@ -1165,11 +1165,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-build" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cc", "lazy_static", @@ -1179,7 +1179,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "sha2", @@ -1200,36 +1200,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-debug-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-panic-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1240,7 +1240,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1258,14 +1258,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1273,11 +1273,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-transaction-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -1309,7 +1309,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cc", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "binascii", @@ -1343,14 +1343,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "generic-array", "prost", @@ -1359,7 +1359,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "prost", "serde", @@ -1368,7 +1368,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ingest/enclave/trusted/Cargo.toml b/fog/ingest/enclave/trusted/Cargo.toml index 6ec654115d..830448bbf3 100644 --- a/fog/ingest/enclave/trusted/Cargo.toml +++ b/fog/ingest/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-enclave-trusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ingest/report/Cargo.toml b/fog/ingest/report/Cargo.toml index bd46908776..cc97876dd5 100644 --- a/fog/ingest/report/Cargo.toml +++ b/fog/ingest/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-report" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2021" diff --git a/fog/ingest/server/Cargo.toml b/fog/ingest/server/Cargo.toml index 1c8c6e84e1..b2f85ea681 100644 --- a/fog/ingest/server/Cargo.toml +++ b/fog/ingest/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ingest-server" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/kex_rng/Cargo.toml b/fog/kex_rng/Cargo.toml index 5504319674..4bb514101a 100644 --- a/fog/kex_rng/Cargo.toml +++ b/fog/kex_rng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-kex-rng" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["Mobilecoin"] edition = "2018" readme = "README.md" diff --git a/fog/ledger/connection/Cargo.toml b/fog/ledger/connection/Cargo.toml index 703f7a9528..59d8afe4ba 100644 --- a/fog/ledger/connection/Cargo.toml +++ b/fog/ledger/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-connection" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/Cargo.toml b/fog/ledger/enclave/Cargo.toml index 4a5bce5af9..33e75f2515 100644 --- a/fog/ledger/enclave/Cargo.toml +++ b/fog/ledger/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/enclave/api/Cargo.toml b/fog/ledger/enclave/api/Cargo.toml index 2d06a15fc4..ecc74eb476 100644 --- a/fog/ledger/enclave/api/Cargo.toml +++ b/fog/ledger/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = """ diff --git a/fog/ledger/enclave/edl/Cargo.toml b/fog/ledger/enclave/edl/Cargo.toml index 3f775f73c9..921cee7fe3 100644 --- a/fog/ledger/enclave/edl/Cargo.toml +++ b/fog/ledger/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "ledger_enclave_edl" diff --git a/fog/ledger/enclave/impl/Cargo.toml b/fog/ledger/enclave/impl/Cargo.toml index 9cfae1273c..88ee0ede8e 100644 --- a/fog/ledger/enclave/impl/Cargo.toml +++ b/fog/ledger/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = ''' diff --git a/fog/ledger/enclave/measurement/Cargo.toml b/fog/ledger/enclave/measurement/Cargo.toml index 5e3344d004..ba6acff087 100644 --- a/fog/ledger/enclave/measurement/Cargo.toml +++ b/fog/ledger/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-measurement" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Ledger Enclave - Measurement" diff --git a/fog/ledger/enclave/trusted/Cargo.lock b/fog/ledger/enclave/trusted/Cargo.lock index 00313fc9b0..7c2b943b55 100644 --- a/fog/ledger/enclave/trusted/Cargo.lock +++ b/fog/ledger/enclave/trusted/Cargo.lock @@ -673,7 +673,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -693,7 +693,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "cargo-emit", @@ -712,7 +712,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "bitflags", @@ -738,7 +738,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -751,7 +751,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cfg-if", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "cfg-if", @@ -806,7 +806,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "digest", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "digest", @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if", "curve25519-dalek", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "proc-macro2", "quote", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -871,7 +871,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "blake2", "digest", @@ -880,7 +880,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -906,7 +906,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "aes-gcm", @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if", "getrandom", @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "digest", "displaydoc", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -991,7 +991,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -999,7 +999,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "mc-fog-ledger-enclave-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1053,14 +1053,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "aligned-cmov", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1084,7 +1084,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "crc", "displaydoc", @@ -1150,11 +1150,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-build" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cc", "lazy_static", @@ -1164,7 +1164,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if", "mc-sgx-alloc", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "sha2", @@ -1185,36 +1185,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-debug-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-panic-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if", "mc-common", @@ -1243,14 +1243,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1258,11 +1258,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-transaction-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -1294,7 +1294,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cc", @@ -1316,7 +1316,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "binascii", @@ -1328,14 +1328,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "generic-array", "prost", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "prost", "serde", @@ -1353,7 +1353,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/ledger/enclave/trusted/Cargo.toml b/fog/ledger/enclave/trusted/Cargo.toml index c42b8d21eb..1371a1d892 100644 --- a/fog/ledger/enclave/trusted/Cargo.toml +++ b/fog/ledger/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-enclave-trusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" resolver = "2" diff --git a/fog/ledger/server/Cargo.toml b/fog/ledger/server/Cargo.toml index 7bffa13b1f..93cd7158ad 100644 --- a/fog/ledger/server/Cargo.toml +++ b/fog/ledger/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-server" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ledger/test_infra/Cargo.toml b/fog/ledger/test_infra/Cargo.toml index 56edb7702c..64e6cd5328 100644 --- a/fog/ledger/test_infra/Cargo.toml +++ b/fog/ledger/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ledger-test-infra" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/load_testing/Cargo.toml b/fog/load_testing/Cargo.toml index 838be85f42..cc11b4ee4e 100644 --- a/fog/load_testing/Cargo.toml +++ b/fog/load_testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-load-testing" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/edl/Cargo.toml b/fog/ocall_oram_storage/edl/Cargo.toml index c93f2f03ef..94322b1f8e 100644 --- a/fog/ocall_oram_storage/edl/Cargo.toml +++ b/fog/ocall_oram_storage/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "fog_ocall_oram_storage_edl" diff --git a/fog/ocall_oram_storage/testing/Cargo.toml b/fog/ocall_oram_storage/testing/Cargo.toml index 80a9726604..17ae4ed916 100644 --- a/fog/ocall_oram_storage/testing/Cargo.toml +++ b/fog/ocall_oram_storage/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-testing" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/trusted/Cargo.toml b/fog/ocall_oram_storage/trusted/Cargo.toml index 7a461e7b07..5868b4acf9 100644 --- a/fog/ocall_oram_storage/trusted/Cargo.toml +++ b/fog/ocall_oram_storage/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-trusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/ocall_oram_storage/untrusted/Cargo.toml b/fog/ocall_oram_storage/untrusted/Cargo.toml index 1761115f19..1a16c8ae8e 100644 --- a/fog/ocall_oram_storage/untrusted/Cargo.toml +++ b/fog/ocall_oram_storage/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-ocall-oram-storage-untrusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/overseer/server/Cargo.toml b/fog/overseer/server/Cargo.toml index 71adf2d233..d0c78b48ed 100644 --- a/fog/overseer/server/Cargo.toml +++ b/fog/overseer/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-overseer-server" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/recovery_db_iface/Cargo.toml b/fog/recovery_db_iface/Cargo.toml index 2186b95b52..ad90dd1839 100644 --- a/fog/recovery_db_iface/Cargo.toml +++ b/fog/recovery_db_iface/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-recovery-db-iface" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/api/Cargo.toml b/fog/report/api/Cargo.toml index 5be25fcadc..9a4a8bc570 100644 --- a/fog/report/api/Cargo.toml +++ b/fog/report/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "mc-fog-report-api" diff --git a/fog/report/api/test-utils/Cargo.toml b/fog/report/api/test-utils/Cargo.toml index eaa9557c34..46104fec9b 100644 --- a/fog/report/api/test-utils/Cargo.toml +++ b/fog/report/api/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-api-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/report/cli/Cargo.toml b/fog/report/cli/Cargo.toml index c6eddc07f8..506e699dd5 100644 --- a/fog/report/cli/Cargo.toml +++ b/fog/report/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-cli" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/connection/Cargo.toml b/fog/report/connection/Cargo.toml index 653bc4a78d..e6947fc130 100644 --- a/fog/report/connection/Cargo.toml +++ b/fog/report/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-connection" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/resolver/Cargo.toml b/fog/report/resolver/Cargo.toml index 63de7b0b67..f6b0501853 100644 --- a/fog/report/resolver/Cargo.toml +++ b/fog/report/resolver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-resolver" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2021" diff --git a/fog/report/server/Cargo.toml b/fog/report/server/Cargo.toml index b4ea718a55..b7b2d0b736 100644 --- a/fog/report/server/Cargo.toml +++ b/fog/report/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-server" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/report/types/Cargo.toml b/fog/report/types/Cargo.toml index 1fe74b451a..2b952a5f20 100644 --- a/fog/report/types/Cargo.toml +++ b/fog/report/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-types" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["Mobilecoin"] edition = "2018" diff --git a/fog/report/validation/Cargo.toml b/fog/report/validation/Cargo.toml index 2db33550b8..1e98f5e743 100644 --- a/fog/report/validation/Cargo.toml +++ b/fog/report/validation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/report/validation/test-utils/Cargo.toml b/fog/report/validation/test-utils/Cargo.toml index 5153c8c2f4..bd8b21aaf2 100644 --- a/fog/report/validation/test-utils/Cargo.toml +++ b/fog/report/validation/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-report-validation-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/fog/sample-paykit/Cargo.toml b/fog/sample-paykit/Cargo.toml index 536fc5ecf0..c362cea19e 100644 --- a/fog/sample-paykit/Cargo.toml +++ b/fog/sample-paykit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sample-paykit" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/sig/Cargo.toml b/fog/sig/Cargo.toml index 63cfc57043..3ed0844640 100644 --- a/fog/sig/Cargo.toml +++ b/fog/sig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Verify Fog Signatures" diff --git a/fog/sig/authority/Cargo.toml b/fog/sig/authority/Cargo.toml index 46260b1dea..9f2fab0639 100644 --- a/fog/sig/authority/Cargo.toml +++ b/fog/sig/authority/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-authority" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog authority signatures" diff --git a/fog/sig/report/Cargo.toml b/fog/sig/report/Cargo.toml index 4c48820477..2ad378f09e 100644 --- a/fog/sig/report/Cargo.toml +++ b/fog/sig/report/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sig-report" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Create and verify fog report signatures" diff --git a/fog/sql_recovery_db/Cargo.toml b/fog/sql_recovery_db/Cargo.toml index d7344013cd..40d6bd2a02 100644 --- a/fog/sql_recovery_db/Cargo.toml +++ b/fog/sql_recovery_db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-sql-recovery-db" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["Mobilecoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/test-client/Cargo.toml b/fog/test-client/Cargo.toml index 62a423a6a2..a95d09d4c9 100644 --- a/fog/test-client/Cargo.toml +++ b/fog/test-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-client" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/test_infra/Cargo.toml b/fog/test_infra/Cargo.toml index 1540363edf..ca52bc13f2 100644 --- a/fog/test_infra/Cargo.toml +++ b/fog/test_infra/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-test-infra" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/types/Cargo.toml b/fog/types/Cargo.toml index 4fb012fc7b..4d21ba274e 100644 --- a/fog/types/Cargo.toml +++ b/fog/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-types" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/uri/Cargo.toml b/fog/uri/Cargo.toml index 9e17f55232..5b7f6f8f71 100644 --- a/fog/uri/Cargo.toml +++ b/fog/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-uri" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/connection/Cargo.toml b/fog/view/connection/Cargo.toml index 794fc3b2f9..099fc7c119 100644 --- a/fog/view/connection/Cargo.toml +++ b/fog/view/connection/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-connection" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/Cargo.toml b/fog/view/enclave/Cargo.toml index c505a76e01..7f86b353ac 100644 --- a/fog/view/enclave/Cargo.toml +++ b/fog/view/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/api/Cargo.toml b/fog/view/enclave/api/Cargo.toml index 0deb35d2ff..8979727a8b 100644 --- a/fog/view/enclave/api/Cargo.toml +++ b/fog/view/enclave/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/edl/Cargo.toml b/fog/view/enclave/edl/Cargo.toml index 3125b40eea..7016205f69 100644 --- a/fog/view/enclave/edl/Cargo.toml +++ b/fog/view/enclave/edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "view_enclave_edl" diff --git a/fog/view/enclave/impl/Cargo.toml b/fog/view/enclave/impl/Cargo.toml index 504747cc1c..84f1f3c5a4 100644 --- a/fog/view/enclave/impl/Cargo.toml +++ b/fog/view/enclave/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/enclave/measurement/Cargo.toml b/fog/view/enclave/measurement/Cargo.toml index b0594ba918..1434160a5b 100644 --- a/fog/view/enclave/measurement/Cargo.toml +++ b/fog/view/enclave/measurement/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-measurement" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "MobileCoin Fog View Enclave - Application Code" diff --git a/fog/view/enclave/trusted/Cargo.lock b/fog/view/enclave/trusted/Cargo.lock index 1d6a531d6b..66da110904 100644 --- a/fog/view/enclave/trusted/Cargo.lock +++ b/fog/view/enclave/trusted/Cargo.lock @@ -679,7 +679,7 @@ dependencies = [ [[package]] name = "mc-account-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "curve25519-dalek", "displaydoc", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "mc-attest-ake" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "cargo-emit", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "mc-attest-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "bitflags", @@ -744,7 +744,7 @@ dependencies = [ [[package]] name = "mc-attest-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-ake", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "mc-attest-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "mc-attest-verifier" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cfg-if 1.0.0", @@ -792,7 +792,7 @@ dependencies = [ [[package]] name = "mc-common" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "cfg-if 1.0.0", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "mc-crypto-ake-enclave" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes-gcm", "digest", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "mc-crypto-box" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "digest", @@ -846,7 +846,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "curve25519-dalek", @@ -859,7 +859,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-derive" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "proc-macro2", "quote", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "mc-crypto-digestible-signature" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "schnorrkel-og", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "mc-crypto-hashes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "blake2", "digest", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "mc-crypto-keys" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "binascii", "curve25519-dalek", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "mc-crypto-multisig" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-digestible", "mc-crypto-keys", @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "mc-crypto-noise" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aead", "aes-gcm", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "mc-crypto-rand" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "getrandom", @@ -953,7 +953,7 @@ dependencies = [ [[package]] name = "mc-enclave-boundary" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-common", "mc-crypto-rand", @@ -964,7 +964,7 @@ dependencies = [ [[package]] name = "mc-fog-kex-rng" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "digest", "displaydoc", @@ -979,14 +979,14 @@ dependencies = [ [[package]] name = "mc-fog-ocall-oram-storage-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-fog-ocall-oram-storage-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "aligned-cmov", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "mc-fog-recovery-db-iface" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "mc-fog-sig-authority" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-crypto-keys", "signature", @@ -1024,7 +1024,7 @@ dependencies = [ [[package]] name = "mc-fog-types" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "crc", "displaydoc", @@ -1038,7 +1038,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1056,7 +1056,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-util-build-script", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-impl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aligned-cmov", "mc-attest-core", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "mc-fog-view-enclave-trusted" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "lazy_static", @@ -1175,11 +1175,11 @@ dependencies = [ [[package]] name = "mc-sgx-alloc" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-build" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cc", "lazy_static", @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "mc-sgx-alloc", @@ -1202,7 +1202,7 @@ dependencies = [ [[package]] name = "mc-sgx-compat-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "mc-sgx-debug-edl", @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "mc-sgx-css" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "sha2", @@ -1219,36 +1219,36 @@ dependencies = [ [[package]] name = "mc-sgx-debug" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-debug-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-enclave-id" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-types", ] [[package]] name = "mc-sgx-panic" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-sgx-panic-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-report-cache-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "mc-attest-core", @@ -1259,7 +1259,7 @@ dependencies = [ [[package]] name = "mc-sgx-service" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-build", "mc-sgx-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "mc-sgx-slog" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cfg-if 1.0.0", "mc-common", @@ -1277,14 +1277,14 @@ dependencies = [ [[package]] name = "mc-sgx-slog-edl" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", ] [[package]] name = "mc-sgx-sync" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "mc-sgx-panic", "mc-sgx-types", @@ -1292,11 +1292,11 @@ dependencies = [ [[package]] name = "mc-sgx-types" -version = "3.0.0-pre0" +version = "3.0.0" [[package]] name = "mc-transaction-core" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "aes", "bulletproofs-og", @@ -1328,7 +1328,7 @@ dependencies = [ [[package]] name = "mc-util-build-script" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "displaydoc", @@ -1339,7 +1339,7 @@ dependencies = [ [[package]] name = "mc-util-build-sgx" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "cargo-emit", "cc", @@ -1350,7 +1350,7 @@ dependencies = [ [[package]] name = "mc-util-encodings" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "base64", "binascii", @@ -1362,14 +1362,14 @@ dependencies = [ [[package]] name = "mc-util-from-random" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "rand_core", ] [[package]] name = "mc-util-repr-bytes" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "generic-array", "prost", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "mc-util-serial" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "prost", "serde", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "mc-watcher-api" -version = "3.0.0-pre0" +version = "3.0.0" dependencies = [ "displaydoc", "serde", diff --git a/fog/view/enclave/trusted/Cargo.toml b/fog/view/enclave/trusted/Cargo.toml index 6140d94db0..4c8600042d 100644 --- a/fog/view/enclave/trusted/Cargo.toml +++ b/fog/view/enclave/trusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-enclave-trusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "The MobileCoin Fog user-facing server's enclave entry point." diff --git a/fog/view/load-test/Cargo.toml b/fog/view/load-test/Cargo.toml index 0bd288289c..7b19226ba1 100644 --- a/fog/view/load-test/Cargo.toml +++ b/fog/view/load-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-load-test" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/fog/view/protocol/Cargo.toml b/fog/view/protocol/Cargo.toml index c385bce196..61aa0788e1 100644 --- a/fog/view/protocol/Cargo.toml +++ b/fog/view/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-protocol" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/fog/view/server/Cargo.toml b/fog/view/server/Cargo.toml index f27680bf82..9230ce82fc 100644 --- a/fog/view/server/Cargo.toml +++ b/fog/view/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-fog-view-server" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/go-grpc-gateway/testing/Cargo.toml b/go-grpc-gateway/testing/Cargo.toml index b3ff0ebcc3..40e8cddb68 100644 --- a/go-grpc-gateway/testing/Cargo.toml +++ b/go-grpc-gateway/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "go-grpc-gateway-testing" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/ledger/db/Cargo.toml b/ledger/db/Cargo.toml index bb7fa14913..d9456dca32 100644 --- a/ledger/db/Cargo.toml +++ b/ledger/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-db" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/distribution/Cargo.toml b/ledger/distribution/Cargo.toml index 4f013cbf9d..8f1ecf6bf3 100644 --- a/ledger/distribution/Cargo.toml +++ b/ledger/distribution/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-distribution" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/from-archive/Cargo.toml b/ledger/from-archive/Cargo.toml index 2d6280d5cc..d656b7c666 100644 --- a/ledger/from-archive/Cargo.toml +++ b/ledger/from-archive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-from-archive" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/migration/Cargo.toml b/ledger/migration/Cargo.toml index a0ee5143a3..d0b167ff8a 100644 --- a/ledger/migration/Cargo.toml +++ b/ledger/migration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-migration" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/ledger/sync/Cargo.toml b/ledger/sync/Cargo.toml index 94af389ef0..c8b221d14b 100644 --- a/ledger/sync/Cargo.toml +++ b/ledger/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-ledger-sync" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/libmobilecoin/Cargo.toml b/libmobilecoin/Cargo.toml index 93632aa14d..799fe12c29 100644 --- a/libmobilecoin/Cargo.toml +++ b/libmobilecoin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libmobilecoin" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/Cargo.toml b/mint-auditor/Cargo.toml index 3cf230fb65..72eac563e9 100644 --- a/mint-auditor/Cargo.toml +++ b/mint-auditor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mint-auditor/api/Cargo.toml b/mint-auditor/api/Cargo.toml index 4085fcde7b..97ad4d8558 100644 --- a/mint-auditor/api/Cargo.toml +++ b/mint-auditor/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mint-auditor-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/mobilecoind-json/Cargo.toml b/mobilecoind-json/Cargo.toml index c32bfb0c49..abdd9ef09d 100644 --- a/mobilecoind-json/Cargo.toml +++ b/mobilecoind-json/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-json" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/Cargo.toml b/mobilecoind/Cargo.toml index c730427074..15c571d562 100644 --- a/mobilecoind/Cargo.toml +++ b/mobilecoind/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/mobilecoind/api/Cargo.toml b/mobilecoind/api/Cargo.toml index 0a39f3caa1..ee77faa253 100644 --- a/mobilecoind/api/Cargo.toml +++ b/mobilecoind/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-mobilecoind-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/peers/Cargo.toml b/peers/Cargo.toml index 465f5a95c1..b9912935d7 100644 --- a/peers/Cargo.toml +++ b/peers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/peers/test-utils/Cargo.toml b/peers/test-utils/Cargo.toml index c029aba117..6e194e307e 100644 --- a/peers/test-utils/Cargo.toml +++ b/peers/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-peers-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/alloc/Cargo.toml b/sgx/alloc/Cargo.toml index d2167fe9cd..d12382281c 100644 --- a/sgx/alloc/Cargo.toml +++ b/sgx/alloc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-alloc" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] [features] diff --git a/sgx/build/Cargo.toml b/sgx/build/Cargo.toml index 01e7e42c76..5f36c1e0ab 100644 --- a/sgx/build/Cargo.toml +++ b/sgx/build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-build" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat-edl/Cargo.toml b/sgx/compat-edl/Cargo.toml index 3e2e9106a3..067bb3b49d 100644 --- a/sgx/compat-edl/Cargo.toml +++ b/sgx/compat-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/compat/Cargo.toml b/sgx/compat/Cargo.toml index d97d43affe..8dbda68a1a 100644 --- a/sgx/compat/Cargo.toml +++ b/sgx/compat/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-compat" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/css-dump/Cargo.toml b/sgx/css-dump/Cargo.toml index 1dabd4dfdc..1d7bd617d9 100644 --- a/sgx/css-dump/Cargo.toml +++ b/sgx/css-dump/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css-dump" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" license = "GPL-3.0" diff --git a/sgx/css/Cargo.toml b/sgx/css/Cargo.toml index e78f64fceb..67d143f060 100644 --- a/sgx/css/Cargo.toml +++ b/sgx/css/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-css" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/debug-edl/Cargo.toml b/sgx/debug-edl/Cargo.toml index 8d95840d5c..ddbd530fa8 100644 --- a/sgx/debug-edl/Cargo.toml +++ b/sgx/debug-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-debug-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_debug_edl" diff --git a/sgx/debug/Cargo.toml b/sgx/debug/Cargo.toml index 2494eadd44..9a9d5a0137 100644 --- a/sgx/debug/Cargo.toml +++ b/sgx/debug/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-sgx-debug" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/enclave-id/Cargo.toml b/sgx/enclave-id/Cargo.toml index 09ebb7e30b..55e782cb3c 100644 --- a/sgx/enclave-id/Cargo.toml +++ b/sgx/enclave-id/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-enclave-id" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/panic-edl/Cargo.toml b/sgx/panic-edl/Cargo.toml index 3de30f72f8..05e10a2922 100644 --- a/sgx/panic-edl/Cargo.toml +++ b/sgx/panic-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_panic_edl" diff --git a/sgx/panic/Cargo.toml b/sgx/panic/Cargo.toml index 607bb439b8..7ea426db81 100644 --- a/sgx/panic/Cargo.toml +++ b/sgx/panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-panic" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] [features] diff --git a/sgx/report-cache/api/Cargo.toml b/sgx/report-cache/api/Cargo.toml index 9f75796653..ad5226fa0c 100644 --- a/sgx/report-cache/api/Cargo.toml +++ b/sgx/report-cache/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/report-cache/untrusted/Cargo.toml b/sgx/report-cache/untrusted/Cargo.toml index 2ea63a4529..6b4f4c8be3 100644 --- a/sgx/report-cache/untrusted/Cargo.toml +++ b/sgx/report-cache/untrusted/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-report-cache-untrusted" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/service/Cargo.toml b/sgx/service/Cargo.toml index 89660de260..be26e4957e 100644 --- a/sgx/service/Cargo.toml +++ b/sgx/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-service" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/slog-edl/Cargo.toml b/sgx/slog-edl/Cargo.toml index 96a50cb79f..375aff9300 100644 --- a/sgx/slog-edl/Cargo.toml +++ b/sgx/slog-edl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog-edl" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" links = "sgx_slog_edl" diff --git a/sgx/slog/Cargo.toml b/sgx/slog/Cargo.toml index 9462416289..46bf1fd4c7 100644 --- a/sgx/slog/Cargo.toml +++ b/sgx/slog/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-slog" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/sgx/sync/Cargo.toml b/sgx/sync/Cargo.toml index 3268183463..dc08235043 100644 --- a/sgx/sync/Cargo.toml +++ b/sgx/sync/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-sync" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] [dependencies] diff --git a/sgx/types/Cargo.toml b/sgx/types/Cargo.toml index b1ba09a170..ee8980c9c9 100644 --- a/sgx/types/Cargo.toml +++ b/sgx/types/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["MobileCoin"] name = "mc-sgx-types" -version = "3.0.0-pre0" +version = "3.0.0" repository = "https://github.com/baidu/rust-sgx-sdk" license-file = "LICENSE" documentation = "https://dingelish.github.io/" diff --git a/sgx/urts/Cargo.toml b/sgx/urts/Cargo.toml index f7bcbfb924..eb561d47f2 100644 --- a/sgx/urts/Cargo.toml +++ b/sgx/urts/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-sgx-urts" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] diff --git a/test-vectors/account-keys/Cargo.toml b/test-vectors/account-keys/Cargo.toml index baeef8ad0b..83b76cf630 100644 --- a/test-vectors/account-keys/Cargo.toml +++ b/test-vectors/account-keys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-account-keys" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/b58-encodings/Cargo.toml b/test-vectors/b58-encodings/Cargo.toml index 46bd48c4ca..238ba70e30 100644 --- a/test-vectors/b58-encodings/Cargo.toml +++ b/test-vectors/b58-encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-b58-encodings" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/definitions/Cargo.toml b/test-vectors/definitions/Cargo.toml index 2f824db1a8..32910e2820 100644 --- a/test-vectors/definitions/Cargo.toml +++ b/test-vectors/definitions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-definitions" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/memos/Cargo.toml b/test-vectors/memos/Cargo.toml index 64a8515ad6..e8e40f13b6 100644 --- a/test-vectors/memos/Cargo.toml +++ b/test-vectors/memos/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-memos" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/test-vectors/tx-out-records/Cargo.toml b/test-vectors/tx-out-records/Cargo.toml index b836ff332b..292556d487 100644 --- a/test-vectors/tx-out-records/Cargo.toml +++ b/test-vectors/tx-out-records/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-test-vectors-tx-out-records" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/Cargo.toml b/transaction/core/Cargo.toml index f1995fbba4..242fb88fe1 100644 --- a/transaction/core/Cargo.toml +++ b/transaction/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/core/test-utils/Cargo.toml b/transaction/core/test-utils/Cargo.toml index 0509330c3c..54db0629f3 100644 --- a/transaction/core/test-utils/Cargo.toml +++ b/transaction/core/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-core-test-utils" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/transaction/std/Cargo.toml b/transaction/std/Cargo.toml index 419f3328fb..8b350f0a81 100644 --- a/transaction/std/Cargo.toml +++ b/transaction/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-transaction-std" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/b58-decoder/Cargo.toml b/util/b58-decoder/Cargo.toml index 1b39331b0b..0cad9c0ca2 100644 --- a/util/b58-decoder/Cargo.toml +++ b/util/b58-decoder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-b58-decoder" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/enclave/Cargo.toml b/util/build/enclave/Cargo.toml index 529db4a400..00b08ee7f1 100644 --- a/util/build/enclave/Cargo.toml +++ b/util/build/enclave/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-enclave" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Enclave build assistance, from MobileCoin." diff --git a/util/build/grpc/Cargo.toml b/util/build/grpc/Cargo.toml index a389850536..19041dc85e 100644 --- a/util/build/grpc/Cargo.toml +++ b/util/build/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-grpc" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/build/info/Cargo.toml b/util/build/info/Cargo.toml index ae2be60a0d..334f95bc47 100644 --- a/util/build/info/Cargo.toml +++ b/util/build/info/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-info" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] build = "build.rs" edition = "2018" diff --git a/util/build/script/Cargo.toml b/util/build/script/Cargo.toml index fd309dcdcc..b940da5caa 100644 --- a/util/build/script/Cargo.toml +++ b/util/build/script/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-script" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Cargo build-script assistance, from MobileCoin." diff --git a/util/build/sgx/Cargo.toml b/util/build/sgx/Cargo.toml index a51de66f84..62320539d3 100644 --- a/util/build/sgx/Cargo.toml +++ b/util/build/sgx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-build-sgx" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "SGX utilities assistance, from MobileCoin." diff --git a/util/cli/Cargo.toml b/util/cli/Cargo.toml index 463620d1bb..b4ba6a5745 100644 --- a/util/cli/Cargo.toml +++ b/util/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-cli" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/encodings/Cargo.toml b/util/encodings/Cargo.toml index f24932b6d9..74680bd8a8 100644 --- a/util/encodings/Cargo.toml +++ b/util/encodings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-encodings" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Support for various simple encodings (hex strings, base64 strings, Intel x86_64 structures, etc.)" diff --git a/util/ffi/Cargo.toml b/util/ffi/Cargo.toml index b51de8b943..6911ae769e 100644 --- a/util/ffi/Cargo.toml +++ b/util/ffi/Cargo.toml @@ -1,5 +1,5 @@ [package] name = "mc-util-ffi" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/from-random/Cargo.toml b/util/from-random/Cargo.toml index 6e0e3634c7..256d858921 100644 --- a/util/from-random/Cargo.toml +++ b/util/from-random/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-from-random" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "A trait for constructing an object from a random number generator." diff --git a/util/generate-sample-ledger/Cargo.toml b/util/generate-sample-ledger/Cargo.toml index 83794c022c..752ba01085 100644 --- a/util/generate-sample-ledger/Cargo.toml +++ b/util/generate-sample-ledger/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-generate-sample-ledger" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-admin-tool/Cargo.toml b/util/grpc-admin-tool/Cargo.toml index 3d07b16511..c849e5a5a3 100644 --- a/util/grpc-admin-tool/Cargo.toml +++ b/util/grpc-admin-tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-admin-tool" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc-token-generator/Cargo.toml b/util/grpc-token-generator/Cargo.toml index 46e2b62581..d0a660b740 100644 --- a/util/grpc-token-generator/Cargo.toml +++ b/util/grpc-token-generator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc-token-generator" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/grpc/Cargo.toml b/util/grpc/Cargo.toml index 8a69173c53..2f9181f75d 100644 --- a/util/grpc/Cargo.toml +++ b/util/grpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-grpc" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Runtime gRPC Utilities" diff --git a/util/host-cert/Cargo.toml b/util/host-cert/Cargo.toml index 94d86467c5..fe1be013dd 100644 --- a/util/host-cert/Cargo.toml +++ b/util/host-cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-host-cert" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/keyfile/Cargo.toml b/util/keyfile/Cargo.toml index 78222d6e9e..5f0160b231 100644 --- a/util/keyfile/Cargo.toml +++ b/util/keyfile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-keyfile" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/lmdb/Cargo.toml b/util/lmdb/Cargo.toml index c2c95bf194..8551243740 100644 --- a/util/lmdb/Cargo.toml +++ b/util/lmdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-lmdb" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/logger-macros/Cargo.toml b/util/logger-macros/Cargo.toml index 70a2093d47..4a2568487c 100644 --- a/util/logger-macros/Cargo.toml +++ b/util/logger-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-logger-macros" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metered-channel/Cargo.toml b/util/metered-channel/Cargo.toml index 8d8682096d..9242b3b86a 100644 --- a/util/metered-channel/Cargo.toml +++ b/util/metered-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metered-channel" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/metrics/Cargo.toml b/util/metrics/Cargo.toml index 745fc96590..159a2cfe4a 100644 --- a/util/metrics/Cargo.toml +++ b/util/metrics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-metrics" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/parse/Cargo.toml b/util/parse/Cargo.toml index f1334b1a72..fd42cc436e 100644 --- a/util/parse/Cargo.toml +++ b/util/parse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-parse" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" description = "Helpers for parsing, particularly, for use with Clap and similar" diff --git a/util/repr-bytes/Cargo.toml b/util/repr-bytes/Cargo.toml index b2953d4c2d..17939a5581 100644 --- a/util/repr-bytes/Cargo.toml +++ b/util/repr-bytes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-repr-bytes" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" readme = "README.md" diff --git a/util/seeded-ed25519-key-gen/Cargo.toml b/util/seeded-ed25519-key-gen/Cargo.toml index 876893630c..cf363db3bd 100644 --- a/util/seeded-ed25519-key-gen/Cargo.toml +++ b/util/seeded-ed25519-key-gen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-seeded-ed25519-key-gen" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/serial/Cargo.toml b/util/serial/Cargo.toml index f382db4873..4f3a9db075 100644 --- a/util/serial/Cargo.toml +++ b/util/serial/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-serial" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/telemetry/Cargo.toml b/util/telemetry/Cargo.toml index c7b1931580..2c61ed38fb 100644 --- a/util/telemetry/Cargo.toml +++ b/util/telemetry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-telemetry" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-helper/Cargo.toml b/util/test-helper/Cargo.toml index 110597f2c3..b6262b70e2 100644 --- a/util/test-helper/Cargo.toml +++ b/util/test-helper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-helper" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-vector/Cargo.toml b/util/test-vector/Cargo.toml index 7a8448c1df..ef7b53a499 100644 --- a/util/test-vector/Cargo.toml +++ b/util/test-vector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-vector" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/test-with-data/Cargo.toml b/util/test-with-data/Cargo.toml index 2b285df40e..6138ac7db0 100644 --- a/util/test-with-data/Cargo.toml +++ b/util/test-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-test-with-data" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/util/uri/Cargo.toml b/util/uri/Cargo.toml index bd1f8c3d42..b731e4ceb4 100644 --- a/util/uri/Cargo.toml +++ b/util/uri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-util-uri" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/wasm-test/Cargo.toml b/wasm-test/Cargo.toml index 2d1d689983..e901cc29b0 100644 --- a/wasm-test/Cargo.toml +++ b/wasm-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-wasm-test" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2021" diff --git a/watcher/Cargo.toml b/watcher/Cargo.toml index 6b35e1a2f1..da13e08712 100644 --- a/watcher/Cargo.toml +++ b/watcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" diff --git a/watcher/api/Cargo.toml b/watcher/api/Cargo.toml index 73dc41425f..2af18bed2c 100644 --- a/watcher/api/Cargo.toml +++ b/watcher/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-watcher-api" -version = "3.0.0-pre0" +version = "3.0.0" authors = ["MobileCoin"] edition = "2018" From 6bb0953c193e443ecdfe8329ee2bab11fdab2ce7 Mon Sep 17 00:00:00 2001 From: James Cape Date: Wed, 26 Oct 2022 12:11:15 -0700 Subject: [PATCH 75/77] Fix mob script (#2782) --- mob | 289 +++++++++++++++++++++--------------------------------------- 1 file changed, 100 insertions(+), 189 deletions(-) diff --git a/mob b/mob index 16b57cfd9f..fd113b1b7a 100755 --- a/mob +++ b/mob @@ -13,24 +13,15 @@ The basic operation is like this: 0. `./mob prompt` is invoked -1. Read .mobconf to find the Dockerfile and Dockerfile-version file, and the remote -source for the image to use for caching. +1. Read .mobconf to find the remote source for the image. -2. Pull the remote version if available, or the previous if not available. (This -is if you want to make changes to the image locally.) - -3. Try to build the Dockerfile, using the version that we pulled as a cache source. -If you didn't change it then this completes instantly. - -4. Do an appropriate form of `docker run -it bash` in this image, mounting the +1. Do an appropriate form of `docker run -it bash` in this image, mounting the root of the repository to `/tmp/mobilenode` and setting that as the working directory. -There are some flags and options for modifying this process, e.g. `image` just builds -the image and doesn't run it or give you a prompt. `--dry-run` just -shows you the shell commands without executing them. `--no-pull` means you don't -pull a docker image at all. +There are some flags and options for modifying this process, e.g. `--dry-run` just +shows you the shell commands without executing them. -`mob` tool attemps to mount the `/dev/isgx` device correctly if it is available +`mob` tool attempts to mount the `/dev/isgx` device correctly if it is available and you selected `--hw` mode, so that you can run tests in hardware mode. usage notes (ssh) @@ -42,25 +33,6 @@ ssh stuff is not needed for that, this is for any private dependencies of the mo repo.) If provided, these options will try to get your credentials from the host environment into the container so that cargo can pull. -usage notes (changing the Dockerfile) -------------------------------------- - -When you make changes to the Dockerfile, you should increment the minor version, -and commit that alongside the changes. - -Previous minor versions are used as cache sources. Caching never occurs across -major version upgrade so this is a way to ensure that security updates are pulled in -over time. - -The major version number is treated as a string -- it doesn't have to be a number, -if you have a long-lived release branch in git-flow and need to patch the dockerfile, -you may want to change the major version to some string to make an independent fork -of dockerfile versions, e.g. `10_15` -> `release-04-09-2010_0` - -The farm only publishes versions when they are merged to master, but your local -builds of the images are also used as caches. If you want to prevent pulling from -the farm entirely use `--no-pull`. - mobconf ------- @@ -73,13 +45,14 @@ it is an error if it can't find one. .mobconf sections: [image] -dockerfile = path to dockerfile. build context is the dir of dockerfile -target = layer in dockerfile that is targetted -repository = storage for remote images from farm e.g. gcr.io/mobilenode-211420 (optional) +url = The image URL to pass to docker run +tag = Image tag/version to use """ import argparse import configparser +import getpass +import grp import os import pathlib import platform @@ -87,29 +60,29 @@ import subprocess import sys parser = argparse.ArgumentParser(prog="mob", description="Perform an action or get a prompt in docker build environment") -parser.add_argument("action", choices=["prompt", "image", "default-tag"], help=""" +parser.add_argument("action", choices=["prompt", "run"], help=""" (prompt) Run bash in the build environment - (image) Only create the builder image, don't even run bash - (default-tag) Print on stdout the default image tag, to support automation + (run) Run the given command (passed to `docker run`) """) -parser.add_argument("container_name", nargs='?', default=None, help="The name for the container, run with prompt") +parser.add_argument("--name", nargs='?', default=None, help="The name for the container, run with prompt") parser.add_argument("--hw", action="store_true", help="Set SGX_MODE=HW. Default is SGX_MODE=SW") parser.add_argument("--ias-prod", action="store_true", help="Set IAS_MODE=PROD. Default is IAS_MODE=DEV. This affects which IAS endpoints we use.") parser.add_argument("--dry-run", action="store_true", help="Don't run docker, show how we would invoke docker.") -parser.add_argument("--tag", default=None, type=str, help="Use given tag for builder image rather than the autogenerated one. (Also cache from here)") -parser.add_argument("--no-pull", action="store_true", help="By default, we attempt to pull latest builder-install from gcr.io (cloudbuild), and use it for caching. Disables that.") +parser.add_argument("--no-pull", action='store_true', help='Skip the `docker image pull` step.') +parser.add_argument("--tag", default=None, type=str, help="Use given tag for image rather than the one in .mobconf") parser.add_argument("--verbose", action="store_true", help="Show the commands on stdout. True by default when noninteractive, implied by dry-run") parser.add_argument("--ssh-dir", action='store_true', help='Mount $HOME/.ssh directory into /root/.ssh for ssh key access') parser.add_argument("--ssh-agent", action='store_true', help='Use ssh-agent on host machine for ssh authentication. Also controlled by SSH_AUTH_SOCK env variable') parser.add_argument("--expose", nargs='+', default=None, help="Any additional ports to expose") parser.add_argument("--publish", nargs='+', default=None, help="Any additional ports to publish, e.g. if running wallet locally.") +parser.add_argument("--cmd", nargs='+', default=None, help="Run this command inside the bash shell instead of an interactive prompt") +parser.add_argument("--run-as-root", action='store_true', help="run prompt as root instead of local user") args = parser.parse_args() ### # Implement forced settings ### - if args.dry_run or not sys.stdout.isatty(): args.verbose = True @@ -135,15 +108,14 @@ def vprint_command(cmd): """ Print a command, whether it is in shell style or list style. """ if isinstance(cmd, list): cmd = ' '.join(cmd) - vprint('$ ' + cmd) - + vprint(f'$ {cmd}') # Run a command, unless we are in dry_run mode and should not do that # Print the command if in verbose mode -def maybe_run(command): - vprint_command(command) +def maybe_run(cmd, **kwargs): + vprint_command(cmd) if not args.dry_run: - subprocess.check_call(command) + return subprocess.check_call(cmd, **kwargs) # Change directory. # Print the command if in verbose mode @@ -151,16 +123,6 @@ def verbose_chdir(path): vprint_command(['cd', path]) os.chdir(path) -# Check if we have a given docker tag -def have_tag(arg): - try: - cmd = ["docker", "images", "-q", arg] - vprint_command(cmd) - return len(subprocess.check_output(cmd)) > 0 - except subprocess.CalledProcessError: - eprint("Error searching for image: " + arg) - return False - # Check if we have a git commit and compute outside the container # Sometimes git cannot be used in the container, if building in public dir, # or if you used git worktree to make a new worktree. @@ -182,20 +144,7 @@ def get_git_commit(): # Check if docker is available and bail out early with a message if appropriate if not args.dry_run: - cmd = "command -v docker > /dev/null 2>&1" - vprint_command(cmd) - try: - retcode = subprocess.call(cmd, shell=True) - except: - eprint("Warning: unable to check for docker being installed") - else: - if retcode != 0: - if not args.verbose: - eprint(cmd) - eprint("docker not found: retcode =", retcode) - eprint("Docker is required to use the mob tool.") - eprint("It is recommended to install from https://docs.docker.com/get-docker/") - sys.exit(1) + maybe_run("command -v docker > /dev/null 2>&1", shell=True) # Check for any SSH handling if "SSH_AUTH_SOCK" in os.environ: @@ -207,7 +156,7 @@ if "SSH_AUTH_SOCK" in os.environ: args.ssh_agent = True # Find work directory and change directory there -# This is based on searching for nearest .mobconf file, moving upwards from cwd +# This is based on searching for nearest .mobconf file, moving upwards from CWD top_level = os.getcwd() while not os.path.exists(os.path.join(top_level, ".mobconf")): new_top_level = os.path.dirname(top_level) @@ -216,83 +165,42 @@ while not os.path.exists(os.path.join(top_level, ".mobconf")): sys.exit(1) top_level = new_top_level -mobconf = configparser.ConfigParser() -mobconf.read(".mobconf") - verbose_chdir(top_level) -# Get dockerfile-version data Find and parse dockerfile version file -if 'Dockerfile-version' in mobconf['image']: - docker_dir = None - version_data = mobconf['image']['Dockerfile-version'] -else: - raise Exception("Neither 'dockerfile' nor 'Dockerfile-version' was found in .mobconf") - -# Calculate default tag. -repo = mobconf['image']['repository'] if 'repository' in mobconf['image'] else "" -default_tag = os.path.join(repo, mobconf['image']['target'] + ':' + version_data) -parent_tag = None - -if args.action == "default-tag": - print(default_tag, end='') - sys.exit(0) - -### -# docker build -### - -if args.tag is None: - tag = default_tag -else: - tag = args.tag - -# Pull cache sources from repository if we have one -if 'repository' in mobconf['image']: - if not args.no_pull: - try: - maybe_run(["docker", "image", "pull", default_tag]) - except: - eprint("Warning: Could not pull from: ", default_tag) - if parent_tag is not None: - try: - maybe_run(["docker", "image", "pull", parent_tag]) - except: - eprint("Warning: Could not pull from: ", parent_tag) -else: - vprint('No repository found in .mobconf to pull from') +mobconf = configparser.ConfigParser() +mobconf.read(".mobconf") +image_conf = mobconf['image'] or {} -build_env = [ - "RUST_BACKTRACE=full", - "SGX_MODE=HW" if args.hw else "SGX_MODE=SW", - "IAS_MODE=PROD" if args.ias_prod else "IAS_MODE=DEV", -] +image_url = image_conf['url'] if 'url' in image_conf else '' +if not image_url: + raise Exception("Missing image.url in .mobconf") -# Don't build the image if we already have it, unless -# image action was specified (user requested the image) +tag = args.tag or image_conf['tag'] if 'tag' in image_conf else '' +if not tag: + raise Exception("Pass a tag via --tag or image.tag in .mobconf") -if args.action == "image": - sys.exit(0) +image_and_tag = f'{image_url}:{tag}' -verbose_chdir(top_level) +if not args.no_pull: + maybe_run(["docker", "image", "pull", image_and_tag]) -### -# Implement mount-through option -### +## +# docker run flags +## # Compute mount_point, mount_from, and workdir mount_point = "/tmp/mobilenode" workdir = mount_point mount_from = top_level -## -# Calculate docker run flags -## - # docker-run parameters: docker_run = ["docker", "run", - # container doesn't know mount_point so we have to set this - "--env", "CARGO_HOME=" + mount_point + "/cargo", + # Remove container afterwards. + "--rm", + # Give docker its own subdirectory under target so it doesn't trash + # the host target directory, but will still be cleaned up with it. + "--env", "CARGO_TARGET_DIR=" + mount_point + "/target/docker", # This is required to run the fog unit tests "--env", "TEST_DATABASE_URL=postgres://localhost", # This is consumed by servers when running locally in the container @@ -300,6 +208,20 @@ docker_run = ["docker", "--volume", mount_from + ":" + mount_point, "--workdir", workdir] +# the entrypoint script will pick up these vars and set up the user. +if not args.run_as_root: + # figure out user and group + uid = os.getuid() + gid = os.getgid() + username = getpass.getuser() + groupname = grp.getgrgid(gid)[0] + docker_run.extend([ + "--env", "EXTERNAL_UID=" + str(uid), + "--env", "EXTERNAL_GID=" + str(gid), + "--env", "EXTERNAL_USER=" + username, + "--env", "EXTERNAL_GROUP=" + groupname + ]) + # Add /dev/isgx if HW mode, and it is available # Mimicking bash checks `if [ -c /dev/isgx ]` # The purpose of this check is that it is possible to build in HW mode, and even @@ -313,60 +235,53 @@ if args.hw: eprint("Did not find /dev/isgx on the host, skipping") # Add build environment -for pair in build_env: - docker_run.extend(["--env", pair]) +build_env = [ + "RUST_BACKTRACE=full", + "SGX_MODE=HW" if args.hw else "SGX_MODE=SW", + "IAS_MODE=PROD" if args.ias_prod else "IAS_MODE=DEV", +] # Add GIT_COMMIT if present git_commit = get_git_commit() -if git_commit is not None: - docker_run.extend(["--env", "GIT_COMMIT=" + git_commit]) - -# Enable sccache usage if sccache dir is found on the host. -# We do this by mounting the dir into the container, and setting the sccache -# environment variable, which can be picked up by Makefile. sccache is already -# installed in the container. -# -# An alternative might be to run the sccache server outside the container, and -# expose port 4226 so that they can talk, per -# https://github.com/mozilla/sccache/blob/master/docs/Jenkins.md -# -# This tool is not used in jenkins anymore so we don't do that -host_sccache_dir = os.path.expanduser("~/.cache/sccache") # per docs this is the default for sccache -if "SCCACHE_DIR" in os.environ: - host_sccache_dir = os.environ["SCCACHE_DIR"] -if os.path.isdir(host_sccache_dir): - docker_run.extend([ - "--env", "SCCACHE=/root/.cargo/bin/sccache", - "--volume", host_sccache_dir + ":" + "/root/.cache/sccache", - ]) +if git_commit: + build_env.extend([f'GIT_COMMIT={git_commit}']) + +for pair in build_env: + docker_run.extend(["--env", pair]) # If running interactively (with a tty), get a tty in the container also # This allows colored build logs when running locally without messing up logs in CI if sys.stdout.isatty(): docker_run.extend(["-t"]) +ports = [] # in prompt, use -i to get user input if args.action == "prompt": docker_run.extend(["-i"]) -# ports might be exposed to run clients or a local network -if args.action == "prompt": + # ports might be exposed to run clients or a local network + ports = [ + "8080", + "8081", + "8443", + "3223", + "3225", + "3226", + "3228", + "4444", + ] + + # debug options allow us to attach gdb when debugging failing tests docker_run.extend([ - "--expose", "8080", - "--expose", "8081", - "--expose", "8443", - "--expose", "3223", - "--expose", "3225", - "--expose", "3226", - "--expose", "3228", - "--expose", "4444", + "--cap-add", "SYS_PTRACE", ]) - if args.expose is not None: - for port in args.expose: - docker_run.extend(["--expose", port]) - if args.publish is not None: - for port in args.publish: - docker_run.extend(["--publish", "{}:{}".format(port, port)]) + +ports.extend(args.expose or []) +for port in ports: + docker_run.extend(["--expose", port]) + +for port in args.publish or []: + docker_run.extend(["--publish", "{}:{}".format(port, port)]) # Map in the ssh directory, or the ssh-agent socket if args.ssh_dir: @@ -378,31 +293,27 @@ elif args.ssh_agent: docker_run.extend(["--env", "SSH_AUTH_SOCK=/tmp/ssh_auth_sock"]) docker_run.extend(["--volume", os.environ["SSH_AUTH_SOCK"] + ":" + "/tmp/ssh_auth_sock"]) -# debug options allow you to attach gdb when debugging failing tests -if args.action == "prompt": - docker_run.extend([ - "--cap-add", "SYS_PTRACE", - ]) - # Name the container if a name was provided -if args.container_name is not None: - docker_run.extend([ - "--name", args.container_name, - ]) +if args.name: + docker_run.extend(["--name", args.name]) # Add image name and command -docker_run.extend([tag]) +docker_run.extend([image_and_tag]) docker_run.extend(["/bin/bash"]) +if args.cmd: + cmd = ' '.join(args.cmd) + vprint('Running command in docker:', cmd) + docker_run.extend(["-c", cmd]) + try: maybe_run(docker_run) except subprocess.CalledProcessError as exception: + if args.cmd: + # Make sure custom commands have their expected return codes + sys.exit(exception.returncode) if args.action == 'prompt' and exception.returncode == 130: - # This is normal exit of prompt + # This is a normal exit of prompt sys.exit(0) raise # rethrow -finally: - # cleanup named container on exit - if args.container_name is not None: - maybe_run(["docker", "rm", "-f", args.container_name]) From 87a3d97c82fe42a31200c7aacefaee11df137a50 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Fri, 28 Oct 2022 19:04:34 -0500 Subject: [PATCH 76/77] use tag as the primary value in the docker tag construction (#2788) --- .internal-ci/util/metadata.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.internal-ci/util/metadata.sh b/.internal-ci/util/metadata.sh index 8a7ea4a3a9..f17584d78f 100755 --- a/.internal-ci/util/metadata.sh +++ b/.internal-ci/util/metadata.sh @@ -73,8 +73,8 @@ case "${GITHUB_REF_TYPE}" in # Set docker metadata action compatible tag. Short tag + metadata tag. docker_tag=$(cat << EOF -type=raw,value=${version},priority=20 -type=raw,value=${version}.${GITHUB_RUN_NUMBER}.${sha},priority=10 +type=raw,value=${tag},priority=20 +type=raw,value=${tag}.${GITHUB_RUN_NUMBER}.${sha},priority=10 EOF ) From df19fabc2fe1d301f12899cec7b53f4507b66f69 Mon Sep 17 00:00:00 2001 From: Jason Greathouse Date: Thu, 10 Nov 2022 10:05:46 -0600 Subject: [PATCH 77/77] release/V3 - CD from backup (#2802) * CD - restore blockchain and fog db from backups * Update deployments to reduce test cluster resources * values for compatibility with dev networks that have token 1 Co-authored-by: Nick Santana --- .github/actionlint.yaml | 1 + .github/workflows/mobilecoin-dev-cd.yaml | 198 +++------- .github/workflows/mobilecoin-dev-delete.yaml | 19 +- .../mobilecoin-dispatch-dev-delete.yaml | 9 +- .../mobilecoin-dispatch-dev-deploy.yaml | 83 ++--- .../mobilecoin-dispatch-dev-test.yaml | 37 +- ...ilecoin-dispatch-dev-update-consensus.yaml | 52 +-- .../mobilecoin-workflow-dev-bootstrap.yaml | 175 +++++++++ .../mobilecoin-workflow-dev-deploy.yaml | 340 +++++++----------- .../mobilecoin-workflow-dev-reset.yaml | 76 ++-- ...lecoin-workflow-dev-setup-environment.yaml | 229 ++++++++++++ .../mobilecoin-workflow-dev-test.yaml | 50 ++- ...ilecoin-workflow-dev-update-consensus.yaml | 197 ++++------ .../helm/mc-core-dev-env-setup/Chart.yaml | 10 - .../helm/mc-core-dev-env-setup/values.yaml | 40 +-- .internal-ci/test/mint-auditor-test.sh | 2 +- .internal-ci/test/minting-config-tx-test.sh | 4 +- .internal-ci/test/minting-tx-test.sh | 2 +- .internal-ci/util/generate_dev_values.sh | 16 +- .internal-ci/util/generate_minting_keys.sh | 35 +- .internal-ci/util/generate_tokens_config.sh | 33 +- .internal-ci/util/tokens.base.json | 8 + 22 files changed, 817 insertions(+), 799 deletions(-) create mode 100644 .github/workflows/mobilecoin-workflow-dev-bootstrap.yaml create mode 100644 .github/workflows/mobilecoin-workflow-dev-setup-environment.yaml diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 5826c623c5..4c0c348faa 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -3,3 +3,4 @@ self-hosted-runner: labels: - small - large + - large-cd diff --git a/.github/workflows/mobilecoin-dev-cd.yaml b/.github/workflows/mobilecoin-dev-cd.yaml index 146f8321ed..ae92459c7d 100644 --- a/.github/workflows/mobilecoin-dev-cd.yaml +++ b/.github/workflows/mobilecoin-dev-cd.yaml @@ -33,12 +33,14 @@ concurrency: group: mobilecoin-dev-cd-${{ github.head_ref || github.ref }} cancel-in-progress: true +# Ignore dependabot. We just need to 'if' the top level jobs. +# Other jobs that 'need' these top level jobs will be skipped. jobs: ############################################ # Generate environment information ############################################ generate-metadata: - if: github.actor != 'dependabot[bot]' + if: "! startsWith(github.head_ref, 'dependabot/')" name: 👾 Environment Info 👾 runs-on: [self-hosted, Linux, small] outputs: @@ -48,7 +50,6 @@ jobs: docker_org: ${{ env.DOCKER_ORG }} chart_repo: ${{ env.CHART_REPO }} release_1x_tag: ${{ env.RELEASE_1X_TAG }} - steps: - name: Checkout uses: actions/checkout@v3 @@ -72,8 +73,9 @@ jobs: # Build binaries ######################################### build-rust-hardware-projects: - if: github.actor != 'dependabot[bot]' - runs-on: [self-hosted, Linux, large] + needs: + - generate-metadata + runs-on: [self-hosted, Linux, large-cd] container: image: mobilecoin/rust-sgx-base:v0.0.18 env: @@ -186,8 +188,9 @@ jobs: path: rust_build_artifacts/ build-go-projects: - if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, small] + needs: + - generate-metadata container: image: golang:1.16.4 steps: @@ -235,15 +238,14 @@ jobs: # Create/Refresh base runtime image ######################################## docker-base: - if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, small] + needs: + - generate-metadata steps: - name: Checkout - if: "! contains(github.event.head_commit.message, '[skip docker]')" uses: actions/checkout@v3 - name: Generate Docker Tags - if: "! contains(github.event.head_commit.message, '[skip docker]')" id: docker_meta uses: docker/metadata-action@v4 with: @@ -254,18 +256,15 @@ jobs: type=sha - name: Set up Docker Buildx - if: "! contains(github.event.head_commit.message, '[skip docker]')" uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - if: "! contains(github.event.head_commit.message, '[skip docker]')" uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Publish to DockerHub - if: "! contains(github.event.head_commit.message, '[skip docker]')" id: docker_publish_dockerhub uses: docker/build-push-action@v3 with: @@ -281,7 +280,6 @@ jobs: # Build/Publish public artifacts ######################################### docker: - if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, small] needs: - build-go-projects @@ -303,25 +301,21 @@ jobs: - watcher steps: - name: Checkout - if: "! contains(github.event.head_commit.message, '[skip docker]')" uses: actions/checkout@v3 - name: Cache rust build binaries - if: "! contains(github.event.head_commit.message, '[skip docker]')" id: rust_artifact_cache uses: ./.github/actions/mobilecoin-cache-rust-binaries with: cache_buster: ${{ secrets.CACHE_BUSTER }} - name: Cache go build binaries - if: "! contains(github.event.head_commit.message, '[skip docker]')" id: go_artifact_cache uses: ./.github/actions/mobilecoin-cache-go-binaries with: cache_buster: ${{ secrets.CACHE_BUSTER }} - name: Generate Docker Tags - if: "! contains(github.event.head_commit.message, '[skip docker]')" id: docker_meta uses: docker/metadata-action@v4 with: @@ -330,18 +324,15 @@ jobs: ${{ needs.generate-metadata.outputs.docker_tag }} - name: Set up Docker Buildx - if: "! contains(github.event.head_commit.message, '[skip docker]')" uses: docker/setup-buildx-action@v2 - name: Login to DockerHub - if: "! contains(github.event.head_commit.message, '[skip docker]')" uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Publish to DockerHub - if: "! contains(github.event.head_commit.message, '[skip docker]')" id: docker_publish_dockerhub uses: docker/build-push-action@v3 with: @@ -358,7 +349,6 @@ jobs: tags: ${{ steps.docker_meta.outputs.tags }} charts: - if: github.actor != 'dependabot[bot]' runs-on: [self-hosted, Linux, small] needs: - docker @@ -384,7 +374,7 @@ jobs: - name: Package and publish chart if: "! contains(github.event.head_commit.message, '[skip charts]')" - uses: mobilecoinofficial/gha-k8s-toolbox@a89efdf4305f3b926b1bb61a59f267532406e653 + uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: helm-publish chart_repo_username: ${{ secrets.HARBOR_USERNAME }} @@ -394,122 +384,39 @@ jobs: chart_version: ${{ needs.generate-metadata.outputs.tag }} chart_path: .internal-ci/helm/${{ matrix.chart }} -################################# -# Reset existing namespace -################################# - dev-reset: - if: github.actor != 'dependabot[bot]' +################################################ +# Bootstrap namespace to v1.1.3-dev from backup +################################################ + bootstrap-v1-bv0: + uses: ./.github/workflows/mobilecoin-workflow-dev-bootstrap.yaml needs: - generate-metadata - uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml with: - namespace: ${{ needs.generate-metadata.outputs.namespace }} - delete_namespace: false - secrets: - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - -####################################### -# Deploy 1.x release to namespace -####################################### - deploy-v1-bv0-release: - if: github.actor != 'dependabot[bot]' - uses: ./.github/workflows/mobilecoin-workflow-dev-deploy.yaml - needs: - - dev-reset - - generate-metadata - with: - block_version: "0" + block_version: 0 chart_repo: ${{ needs.generate-metadata.outputs.chart_repo }} - docker_image_org: ${{ needs.generate-metadata.outputs.docker_org }} - ingest_color: blue - minting_config_enabled: false namespace: ${{ needs.generate-metadata.outputs.namespace }} version: ${{ needs.generate-metadata.outputs.release_1x_tag }} - secrets: - CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - FOG_KEYS_SEED: ${{ secrets.DEV_FOG_KEYS_SEED }} - FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} - FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} - FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} - IAS_KEY: ${{ secrets.DEV_IAS_KEY }} - IAS_SPID: ${{ secrets.DEV_IAS_SPID }} - INITIAL_KEYS_SEED: ${{ secrets.DEV_INITIAL_KEYS_SEED }} - IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} - MNEMONIC_FOG_KEYS_SEED: ${{ secrets.DEV_MNEMONIC_FOG_KEYS_SEED }} - MNEMONIC_KEYS_SEED: ${{ secrets.DEV_MNEMONIC_KEYS_SEED }} - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - - test-v1-bv0-release: - if: github.actor != 'dependabot[bot]' - uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml - needs: - - deploy-v1-bv0-release - - generate-metadata - with: - fog_distribution: true - ingest_color: blue - namespace: ${{ needs.generate-metadata.outputs.namespace }} - testing_block_v0: true - testing_block_v2: false - secrets: - CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} - FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} + secrets: inherit ############################################### # Deploy current version to namespace block v2 ############################################### deploy-current-bv0-release: - if: github.actor != 'dependabot[bot]' uses: ./.github/workflows/mobilecoin-workflow-dev-deploy.yaml needs: - - test-v1-bv0-release + - bootstrap-v1-bv0 - charts - generate-metadata with: - block_version: "0" + block_version: 0 chart_repo: ${{ needs.generate-metadata.outputs.chart_repo }} docker_image_org: ${{ needs.generate-metadata.outputs.docker_org }} ingest_color: green - minting_config_enabled: true namespace: ${{ needs.generate-metadata.outputs.namespace }} version: ${{ needs.generate-metadata.outputs.tag }} - secrets: - CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - FOG_KEYS_SEED: ${{ secrets.DEV_FOG_KEYS_SEED }} - FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} - FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} - FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} - IAS_KEY: ${{ secrets.DEV_IAS_KEY }} - IAS_SPID: ${{ secrets.DEV_IAS_SPID }} - INITIAL_KEYS_SEED: ${{ secrets.DEV_INITIAL_KEYS_SEED }} - IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} - MNEMONIC_FOG_KEYS_SEED: ${{ secrets.DEV_MNEMONIC_FOG_KEYS_SEED }} - MNEMONIC_KEYS_SEED: ${{ secrets.DEV_MNEMONIC_KEYS_SEED }} - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} + secrets: inherit test-current-bv0-release: - if: github.actor != 'dependabot[bot]' uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml needs: - deploy-current-bv0-release @@ -520,19 +427,12 @@ jobs: namespace: ${{ needs.generate-metadata.outputs.namespace }} testing_block_v0: true testing_block_v2: false - - secrets: - CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} - FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} + secrets: inherit ################################################# -# Update current consensus to namespace block v3 +# Update current consensus to namespace block v2 ################################################# update-current-to-bv2: - if: github.actor != 'dependabot[bot]' uses: ./.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml needs: - test-current-bv0-release @@ -540,27 +440,11 @@ jobs: with: block_version: "2" chart_repo: ${{ needs.generate-metadata.outputs.chart_repo }} - docker_image_org: ${{ needs.generate-metadata.outputs.docker_org }} - minting_config_enabled: true namespace: ${{ needs.generate-metadata.outputs.namespace }} version: ${{ needs.generate-metadata.outputs.tag }} - secrets: - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} - FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} - IAS_KEY: ${{ secrets.DEV_IAS_KEY }} - IAS_SPID: ${{ secrets.DEV_IAS_SPID }} - IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} + secrets: inherit test-current-bv2-release: - if: github.actor != 'dependabot[bot]' uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml needs: - update-current-to-bv2 @@ -571,17 +455,24 @@ jobs: namespace: ${{ needs.generate-metadata.outputs.namespace }} testing_block_v0: false testing_block_v2: true - secrets: - CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} - FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - - cleanup-on-pr: + secrets: inherit + +############################################################### +# Clean up deployments +############################################################### +# we want to clean up on everything but master and feature/* +# run on pr, run on tag. run on branch that's not master or feature/* + cleanup-after-run: if: | - github.actor != 'dependabot[bot]' && - (github.event_name == 'pull_request' || github.ref_type == 'tag') + github.event_name == 'pull_request' || + github.ref_type == 'tag' || + ( + github.ref_type == 'branch' && + ! ( + github.ref_name == 'master' || + startsWith('feature/', github.ref_name) + ) + ) needs: - test-current-bv2-release - generate-metadata @@ -589,9 +480,4 @@ jobs: with: namespace: ${{ needs.generate-metadata.outputs.namespace }} delete_namespace: true - secrets: - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + secrets: inherit diff --git a/.github/workflows/mobilecoin-dev-delete.yaml b/.github/workflows/mobilecoin-dev-delete.yaml index ece72018cc..e8b8d41d39 100644 --- a/.github/workflows/mobilecoin-dev-delete.yaml +++ b/.github/workflows/mobilecoin-dev-delete.yaml @@ -9,7 +9,7 @@ on: jobs: metadata: - if: startsWith(github.event.ref, 'feature/') || startsWith(github.event.ref, 'release/') + if: startsWith(github.event.ref, 'feature/') runs-on: [self-hosted, Linux, small] outputs: namespace: ${{ steps.meta.outputs.namespace }} @@ -33,19 +33,4 @@ jobs: with: namespace: ${{ needs.metadata.outputs.namespace }} delete_namespace: true - secrets: - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - - why-was-this-skipped: - if: always() && needs.metadata.result == 'skipped' - needs: - - metadata - runs-on: [self-hosted, Linux, small] - steps: - - name: details - run: | - echo "Deleted branch: ${{ github.event.ref }} did not match feature/* or release/*" + secrets: inherit diff --git a/.github/workflows/mobilecoin-dispatch-dev-delete.yaml b/.github/workflows/mobilecoin-dispatch-dev-delete.yaml index 0fcd7a1e2a..2941156bbf 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-delete.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-delete.yaml @@ -4,6 +4,8 @@ name: (Manual) Delete a Dev Namespace +run-name: Reset and Delete ${{ inputs.namespace }} + on: workflow_dispatch: inputs: @@ -24,9 +26,4 @@ jobs: with: namespace: ${{ inputs.namespace }} delete_namespace: ${{ inputs.delete_namespace }} - secrets: - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} + secrets: inherit diff --git a/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml b/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml index a286445ef1..1b62496016 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-deploy.yaml @@ -4,6 +4,8 @@ name: (Manual) Deploy to Dev Namespace +run-name: Deploy ${{ inputs.version }} to ${{ inputs.namespace }} + on: workflow_dispatch: inputs: @@ -15,45 +17,33 @@ on: description: "Chart Version" type: string required: true - chart_repo: - description: "Chart Repo URL" - type: string - required: true - default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public - docker_image_org: - description: "Docker Image Org" - type: string - required: true - default: docker.io/mobilecoin ingest_color: description: "Fog Ingest blue/green" - type: string + type: choice required: true default: blue - minting_config_enabled: - description: "Enable minting config" - type: boolean - required: true - default: false + options: + - blue + - green block_version: description: "Consensus block_version" type: string required: true - client_auth_enabled: - description: "Enable client token auth" - type: boolean + chart_repo: + description: "Chart Repo URL" + type: string required: true - default: false - # true: use GHA secret values, false: generate random seeds - use_static_wallet_seeds: - description: "Use static wallet seeds" - type: boolean + default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + docker_image_org: + description: "Docker Image Org" + type: string required: true - default: false + default: docker.io/mobilecoin + jobs: list-values: - name: 👾 Environment Info - ${{ github.event.inputs.namespace }} - ${{ github.event.inputs.version }} 👾 + name: 👾 Environment Info - ${{ inputs.namespace }} - ${{ inputs.version }} 👾 runs-on: [self-hosted, Linux, small] steps: - name: Checkout @@ -61,40 +51,19 @@ jobs: - name: 👾 Print Environment Details 👾 env: - CHART_REPO: ${{ github.event.inputs.chart_repo }} - NAMESPACE: ${{ github.event.inputs.namespace }} - VERSION: ${{ github.event.inputs.version }} + CHART_REPO: ${{ inputs.chart_repo }} + NAMESPACE: ${{ inputs.namespace }} + VERSION: ${{ inputs.version }} run: | .internal-ci/util/print_details.sh deploy: uses: ./.github/workflows/mobilecoin-workflow-dev-deploy.yaml with: - namespace: ${{ github.event.inputs.namespace }} - version: ${{ github.event.inputs.version }} - docker_image_org: ${{ github.event.inputs.docker_image_org }} - chart_repo: ${{ github.event.inputs.chart_repo }} - ingest_color: ${{ github.event.inputs.ingest_color }} - minting_config_enabled: ${{ github.event.inputs.minting_config_enabled }} - block_version: ${{ github.event.inputs.block_version }} - secrets: - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - IAS_KEY: ${{ secrets.DEV_IAS_KEY }} - IAS_SPID: ${{ secrets.DEV_IAS_SPID }} - FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} - FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} - FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} - MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} - CLIENT_AUTH_TOKEN: ${{ github.event.inputs.client_auth_enabled == 'true' && secrets.DEV_CLIENT_AUTH_TOKEN || '' }} - CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} - INITIAL_KEYS_SEED: ${{ github.event.inputs.use_static_wallet_seeds == 'true' && secrets.DEV_INITIAL_KEYS_SEED || '' }} - FOG_KEYS_SEED: ${{ github.event.inputs.use_static_wallet_seeds == 'true' && secrets.DEV_FOG_KEYS_SEED || '' }} - MNEMONIC_KEYS_SEED: ${{ github.event.inputs.use_static_wallet_seeds == 'true' && secrets.DEV_MNEMONIC_KEYS_SEED || '' }} - MNEMONIC_FOG_KEYS_SEED: ${{ github.event.inputs.use_static_wallet_seeds == 'true' && secrets.DEV_MNEMONIC_FOG_KEYS_SEED || '' }} + block_version: ${{ inputs.block_version }} + chart_repo: ${{ inputs.chart_repo }} + docker_image_org: ${{ inputs.docker_image_org }} + ingest_color: ${{ inputs.ingest_color }} + namespace: ${{ inputs.namespace }} + version: ${{ inputs.version }} + secrets: inherit diff --git a/.github/workflows/mobilecoin-dispatch-dev-test.yaml b/.github/workflows/mobilecoin-dispatch-dev-test.yaml index 8695182dbf..cbd8319f3a 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-test.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-test.yaml @@ -4,6 +4,8 @@ name: (Manual) Run Tests in Dev Namespace +run-name: Test ${{ inputs.namespace }} - ${{ inputs.ingest_color }} + on: workflow_dispatch: inputs: @@ -13,9 +15,12 @@ on: required: true ingest_color: description: "Fog Ingest blue/green" - type: string + type: choice required: true default: blue + options: + - blue + - green fog_distribution: description: "Run fog-distribution test" type: boolean @@ -31,32 +36,14 @@ on: type: boolean required: false default: true - testing_block_v3: - description: "Run block v3 tests" - type: boolean - required: false - default: true - client_auth_enabled: - description: "Is client auth enabled?" - type: boolean - required: false - default: false jobs: test: - name: Test ${{ github.event.inputs.namespace }} - ${{ github.event.inputs.ingest_color }} uses: ./.github/workflows/mobilecoin-workflow-dev-test.yaml with: - namespace: ${{ github.event.inputs.namespace }} - ingest_color: ${{ github.event.inputs.ingest_color }} - fog_distribution: ${{ github.event.inputs.fog_distribution == 'true' && 'true' || 'false' }} - testing_block_v0 : ${{ github.event.inputs.testing_block_v0 == 'true' && 'true' || 'false' }} - testing_block_v2: ${{ github.event.inputs.testing_block_v2 == 'true' && 'true' || 'false' }} - testing_block_v3: ${{ github.event.inputs.testing_block_v3 == 'true' && 'true' || 'false' }} - secrets: - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CA_CERT }} - CACHE_BUSTER: ${{ secrets.CACHE_BUSTER }} - CLIENT_AUTH_USER_VALUE: ${{ github.event.inputs.client_auth_enabled == 'true' && secrets.DEV_CLIENT_AUTH_USER_VALUE || '' }} + namespace: ${{ inputs.namespace }} + ingest_color: ${{ inputs.ingest_color }} + fog_distribution: ${{ inputs.fog_distribution }} + testing_block_v0 : ${{ inputs.testing_block_v0 }} + testing_block_v2: ${{ inputs.testing_block_v2 }} + secrets: inherit diff --git a/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml b/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml index 09f50f84ea..d2b897207d 100644 --- a/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml +++ b/.github/workflows/mobilecoin-dispatch-dev-update-consensus.yaml @@ -4,6 +4,8 @@ name: (Manual) Upgrade Consensus Config in Dev Namespace +run-name: Update Consensus Block Version - ${{ inputs.namespace }} - ${{ inputs.block_version }} + on: workflow_dispatch: inputs: @@ -15,55 +17,23 @@ on: description: "Chart Version" type: string required: true - chart_repo: - description: "Chart Repo URL" - type: string - required: true - default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public - docker_image_org: - description: "Docker Image Org" - type: string - required: true - default: docker.io/mobilecoin - minting_config_enabled: - description: "Enable minting config" - type: boolean - required: true - default: true block_version: description: "Block Version" type: string required: true default: '2' - client_auth_enabled: - description: "additional shared token for client auth" - type: boolean + chart_repo: + description: "Chart Repo URL" + type: string required: true - default: false + default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public jobs: update-consensus-block-version: - name: Update Consensus Block Version - ${{ github.event.inputs.namespace }} - ${{ github.event.inputs.block_version }} uses: ./.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml with: - namespace: ${{ github.event.inputs.namespace }} - version: ${{ github.event.inputs.version }} - docker_image_org: ${{ github.event.inputs.docker_image_org }} - chart_repo: ${{ github.event.inputs.chart_repo }} - minting_config_enabled: ${{ github.event.inputs.minting_config_enabled }} - block_version: "${{ github.event.inputs.block_version }}" - secrets: - RANCHER_CLUSTER: ${{ secrets.RANCHER_CLUSTER }} - RANCHER_URL: ${{ secrets.RANCHER_URL }} - RANCHER_TOKEN: ${{ secrets.RANCHER_TOKEN }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.DEV_LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_LEDGER_AWS_SECRET_ACCESS_KEY }} - IAS_KEY: ${{ secrets.DEV_IAS_KEY }} - IAS_SPID: ${{ secrets.DEV_IAS_SPID }} - FOG_REPORT_SIGNING_CERT: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT }} - FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.DEV_FOG_REPORT_SIGNING_CERT_KEY }} - MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.DEV_MINTING_TRUST_ROOT_PRIVATE }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - IP_INFO_TOKEN: ${{ secrets.DEV_IP_INFO_TOKEN }} - CLIENT_AUTH_TOKEN: ${{ github.event.inputs.client_auth_enabled == 'true' && secrets.DEV_CLIENT_AUTH_TOKEN || '' }} + namespace: ${{ inputs.namespace }} + version: ${{ inputs.version }} + chart_repo: ${{ inputs.chart_repo }} + block_version: "${{ inputs.block_version }}" + secrets: inherit diff --git a/.github/workflows/mobilecoin-workflow-dev-bootstrap.yaml b/.github/workflows/mobilecoin-workflow-dev-bootstrap.yaml new file mode 100644 index 0000000000..d90f0bce60 --- /dev/null +++ b/.github/workflows/mobilecoin-workflow-dev-bootstrap.yaml @@ -0,0 +1,175 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Reusable Workflow - Restore dev env to previous release level. + +name: mobilecoin-workflow-dev-bootstrap + +on: + workflow_call: + inputs: + block_version: + description: "block_version" + type: string + required: true + chart_repo: + description: "Chart Repo URL" + type: string + required: false + default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + namespace: + description: "Target Namespace" + type: string + required: true + version: + description: "Chart Version" + type: string + required: true + secrets: + FOG_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + FOG_REPORT_SIGNING_CA_CERT: + description: "(from environment) Fog Report signing CA cert" + required: true + FOG_REPORT_SIGNING_CERT: + description: "(from environment) Fog Report signing cert pem" + required: true + FOG_REPORT_SIGNING_CERT_KEY: + description: "(from environment) Fog Report signing cert key" + required: true + IAS_KEY: + description: "(from environment) IAS" + required: true + IAS_SPID: + description: "(from environment) IAS" + required: true + INITIAL_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + IP_INFO_TOKEN: + description: "ipinfo.io token for authenticated access" + required: true + LEDGER_AWS_ACCESS_KEY_ID: + description: "(from environment) Ledger AWS S3 access" + required: true + LEDGER_AWS_SECRET_ACCESS_KEY: + description: "(from environment) Ledger AWS S3 access" + required: true + MINTING_1_GOVERNOR_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_1_GOVERNOR_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_1_SIGNER_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_1_SIGNER_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_8192_GOVERNOR_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_8192_GOVERNOR_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_8192_SIGNER_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_8192_SIGNER_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MNEMONIC_FOG_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + MNEMONIC_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + POSTGRESQL_FOG_RECOVERY_PASSWORD: + description: "password for fog_recovery database" + required: true + RANCHER_CLUSTER: + description: "(from environment) Rancher cluster name" + required: true + RANCHER_URL: + description: "(from environment) Rancher server URL" + required: true + RANCHER_TOKEN: + description: "(from environment) Rancher access token" + required: true + +jobs: + reset: + uses: ./.github/workflows/mobilecoin-workflow-dev-reset.yaml + with: + namespace: ${{ inputs.namespace }} + delete_namespace: true + secrets: inherit + + restore-s3-archive: + runs-on: [self-hosted, Linux, small] + needs: + - reset + environment: + name: dev + container: + image: mobilecoin/gha-s3-pg-helper:v0 + steps: + - name: Restore Ledger Archive from S3 + env: + AWS_ACCESS_KEY_ID: ${{ secrets.LEDGER_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LEDGER_AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: eu-central-1 + BUCKET: mobilecoin.eu.development.chain + NAMESPACE: ${{ inputs.namespace }} + VERSION: ${{ inputs.version }} + run: | + for i in 1 2 3 + do + aws s3 cp --only-show-errors --recursive --acl public-read \ + s3://${BUCKET}/prebuilt/${VERSION}/chain/node${i} \ + s3://${BUCKET}/node${i}.${NAMESPACE}.development.mobilecoin.com + done + + setup-environment: + uses: ./.github/workflows/mobilecoin-workflow-dev-setup-environment.yaml + needs: + - reset + with: + namespace: ${{ inputs.namespace }} + block_version: ${{ inputs.block_version }} + chart_repo: ${{ inputs.chart_repo }} + version: ${{ inputs.version }} + secrets: inherit + + # We now have a db with setup-environment + # Note this only works if we are in the same cluster as the dev env. + restore-db-from-archive: + runs-on: [self-hosted, Linux, small] + needs: + - setup-environment + environment: + name: dev + container: + image: mobilecoin/gha-s3-pg-helper:v0 + steps: + - name: restore-db + env: + AWS_ACCESS_KEY_ID: ${{ secrets.LEDGER_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.LEDGER_AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: eu-central-1 + BUCKET: mobilecoin.eu.development.chain + PGDATABASE: postgres + PGHOST: fog-recovery-postgresql-primary.${{ inputs.namespace }} + PGPASSWORD: ${{ secrets.POSTGRESQL_FOG_RECOVERY_PASSWORD }} + PGUSER: postgres + VERSION: ${{ inputs.version }} + run: | + # Copy sql from S3 + aws s3 cp --only-show-errors \ + s3://${BUCKET}/prebuilt/${VERSION}/sql/fog_recovery.sql \ + /tmp/fog_recovery.sql + + # Restore to PG + psql < /tmp/fog_recovery.sql + diff --git a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml index ec11508508..eb08db93aa 100644 --- a/.github/workflows/mobilecoin-workflow-dev-deploy.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-deploy.yaml @@ -29,238 +29,128 @@ on: description: "Fog Ingest blue/green" type: string required: true - minting_config_enabled: - description: "Enable minting config" - type: string - default: 'false' - required: false block_version: description: "block_version" type: string required: true secrets: RANCHER_CLUSTER: - description: "Rancher cluster name" + description: "(from environment) Rancher cluster name" required: true RANCHER_URL: - description: "Rancher server URL" + description: "(from environment) Rancher server URL" required: true RANCHER_TOKEN: - description: "Rancher access token" + description: "(from environment) Rancher access token" required: true LEDGER_AWS_ACCESS_KEY_ID: - description: "Ledger AWS S3 access" + description: "(from environment) Ledger AWS S3 access" required: true LEDGER_AWS_SECRET_ACCESS_KEY: - description: "Ledger AWS S3 access" + description: "(from environment) Ledger AWS S3 access" required: true IAS_KEY: - description: "IAS" + description: "(from environment) IAS" required: true IAS_SPID: - description: "IAS" + description: "(from environment) IAS" required: true FOG_REPORT_SIGNING_CERT: - description: "Fog Report signing cert pem" + description: "(from environment) Fog Report signing cert pem" required: true FOG_REPORT_SIGNING_CERT_KEY: - description: "Fog Report signing cert key" + description: "(from environment) Fog Report signing cert key" required: true FOG_REPORT_SIGNING_CA_CERT: - description: "Fog Report signing CA cert" + description: "(from environment) Fog Report signing CA cert" required: true - MINTING_TRUST_ROOT_PRIVATE: - description: "Root private key for singing the tokens config" - required: false - DOCKERHUB_TOKEN: - description: "Docker hub creds" - required: false - DOCKERHUB_USERNAME: - description: "Docker hub creds" - required: false IP_INFO_TOKEN: description: "ipinfo.io token for authenticated access" required: true - CLIENT_AUTH_TOKEN: - description: "shared token for client auth" - required: false - CACHE_BUSTER: - description: "string to make cache unique" - required: false INITIAL_KEYS_SEED: - description: "static wallet seed" - required: false + description: "(from environment) static wallet seed" + required: true FOG_KEYS_SEED: - description: "static wallet seed" - required: false + description: "(from environment) static wallet seed" + required: true + MINTING_1_GOVERNOR_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_1_GOVERNOR_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_1_SIGNER_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_1_SIGNER_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_8192_GOVERNOR_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_8192_GOVERNOR_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_8192_SIGNER_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_8192_SIGNER_1_PUBLIC: + description: "(from environment) minting governor key" + required: true MNEMONIC_KEYS_SEED: - description: "static wallet seed" - required: false + description: "(from environment) static wallet seed" + required: true MNEMONIC_FOG_KEYS_SEED: - description: "static wallet seed" - required: false + description: "(from environment) static wallet seed" + required: true + env: FLIPSIDE: ${{ inputs.ingest_color == 'blue' && 'green' || 'blue' }} + VALUES_BASE_PATH: .tmp/values jobs: - # Reset consensus nodes between releases - if there's existing data, we'll - # restore from S3. - reset-releases: - runs-on: [self-hosted, Linux, small] - strategy: - matrix: - chart: - - consensus-node-1 - - consensus-node-2 - - consensus-node-3 - - consensus-node-4 - - consensus-node-5 - steps: - - name: Delete release - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: helm-release-delete - namespace: ${{ inputs.namespace }} - release_name: ${{ matrix.chart }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} - setup-environment: - runs-on: [self-hosted, Linux, small] - needs: - - reset-releases - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Create namespace - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: namespace-create - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} - - - name: Cache wallet seeds .tmp/seeds - uses: ./.github/actions/mobilecoin-cache-seeds - with: - cache_buster: ${{ secrets.CACHE_BUSTER }} - - # use static keys if provided. - - name: Generate Wallet Seed - env: - INITIAL_KEYS_SEED: ${{ secrets.INITIAL_KEYS_SEED }} - FOG_KEYS_SEED: ${{ secrets.FOG_KEYS_SEED }} - MNEMONIC_KEYS_SEED: ${{ secrets.MNEMONIC_KEYS_SEED }} - MNEMONIC_FOG_KEYS_SEED: ${{ secrets.MNEMONIC_FOG_KEYS_SEED }} - run: | - .internal-ci/util/generate_wallet_seeds.sh - - # write this to the seeds dir and set the path that toolbox will find it at. - - name: Write fog-report signing CA cert - env: - FOG_REPORT_SIGNING_CA_CERT: ${{ secrets.FOG_REPORT_SIGNING_CA_CERT }} - run: | - mkdir -p .tmp/seeds - echo -n "${FOG_REPORT_SIGNING_CA_CERT}" > .tmp/seeds/FOG_REPORT_SIGNING_CA_CERT - echo -n "/wallet-seeds/FOG_REPORT_SIGNING_CA_CERT" > .tmp/seeds/FOG_REPORT_SIGNING_CA_CERT_PATH - echo -n "fog://fog.${{ inputs.namespace }}.development.mobilecoin.com:443" > .tmp/seeds/FOG_REPORT_URL - - - name: Create wallet key secrets - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: secrets-create-from-file - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} - object_name: sample-keys-seeds - src: .tmp/seeds - - - name: Create minting keys - if: inputs.minting_config_enabled == 'true' - env: - MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.MINTING_TRUST_ROOT_PRIVATE }} - run: | - .internal-ci/util/generate_minting_keys.sh --token-id 8192 - - - name: Login to DockerHub - if: inputs.minting_config_enabled == 'true' - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - # CBB: create a minimal image with just mc-consensus-mint-client binary. - - name: Generate and sign tokens config - if: inputs.minting_config_enabled == 'true' - id: tokens_config - run: | - docker run \ - -v ${{ github.workspace }}:/workspace \ - --network none \ - --workdir /workspace \ - ${{ inputs.docker_image_org }}/bootstrap-tools:${{ inputs.version }} \ - .internal-ci/util/generate_tokens_config.sh - - - name: Create minting key secrets - if: inputs.minting_config_enabled == 'true' - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: secrets-create-from-file - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} - object_name: consensus-minting-secrets - src: .tmp/seeds/minting - - - name: Generate environment values file - env: - IAS_KEY: ${{ secrets.IAS_KEY }} - IAS_SPID: ${{ secrets.IAS_SPID }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.LEDGER_AWS_SECRET_ACCESS_KEY }} - FOG_REPORT_SIGNING_CERT: ${{ secrets.FOG_REPORT_SIGNING_CERT }} - FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.FOG_REPORT_SIGNING_CERT_KEY }} - IP_INFO_TOKEN: ${{ secrets.IP_INFO_TOKEN }} - CLIENT_AUTH_TOKEN: ${{ secrets.CLIENT_AUTH_TOKEN }} - run: | - mkdir -p .tmp/values/ - .internal-ci/util/generate_dev_values.sh > .tmp/values/mc-core-dev-env-values.yaml - - - name: Deploy environment setup - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: helm-deploy - chart_repo: ${{ inputs.chart_repo }} - chart_name: mc-core-dev-env-setup - chart_version: ${{ inputs.version }} - chart_values: .tmp/values/mc-core-dev-env-values.yaml - chart_set: | - --set=global.node.nodeConfig.blockVersion=${{ inputs.block_version }} - release_name: mc-core-dev-env-setup - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} + uses: ./.github/workflows/mobilecoin-workflow-dev-setup-environment.yaml + with: + block_version: ${{ inputs.block_version }} + chart_repo: ${{ inputs.chart_repo }} + namespace: ${{ inputs.namespace }} + version: ${{ inputs.version }} + secrets: inherit consensus-deploy: needs: - setup-environment runs-on: [self-hosted, Linux, small] + environment: + name: dev strategy: matrix: release_name: - consensus-node-1 - consensus-node-2 - consensus-node-3 - - consensus-node-4 - - consensus-node-5 steps: + # use values file because intel.com/sgx is hard to escape on the --set option. + - name: Generate consensus-node values file + run: | + mkdir -p ${VALUES_BASE_PATH} + cat < ${VALUES_BASE_PATH}/consensus-node-values.yaml + image: + org: ${{ inputs.docker_image_org }} + global: + certManagerClusterIssuer: zerossl-prod-http + node: + resources: + limits: + intel.com/sgx: 2000 + requests: + intel.com/sgx: 2000 + persistence: + enabled: false + EOF + - name: Deploy Consensus nodes uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: @@ -268,9 +158,7 @@ jobs: chart_repo: ${{ inputs.chart_repo }} chart_name: consensus-node chart_version: ${{ inputs.version }} - chart_set: | - --set=image.org=${{ inputs.docker_image_org }} - --set=global.certManagerClusterIssuer=zerossl-prod-http + chart_values: ${{ env.VALUES_BASE_PATH }}/consensus-node-values.yaml chart_wait_timeout: 10m release_name: ${{ matrix.release_name }} namespace: ${{ inputs.namespace }} @@ -278,33 +166,12 @@ jobs: rancher_url: ${{ secrets.RANCHER_URL }} rancher_token: ${{ secrets.RANCHER_TOKEN }} - postgresql-deploy: - needs: - - setup-environment - runs-on: [self-hosted, Linux, small] - steps: - - name: Deploy PostgreSQL instance - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: helm-deploy - chart_repo: https://charts.bitnami.com/bitnami - chart_name: postgresql - chart_version: 11.2.3 - chart_set: | - --set=global.postgresql.auth.existingSecret=fog-recovery-postgresql - --set=global.postgresql.auth.database=fog_recovery - --set=architecture=replication - chart_wait_timeout: 5m - release_name: fog-recovery-postgresql - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} - mobilecoind-deploy: needs: - consensus-deploy runs-on: [self-hosted, Linux, small] + environment: + name: dev steps: - name: Deploy Consensus nodes uses: mobilecoinofficial/gha-k8s-toolbox@v1 @@ -324,10 +191,36 @@ jobs: fog-services-deploy: needs: - - postgresql-deploy - consensus-deploy runs-on: [self-hosted, Linux, small] + environment: + name: dev steps: + - name: Generate fog-services values file + run: | + mkdir -p ${VALUES_BASE_PATH} + cat < ${VALUES_BASE_PATH}/fog-services-values.yaml + image: + org: ${{ inputs.docker_image_org }} + global: + certManagerClusterIssuer: zerossl-prod-http + fogLedger: + resources: + limits: + intel.com/sgx: 2000 + requests: + intel.com/sgx: 2000 + persistence: + enabled: false + fogView: + replicaCount: 2 + resources: + limits: + intel.com/sgx: 2000 + requests: + intel.com/sgx: 2000 + EOF + - name: Deploy fog-services uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: @@ -336,11 +229,7 @@ jobs: chart_name: fog-services chart_version: ${{ inputs.version }} chart_wait_timeout: 10m - # Set orderedReady for compatibility with 1.1.3 chart - remove after 1.2.x - chart_set: | - --set=image.org=${{ inputs.docker_image_org }} - --set=global.certManagerClusterIssuer=zerossl-prod-http - --set=fogLedger.podManagementPolicy=OrderedReady + chart_values: ${{ env.VALUES_BASE_PATH }}/fog-services-values.yaml release_name: fog-services namespace: ${{ inputs.namespace }} rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} @@ -349,9 +238,27 @@ jobs: fog-ingest-deploy: needs: - - fog-services-deploy + - consensus-deploy runs-on: [self-hosted, Linux, small] + environment: + name: dev steps: + - name: Generate fog-ingest values file + run: | + mkdir -p ${VALUES_BASE_PATH} + cat < ${VALUES_BASE_PATH}/fog-ingest-values.yaml + image: + org: ${{ inputs.docker_image_org }} + fogIngest: + resources: + limits: + intel.com/sgx: 2000 + requests: + intel.com/sgx: 2000 + persistence: + enabled: false + EOF + - name: Deploy fog-ingest uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: @@ -360,8 +267,7 @@ jobs: chart_name: fog-ingest chart_version: ${{ inputs.version }} chart_wait_timeout: 10m - chart_set: | - --set=image.org=${{ inputs.docker_image_org }} + chart_values: ${{ env.VALUES_BASE_PATH }}/fog-ingest-values.yaml release_name: fog-ingest-${{ inputs.ingest_color }} namespace: ${{ inputs.namespace }} rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} diff --git a/.github/workflows/mobilecoin-workflow-dev-reset.yaml b/.github/workflows/mobilecoin-workflow-dev-reset.yaml index c6f1ce5f88..6fca2bc8e2 100644 --- a/.github/workflows/mobilecoin-workflow-dev-reset.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-reset.yaml @@ -9,16 +9,22 @@ name: mobilecoin-workflow-dev-reset on: workflow_call: inputs: - namespace: - description: "Target Namespace" - type: string - required: true delete_namespace: description: "Delete Target Namespace" type: boolean default: false required: false + namespace: + description: "Target Namespace" + type: string + required: true secrets: + LEDGER_AWS_ACCESS_KEY_ID: + description: "Ledger AWS S3 access" + required: true + LEDGER_AWS_SECRET_ACCESS_KEY: + description: "Ledger AWS S3 access" + required: true RANCHER_CLUSTER: description: "Rancher cluster name" required: true @@ -28,29 +34,25 @@ on: RANCHER_TOKEN: description: "Rancher access token" required: true - LEDGER_AWS_ACCESS_KEY_ID: - description: "Ledger AWS S3 access" - required: true - LEDGER_AWS_SECRET_ACCESS_KEY: - description: "Ledger AWS S3 access" - required: true jobs: - reset-releases: + reset-helm: runs-on: [self-hosted, Linux, small] + environment: + name: dev strategy: matrix: chart: - consensus-node-1 - consensus-node-2 - consensus-node-3 - - consensus-node-4 - - consensus-node-5 - fog-ingest-blue - fog-ingest-green - fog-recovery-postgresql - fog-services - mobilecoind + - mc-core-common-config + - mc-core-dev-env-setup steps: - name: Delete release uses: mobilecoinofficial/gha-k8s-toolbox@v1 @@ -62,10 +64,12 @@ jobs: rancher_url: ${{ secrets.RANCHER_URL }} rancher_token: ${{ secrets.RANCHER_TOKEN }} - reset-storage: - needs: - - reset-releases + reset-k8s: runs-on: [self-hosted, Linux, small] + needs: + - reset-helm + environment: + name: dev steps: - name: Delete PersistentVolumeClaims uses: mobilecoinofficial/gha-k8s-toolbox@v1 @@ -76,12 +80,22 @@ jobs: rancher_url: ${{ secrets.RANCHER_URL }} rancher_token: ${{ secrets.RANCHER_TOKEN }} + - name: Delete namespace + if: inputs.delete_namespace + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: namespace-delete + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + reset-s3: - needs: - - reset-releases + environment: + name: dev runs-on: [self-hosted, Linux, small] container: - image: amazon/aws-cli:latest + image: mobilecoin/gha-s3-pg-helper:v0 steps: - name: Clear out s3 bucket objects env: @@ -91,23 +105,7 @@ jobs: BUCKET: mobilecoin.eu.development.chain NAMESPACE: ${{ inputs.namespace }} run: | - aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node1.${NAMESPACE}.development.mobilecoin.com - aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node2.${NAMESPACE}.development.mobilecoin.com - aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node3.${NAMESPACE}.development.mobilecoin.com - aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node4.${NAMESPACE}.development.mobilecoin.com - aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node5.${NAMESPACE}.development.mobilecoin.com - - delete-namespace: - if: inputs.delete_namespace - needs: - - reset-storage - runs-on: [self-hosted, Linux, small] - steps: - - name: Delete namespace - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: namespace-delete - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} + for i in 1 2 3 + do + aws s3 rm --only-show-errors --recursive s3://${BUCKET}/node${i}.${NAMESPACE}.development.mobilecoin.com + done diff --git a/.github/workflows/mobilecoin-workflow-dev-setup-environment.yaml b/.github/workflows/mobilecoin-workflow-dev-setup-environment.yaml new file mode 100644 index 0000000000..460328f667 --- /dev/null +++ b/.github/workflows/mobilecoin-workflow-dev-setup-environment.yaml @@ -0,0 +1,229 @@ +# Copyright (c) 2018-2022 The MobileCoin Foundation +# +# MobileCoin Core projects - Reusable Workflow - Deploy core apps to to the development namespace. + +name: mobilecoin-workflow-dev-setup-environment + +on: + workflow_call: + inputs: + block_version: + description: "block_version" + type: string + required: true + chart_repo: + description: "Chart Repo URL" + type: string + required: false + default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public + namespace: + description: "Target Namespace" + type: string + required: true + version: + description: "Chart Version" + type: string + required: true + secrets: + FOG_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + FOG_REPORT_SIGNING_CA_CERT: + description: "(from environment) Fog Report signing CA cert" + required: true + FOG_REPORT_SIGNING_CERT: + description: "(from environment) Fog Report signing cert pem" + required: true + FOG_REPORT_SIGNING_CERT_KEY: + description: "(from environment) Fog Report signing cert key" + required: true + IAS_KEY: + description: "(from environment) IAS" + required: true + IAS_SPID: + description: "(from environment) IAS" + required: true + INITIAL_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + IP_INFO_TOKEN: + description: "ipinfo.io token for authenticated access" + required: true + LEDGER_AWS_ACCESS_KEY_ID: + description: "(from environment) Ledger AWS S3 access" + required: true + LEDGER_AWS_SECRET_ACCESS_KEY: + description: "(from environment) Ledger AWS S3 access" + required: true + MINTING_1_GOVERNOR_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_1_GOVERNOR_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_1_SIGNER_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_1_SIGNER_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_8192_GOVERNOR_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_8192_GOVERNOR_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_8192_SIGNER_1_PRIVATE: + description: "(from environment) minting signer key" + required: true + MINTING_8192_SIGNER_1_PUBLIC: + description: "(from environment) minting signer key" + required: true + MNEMONIC_FOG_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + MNEMONIC_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + POSTGRESQL_FOG_RECOVERY_PASSWORD: + description: "password for fog_recovery database" + required: true + RANCHER_CLUSTER: + description: "(from environment) Rancher cluster name" + required: true + RANCHER_URL: + description: "(from environment) Rancher server URL" + required: true + RANCHER_TOKEN: + description: "(from environment) Rancher access token" + required: true + TOKENS_CONFIG_JSON: + description: "(from environment) signed tokens config json" + required: true + +jobs: + setup-environment: + runs-on: [self-hosted, Linux, small] + environment: + name: dev + env: + BASE_PATH: .tmp + MINTING_BASE_PATH: .tmp/minting + SEEDS_BASE_PATH: .tmp/seeds + VALUES_BASE_PATH: .tmp/values + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Create namespace + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: namespace-create + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + - name: Write seeds and fog-report values + run: | + # Create seeds dir. + mkdir -p "${SEEDS_BASE_PATH}" + + # Write values to be used as k8s secret values. + echo -n "${{ secrets.INITIAL_KEYS_SEED }}" > "${SEEDS_BASE_PATH}/INITIAL_KEYS_SEED" + echo -n "${{ secrets.FOG_KEYS_SEED }}" > "${SEEDS_BASE_PATH}/FOG_KEYS_SEED" + echo -n "${{ secrets.MNEMONIC_KEYS_SEED }}" > "${SEEDS_BASE_PATH}/MNEMONIC_KEYS_SEED" + echo -n "${{ secrets.MNEMONIC_FOG_KEYS_SEED }}" > "${SEEDS_BASE_PATH}/MNEMONIC_FOG_KEYS_SEED" + echo -n "${{ secrets.FOG_REPORT_SIGNING_CA_CERT }}" > "${SEEDS_BASE_PATH}/FOG_REPORT_SIGNING_CA_CERT" + echo -n "/wallet-seeds/FOG_REPORT_SIGNING_CA_CERT" > "${SEEDS_BASE_PATH}/FOG_REPORT_SIGNING_CA_CERT_PATH" + echo -n "fog://fog.${{ inputs.namespace }}.development.mobilecoin.com:443" > "${SEEDS_BASE_PATH}/FOG_REPORT_URL" + + - name: Create wallet key secrets + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: secrets-create-from-file + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + object_name: sample-keys-seeds + src: ${{ env.SEEDS_BASE_PATH }} + + - name: Write minting keys + run: | + # Create minting secrets dir + mkdir -p "${MINTING_BASE_PATH}" + + # Write values to be used as k8s secret values. + echo -n "${{ secrets.MINTING_1_GOVERNOR_1_PRIVATE }}" > "${MINTING_BASE_PATH}/token_1_governor_1.private.pem" + echo -n "${{ secrets.MINTING_1_GOVERNOR_1_PUBLIC }}" > "${MINTING_BASE_PATH}/token_1_governor_1.public.pem" + echo -n "${{ secrets.MINTING_1_SIGNER_1_PRIVATE }}" > "${MINTING_BASE_PATH}/token_1_signer_1.private.pem" + echo -n "${{ secrets.MINTING_1_SIGNER_1_PUBLIC }}" > "${MINTING_BASE_PATH}/token_1_signer_1.public.pem" + echo -n "${{ secrets.MINTING_8192_GOVERNOR_1_PRIVATE }}" > "${MINTING_BASE_PATH}/token_8192_governor_1.private.pem" + echo -n "${{ secrets.MINTING_8192_GOVERNOR_1_PUBLIC }}" > "${MINTING_BASE_PATH}/token_8192_governor_1.public.pem" + echo -n "${{ secrets.MINTING_8192_SIGNER_1_PRIVATE }}" > "${MINTING_BASE_PATH}/token_8192_signer_1.private.pem" + echo -n "${{ secrets.MINTING_8192_SIGNER_1_PUBLIC }}" > "${MINTING_BASE_PATH}/token_8192_signer_1.public.pem" + + - name: Create minting key secrets + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: secrets-create-from-file + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + object_name: consensus-minting-secrets + src: ${{ env.MINTING_BASE_PATH }} + + - name: Write tokens.signed.json + run: | + mkdir -p "${BASE_PATH}" + echo '${{ secrets.TOKENS_CONFIG_JSON }}' > "${BASE_PATH}/tokens.signed.json" + + - name: Generate environment values file + env: + IAS_KEY: ${{ secrets.IAS_KEY }} + IAS_SPID: ${{ secrets.IAS_SPID }} + LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.LEDGER_AWS_ACCESS_KEY_ID }} + LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.LEDGER_AWS_SECRET_ACCESS_KEY }} + FOG_REPORT_SIGNING_CERT: ${{ secrets.FOG_REPORT_SIGNING_CERT }} + FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.FOG_REPORT_SIGNING_CERT_KEY }} + IP_INFO_TOKEN: ${{ secrets.IP_INFO_TOKEN }} + run: | + mkdir -p ${VALUES_BASE_PATH} + .internal-ci/util/generate_dev_values.sh > ${VALUES_BASE_PATH}/mc-core-dev-env-values.yaml + + - name: Deploy environment setup + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: ${{ inputs.chart_repo }} + chart_name: mc-core-dev-env-setup + chart_version: ${{ inputs.version }} + chart_values: ${{ env.VALUES_BASE_PATH }}/mc-core-dev-env-values.yaml + chart_set: | + --set=global.node.nodeConfig.blockVersion=${{ inputs.block_version }} + --set=fogIngestConfig.fogRecoveryDatabase.password=${{ secrets.POSTGRESQL_FOG_RECOVERY_PASSWORD }} + release_name: mc-core-dev-env-setup + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} + + - name: Deploy PostgreSQL instance + uses: mobilecoinofficial/gha-k8s-toolbox@v1 + with: + action: helm-deploy + chart_repo: https://charts.bitnami.com/bitnami + chart_name: postgresql + chart_version: 11.2.3 + chart_set: | + --set=global.postgresql.auth.existingSecret=fog-recovery-postgresql + --set=global.postgresql.auth.database=fog_recovery + --set=architecture=replication + chart_wait_timeout: 5m + release_name: fog-recovery-postgresql + namespace: ${{ inputs.namespace }} + rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} + rancher_url: ${{ secrets.RANCHER_URL }} + rancher_token: ${{ secrets.RANCHER_TOKEN }} diff --git a/.github/workflows/mobilecoin-workflow-dev-test.yaml b/.github/workflows/mobilecoin-workflow-dev-test.yaml index dbe25ec82b..1511f96ed5 100644 --- a/.github/workflows/mobilecoin-workflow-dev-test.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-test.yaml @@ -53,19 +53,19 @@ on: required: true fog_distribution: description: "Run fog-distribution test" - type: string + type: boolean required: false - default: 'true' + default: true testing_block_v0: description: "Run block v0 tests" - type: string + type: boolean required: false - default: 'true' + default: true testing_block_v2: description: "Run block v2 tests" - type: string + type: boolean required: false - default: 'true' + default: true secrets: RANCHER_CLUSTER: description: "Rancher cluster name" @@ -76,21 +76,13 @@ on: RANCHER_TOKEN: description: "Rancher access token" required: true - FOG_REPORT_SIGNING_CA_CERT: - description: "Fog Report Signing CA" - required: true - CACHE_BUSTER: - description: "string to make cache unique" - required: true - CLIENT_AUTH_USER_VALUE: - description: "client auth rendered value" - required: false jobs: cd-integration-tests: runs-on: [self-hosted, Linux, small] + environment: + name: dev env: - FOG_REPORT_SIGNING_CA_CERT_PATH: .tmp/fog_report_signing_ca_cert.pem SRC_KEYS_DIR: /tmp/sample_data/keys SRC_FOG_KEYS_DIR: /tmp/sample_data/fog_keys V2_DST_KEYS_DIR: /tmp/2-testing/keys @@ -129,7 +121,7 @@ jobs: /util/generate_origin_data.sh - name: Test - fog-distribution - if: inputs.fog_distribution == 'true' + if: inputs.fog_distribution uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -142,7 +134,7 @@ jobs: /test/fog-distribution-test.sh - name: Test - block-v0 - fog-test-client - if: inputs.testing_block_v0 == 'true' + if: inputs.testing_block_v0 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -161,11 +153,11 @@ jobs: --num-transactions 32 \ --consensus-wait 300 \ --transfer-amount 20 \ - --fog-view fog-view://${{ secrets.CLIENT_AUTH_USER_VALUE }}fog.${{ inputs.namespace }}.development.mobilecoin.com:443 \ - --fog-ledger fog-ledger://${{ secrets.CLIENT_AUTH_USER_VALUE }}fog.${{ inputs.namespace }}.development.mobilecoin.com:443 + --fog-view fog-view://fog.${{ inputs.namespace }}.development.mobilecoin.com:443 \ + --fog-ledger fog-ledger://fog.${{ inputs.namespace }}.development.mobilecoin.com:443 - name: Test - block-v0 - mobilecoind-grpc (previously Wallet Integration) - if: inputs.testing_block_v0 == 'true' + if: inputs.testing_block_v0 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -178,7 +170,7 @@ jobs: /test/mobilecoind-integration-test.sh - name: Setup - block-v2 - Copy subset of non-fog keys - if: inputs.testing_block_v2 == 'true' + if: inputs.testing_block_v2 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -195,7 +187,7 @@ jobs: --end ${{ env.END_KEYS }} - name: Setup - block-v2 - Copy subset of fog keys - if: inputs.testing_block_v2 == 'true' + if: inputs.testing_block_v2 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -212,7 +204,7 @@ jobs: --end ${{ env.END_KEYS }} - name: Test - block-v2 - Minting config tx - if: inputs.testing_block_v2 == 'true' + if: inputs.testing_block_v2 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -226,7 +218,7 @@ jobs: --token-id 8192 - name: Test - block-v2 - Minting tx - if: inputs.testing_block_v2 == 'true' + if: inputs.testing_block_v2 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -241,7 +233,7 @@ jobs: --token-id 8192 - name: Test - block-v2 - mobilecoind-json integration - if: inputs.testing_block_v2 == 'true' + if: inputs.testing_block_v2 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -255,7 +247,7 @@ jobs: --key-dir ${{ env.V2_DST_KEYS_DIR }} - name: Test - block-v2 - use drain_accounts to transfer id 1 balances to fog keys - if: inputs.testing_block_v2 == 'true' + if: inputs.testing_block_v2 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -272,7 +264,7 @@ jobs: --token-id 8192 - name: Test - block-v2 - fog-test-client token id 0 - if: inputs.testing_block_v2 == 'true' + if: inputs.testing_block_v2 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec @@ -287,7 +279,7 @@ jobs: --token-id 0 - name: Test - block-v2 - fog-test-client token id 1 - if: inputs.testing_block_v2 == 'true' + if: inputs.testing_block_v2 uses: mobilecoinofficial/gha-k8s-toolbox@v1 with: action: toolbox-exec diff --git a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml index ea887ba164..c42fcbe478 100644 --- a/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml +++ b/.github/workflows/mobilecoin-workflow-dev-update-consensus.yaml @@ -7,164 +7,119 @@ name: mobilecoin-workflow-dev-update-consensus on: workflow_call: inputs: - namespace: - description: "Target Namespace" - type: string - required: true - version: - description: "release version" + block_version: + description: "block_version" type: string required: true - docker_image_org: - description: "Docker Image Org" - type: string - required: false - default: docker.io/mobilecoin chart_repo: description: "Chart Repo URL" type: string required: false default: https://harbor.mobilecoin.com/chartrepo/mobilecoinfoundation-public - minting_config_enabled: - description: "Enable minting config" + namespace: + description: "Target Namespace" type: string required: true - block_version: - description: "block_version" + version: + description: "release version" type: string required: true - secrets: - RANCHER_CLUSTER: - description: "Rancher cluster name" - required: true - RANCHER_URL: - description: "Rancher server URL" + FOG_KEYS_SEED: + description: "(from environment) static wallet seed" required: true - RANCHER_TOKEN: - description: "Rancher access token" + FOG_REPORT_SIGNING_CA_CERT: + description: "(from environment) Fog Report signing CA cert" required: true - LEDGER_AWS_ACCESS_KEY_ID: - description: "Ledger AWS S3 access" + FOG_REPORT_SIGNING_CERT: + description: "(from environment) Fog Report signing cert pem" required: true - LEDGER_AWS_SECRET_ACCESS_KEY: - description: "Ledger AWS S3 access" + FOG_REPORT_SIGNING_CERT_KEY: + description: "(from environment) Fog Report signing cert key" required: true IAS_KEY: - description: "IAS" + description: "(from environment) IAS" required: true IAS_SPID: - description: "IAS" + description: "(from environment) IAS" required: true - FOG_REPORT_SIGNING_CERT: - description: "Fog Report signing cert pem" + INITIAL_KEYS_SEED: + description: "(from environment) static wallet seed" required: true - FOG_REPORT_SIGNING_CERT_KEY: - description: "Fog Report signing cert key" - required: true - MINTING_TRUST_ROOT_PRIVATE: - description: "Root private key for singing the tokens config" - required: false - DOCKERHUB_TOKEN: - description: "Docker hub creds" - required: false - DOCKERHUB_USERNAME: - description: "Docker hub creds" - required: false IP_INFO_TOKEN: description: "ipinfo.io token for authenticated access" required: true - CLIENT_AUTH_TOKEN: - description: "shared token for client auth" - required: false + LEDGER_AWS_ACCESS_KEY_ID: + description: "(from environment) Ledger AWS S3 access" + required: true + LEDGER_AWS_SECRET_ACCESS_KEY: + description: "(from environment) Ledger AWS S3 access" + required: true + MINTING_1_GOVERNOR_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_1_GOVERNOR_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_1_SIGNER_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_1_SIGNER_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_8192_GOVERNOR_1_PRIVATE: + description: "(from environment) minting governor key" + required: true + MINTING_8192_GOVERNOR_1_PUBLIC: + description: "(from environment) minting governor key" + required: true + MINTING_8192_SIGNER_1_PRIVATE: + description: "(from environment) minting signer key" + required: true + MINTING_8192_SIGNER_1_PUBLIC: + description: "(from environment) minting signer key" + required: true + MNEMONIC_FOG_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + MNEMONIC_KEYS_SEED: + description: "(from environment) static wallet seed" + required: true + POSTGRESQL_FOG_RECOVERY_PASSWORD: + description: "password for fog_recovery database" + required: true + RANCHER_CLUSTER: + description: "(from environment) Rancher cluster name" + required: true + RANCHER_URL: + description: "(from environment) Rancher server URL" + required: true + RANCHER_TOKEN: + description: "(from environment) Rancher access token" + required: true jobs: setup-environment: - runs-on: [self-hosted, Linux, small] - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Create minting keys - if: inputs.minting_config_enabled == 'true' - env: - MINTING_TRUST_ROOT_PRIVATE: ${{ secrets.MINTING_TRUST_ROOT_PRIVATE }} - run: | - .internal-ci/util/generate_minting_keys.sh --token-id 8192 - - - name: Login to DockerHub - if: inputs.minting_config_enabled == 'true' - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - # CBB: create a minimal image with just mc-consensus-mint-client binary. - - name: Generate and sign tokens config - if: inputs.minting_config_enabled == 'true' - id: tokens_config - run: | - docker run \ - -v ${{ github.workspace }}:/workspace \ - --network none \ - --workdir /workspace \ - ${{ inputs.docker_image_org }}/bootstrap-tools:${{ inputs.version }} \ - .internal-ci/util/generate_tokens_config.sh - - - name: Create minting key secrets - if: inputs.minting_config_enabled == 'true' - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: secrets-create-from-file - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} - object_name: consensus-minting-secrets - src: .tmp/seeds/minting - - - name: Generate environment values file - env: - IAS_KEY: ${{ secrets.IAS_KEY }} - IAS_SPID: ${{ secrets.IAS_SPID }} - LEDGER_AWS_ACCESS_KEY_ID: ${{ secrets.LEDGER_AWS_ACCESS_KEY_ID }} - LEDGER_AWS_SECRET_ACCESS_KEY: ${{ secrets.LEDGER_AWS_SECRET_ACCESS_KEY }} - FOG_REPORT_SIGNING_CERT: ${{ secrets.FOG_REPORT_SIGNING_CERT }} - FOG_REPORT_SIGNING_CERT_KEY: ${{ secrets.FOG_REPORT_SIGNING_CERT_KEY }} - IP_INFO_TOKEN: ${{ secrets.IP_INFO_TOKEN }} - CLIENT_AUTH_TOKEN: ${{ secrets.CLIENT_AUTH_TOKEN }} - run: | - mkdir -p .tmp/values/ - .internal-ci/util/generate_dev_values.sh > .tmp/values/mc-core-dev-env-values.yaml - - - name: Deploy environment setup with block_version - uses: mobilecoinofficial/gha-k8s-toolbox@v1 - with: - action: helm-deploy - chart_repo: ${{ inputs.chart_repo }} - chart_name: mc-core-dev-env-setup - chart_version: ${{ inputs.version }} - chart_values: .tmp/values/mc-core-dev-env-values.yaml - chart_set: | - --set=global.node.nodeConfig.blockVersion=${{ inputs.block_version }} - release_name: mc-core-dev-env-setup - namespace: ${{ inputs.namespace }} - rancher_cluster: ${{ secrets.RANCHER_CLUSTER }} - rancher_url: ${{ secrets.RANCHER_URL }} - rancher_token: ${{ secrets.RANCHER_TOKEN }} + uses: ./.github/workflows/mobilecoin-workflow-dev-setup-environment.yaml + with: + namespace: ${{ inputs.namespace }} + block_version: ${{ inputs.block_version }} + chart_repo: ${{ inputs.chart_repo }} + version: ${{ inputs.version }} + secrets: inherit consensus-restart: + runs-on: [self-hosted, Linux, small] needs: - setup-environment - runs-on: [self-hosted, Linux, small] + environment: + name: dev strategy: matrix: object_name: - deployment.app/consensus-node-1 - deployment.app/consensus-node-2 - deployment.app/consensus-node-3 - - deployment.app/consensus-node-4 - - deployment.app/consensus-node-5 steps: - name: Restart Consensus Nodes uses: mobilecoinofficial/gha-k8s-toolbox@v1 diff --git a/.internal-ci/helm/mc-core-dev-env-setup/Chart.yaml b/.internal-ci/helm/mc-core-dev-env-setup/Chart.yaml index b517185c27..ad8a13f951 100644 --- a/.internal-ci/helm/mc-core-dev-env-setup/Chart.yaml +++ b/.internal-ci/helm/mc-core-dev-env-setup/Chart.yaml @@ -26,16 +26,6 @@ dependencies: repository: file://../consensus-node-config version: 0.0.0 condition: consensusNodeConfig3.enabled -- name: consensus-node-config - alias: consensusNodeConfig4 - repository: file://../consensus-node-config - version: 0.0.0 - condition: consensusNodeConfig4.enabled -- name: consensus-node-config - alias: consensusNodeConfig5 - repository: file://../consensus-node-config - version: 0.0.0 - condition: consensusNodeConfig5.enabled - name: fog-ingest-config alias: fogIngestConfig repository: file://../fog-ingest-config diff --git a/.internal-ci/helm/mc-core-dev-env-setup/values.yaml b/.internal-ci/helm/mc-core-dev-env-setup/values.yaml index c36958ac63..6eef41f95d 100644 --- a/.internal-ci/helm/mc-core-dev-env-setup/values.yaml +++ b/.internal-ci/helm/mc-core-dev-env-setup/values.yaml @@ -8,7 +8,7 @@ global: startFrom: last networkConfig: - threshold: '3' + threshold: '2' peers: 1: peer: @@ -28,18 +28,6 @@ global: port: '443' signerPublicKey: '' ledgerArchiveLocation: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node3.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' - 4: - peer: - hostname: '{{ printf "peer4.%s.development.mobilecoin.com" .Release.Namespace }}' - port: '443' - signerPublicKey: '' - ledgerArchiveLocation: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node4.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' - 5: - peer: - hostname: '{{ printf "peer5.%s.development.mobilecoin.com" .Release.Namespace }}' - port: '443' - signerPublicKey: '' - ledgerArchiveLocation: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node5.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' # Add signed tokens.json with --set-file=global.node.tokensConfig."tokens\.signed\.json"=tokens.signed.json tokensConfig: @@ -52,7 +40,7 @@ mcCoreCommonConfig: network: '{{ .Release.Namespace }}' partner: 'dev' mobilecoind: - threshold: '3' + threshold: '2' nodes: - client: '{{ printf "node1.%s.development.mobilecoin.com:443" .Release.Namespace }}' txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node1.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' @@ -60,10 +48,6 @@ mcCoreCommonConfig: txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node2.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' - client: '{{ printf "node3.%s.development.mobilecoin.com:443" .Release.Namespace }}' txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node3.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' - - client: '{{ printf "node4.%s.development.mobilecoin.com:443" .Release.Namespace }}' - txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node4.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' - - client: '{{ printf "node5.%s.development.mobilecoin.com:443" .Release.Namespace }}' - txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node5.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' consensusNodeConfig1: @@ -96,26 +80,6 @@ consensusNodeConfig3: hostname: '{{ printf "peer3.%s.development.mobilecoin.com" .Release.Namespace }}' txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node3.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' -consensusNodeConfig4: - enabled: true - fullnameOverride: 'consensus-node-4' - node: - client: - hostname: '{{ printf "node4.%s.development.mobilecoin.com" .Release.Namespace }}' - peer: - hostname: '{{ printf "peer4.%s.development.mobilecoin.com" .Release.Namespace }}' - txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node4.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' - -consensusNodeConfig5: - enabled: true - fullnameOverride: 'consensus-node-5' - node: - client: - hostname: '{{ printf "node5.%s.development.mobilecoin.com" .Release.Namespace }}' - peer: - hostname: '{{ printf "peer5.%s.development.mobilecoin.com" .Release.Namespace }}' - txSourceUrl: '{{ with .Values.global.node.ledgerDistribution }}{{ printf "https://s3-%s.amazonaws.com/%s/%s/" .awsRegion .s3Bucket (printf "node5.%s.development.mobilecoin.com" $.Release.Namespace) }}{{ end }}' - fogIngestConfig: enabled: true fogRecoveryDatabase: diff --git a/.internal-ci/test/mint-auditor-test.sh b/.internal-ci/test/mint-auditor-test.sh index e12cc5fd58..57dca4b348 100755 --- a/.internal-ci/test/mint-auditor-test.sh +++ b/.internal-ci/test/mint-auditor-test.sh @@ -93,7 +93,7 @@ python3 -m grpc_tools.protoc \ echo "" echo "-- Run integration_test.py" echo "" -token_signer_key="/minting-keys/token${token_id}_signer.private.pem" +token_signer_key="/minting-keys/token_${token_id}_signer_1.private.pem" python3 integration_test.py \ --mobilecoind-addr "mobilecoind:3229" \ diff --git a/.internal-ci/test/minting-config-tx-test.sh b/.internal-ci/test/minting-config-tx-test.sh index a98e9c1d8b..9c858833a1 100755 --- a/.internal-ci/test/minting-config-tx-test.sh +++ b/.internal-ci/test/minting-config-tx-test.sh @@ -46,8 +46,8 @@ is_set token_id is_set NAMESPACE # These should be populated by volume in toolbox container. -governor_signer_key="/minting-keys/minter${token_id}_governor.private.pem" -token_signer_key="/minting-keys/token${token_id}_signer.public.pem" +governor_signer_key="/minting-keys/token_${token_id}_governor_1.private.pem" +token_signer_key="/minting-keys/token_${token_id}_signer_1.public.pem" mc-consensus-mint-client generate-and-submit-mint-config-tx \ --node "mc://node1.${NAMESPACE}.development.mobilecoin.com/" \ diff --git a/.internal-ci/test/minting-tx-test.sh b/.internal-ci/test/minting-tx-test.sh index 2539b89d03..b4dc6943c6 100755 --- a/.internal-ci/test/minting-tx-test.sh +++ b/.internal-ci/test/minting-tx-test.sh @@ -52,7 +52,7 @@ is_set token_id is_set NAMESPACE # These should be populated by volume in toolbox container. -token_signer_key="/minting-keys/token${token_id}_signer.private.pem" +token_signer_key="/minting-keys/token_${token_id}_signer_1.private.pem" keys=$(find "${key_dir}" -name "*.b58pub") diff --git a/.internal-ci/util/generate_dev_values.sh b/.internal-ci/util/generate_dev_values.sh index ba1136c92e..b212b91d45 100755 --- a/.internal-ci/util/generate_dev_values.sh +++ b/.internal-ci/util/generate_dev_values.sh @@ -11,7 +11,7 @@ declare -a signer_keys_pub declare -a signer_keys_pri count=1 -while [ ${count} -le 5 ] +while [ ${count} -le 3 ] do key=$("${location}/generate_ed25519_keys.sh") signer_keys_pub+=("$(echo -n "${key}" | grep public | awk -F': ' '{print $2}')") @@ -41,10 +41,6 @@ global: signerPublicKey: ${signer_keys_pub[1]} 3: signerPublicKey: ${signer_keys_pub[2]} - 4: - signerPublicKey: ${signer_keys_pub[3]} - 5: - signerPublicKey: ${signer_keys_pub[4]} tokensConfig: tokensSignedJson: | @@ -81,16 +77,6 @@ consensusNodeConfig3: msgSignerKey: privateKey: ${signer_keys_pri[2]} -consensusNodeConfig4: - node: - msgSignerKey: - privateKey: ${signer_keys_pri[3]} - -consensusNodeConfig5: - node: - msgSignerKey: - privateKey: ${signer_keys_pri[4]} - fogServicesConfig: fogReport: signingCert: diff --git a/.internal-ci/util/generate_minting_keys.sh b/.internal-ci/util/generate_minting_keys.sh index 18d287d109..434e2a40cf 100755 --- a/.internal-ci/util/generate_minting_keys.sh +++ b/.internal-ci/util/generate_minting_keys.sh @@ -14,6 +14,7 @@ usage() echo "Usage:" echo "${0} --token-id 8192" echo " --token-id - id to generate keys for" + echo " --key-id - default:1 - sig name for key files. use for multi sig" } is_set() @@ -38,6 +39,10 @@ do token_id="${2}" shift 2 ;; + --key-id ) + key_id="${2}" + shift 2 + ;; *) break ;; @@ -46,35 +51,37 @@ done is_set token_id -BASE_PATH="${BASE_PATH:-.tmp/seeds/minting}" +key_id=${key_id:-1} +BASE_PATH="${BASE_PATH:-.tmp/minting}" mkdir -p "${BASE_PATH}" # Token governor keys # This key pair is used to validate MintConfigTxs -if [[ ! -f "${BASE_PATH}/minter${token_id}_governor.private.pem" ]] +if [[ ! -f "${BASE_PATH}/token_${token_id}_governor_${key_id}.private.pem" ]] then + echo "Writing token_${token_id}_governor_${key_id} keys" "${location}/generate_ed25519_keys.sh" \ - --public-out "${BASE_PATH}/minter${token_id}_governor.public.pem" \ - --private-out "${BASE_PATH}/minter${token_id}_governor.private.pem" + --public-out "${BASE_PATH}/token_${token_id}_governor_${key_id}.public.pem" \ + --private-out "${BASE_PATH}/token_${token_id}_governor_${key_id}.private.pem" else - echo "minter${token_id}_governor keys already exist" + echo "minter ${token_id}_governor_${key_id} keys already exist" fi -sha256sum "${BASE_PATH}/minter${token_id}_governor.private.pem" -sha256sum "${BASE_PATH}/minter${token_id}_governor.public.pem" +sha256sum "${BASE_PATH}/token_${token_id}_governor_${key_id}.private.pem" +sha256sum "${BASE_PATH}/token_${token_id}_governor_${key_id}.public.pem" # Token signer keys # This key pair is used to validate MintTX -if [[ ! -f "${BASE_PATH}/token_signer.private.pem" ]] +if [[ ! -f "${BASE_PATH}/token_${token_id}_signer_${key_id}.private.pem" ]] then - echo "Writing token${token_id}_signer keys" + echo "Writing token_${token_id}_signer_${key_id} keys" "${location}/generate_ed25519_keys.sh" \ - --public-out "${BASE_PATH}/token${token_id}_signer.public.pem" \ - --private-out "${BASE_PATH}/token${token_id}_signer.private.pem" + --public-out "${BASE_PATH}/token_${token_id}_signer_${key_id}.public.pem" \ + --private-out "${BASE_PATH}/token_${token_id}_signer_${key_id}.private.pem" else - echo "token${token_id}_signer keys already exist" + echo "token ${token_id}_signer_${key_id} keys already exist" fi -sha256sum "${BASE_PATH}/token${token_id}_signer.private.pem" -sha256sum "${BASE_PATH}/token${token_id}_signer.public.pem" +sha256sum "${BASE_PATH}/token_${token_id}_signer_${key_id}.private.pem" +sha256sum "${BASE_PATH}/token_${token_id}_signer_${key_id}.public.pem" # Write minting trust root private key if its defined. if [[ -n "${MINTING_TRUST_ROOT_PRIVATE}" ]] diff --git a/.internal-ci/util/generate_tokens_config.sh b/.internal-ci/util/generate_tokens_config.sh index 7a28d8c7df..81f7da5eca 100755 --- a/.internal-ci/util/generate_tokens_config.sh +++ b/.internal-ci/util/generate_tokens_config.sh @@ -16,7 +16,7 @@ exists() location=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) BASE_PATH="${BASE_PATH:-.tmp}" -minting_path="${BASE_PATH}/seeds/minting" +MINTING_BASE_PATH="${MINTING_BASE_PATH:-.tmp/minting}" # check for required files exists "${location}/tokens.base.json" @@ -34,28 +34,41 @@ do fi echo "Token ID: ${id} - Checking for governor ed25519 keys" - exists "${minting_path}/minter${id}_governor.public.pem" - sha256sum "${minting_path}/minter8192_governor.public.pem" + threshold=0 + governors="" - echo "Token ID: ${id} - Add governor signer pub keys and threshold to json" - minter_governor=$(cat "${minting_path}/minter${id}_governor.public.pem") + files="${MINTING_BASE_PATH}/token_${id}_governor_*" - json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == ${id}) | .governors.signers) |= \"${minter_governor}\"") + # concat governor keys + for g in $files + do + if [[ "${g}" =~ "public" ]] + then + echo "-- Found governor: ${g}, adding it to the governors list." + sha256sum "${g}" - json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == ${id}) | .governors.threshold) |= 1") + governors="${governors}$(cat "${g}")" + ((threshold+=1)) + fi + done + + + json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == ${id}) | .governors.signers) |= \"${governors}\"") + + json=$(echo "${json}" | jq "(.tokens[] | select(.token_id == ${id}) | .governors.threshold) |= ${threshold}") done #output unsigned tokens echo "$json" | jq . > "${BASE_PATH}/tokens.json" echo "Checking for minting_trust_root ed25519 keys" -exists "${minting_path}/minting_trust_root.private.pem" -sha256sum "${minting_path}/minting_trust_root.private.pem" +exists "${MINTING_BASE_PATH}/minting_trust_root.private.pem" +sha256sum "${MINTING_BASE_PATH}/minting_trust_root.private.pem" # Sign tokens file echo "Signing the tokens file" mc-consensus-mint-client sign-governors --tokens "${BASE_PATH}/tokens.json" \ - --signing-key "${minting_path}/minting_trust_root.private.pem" \ + --signing-key "${MINTING_BASE_PATH}/minting_trust_root.private.pem" \ --output-json "${BASE_PATH}/tokens.signed.json" >/dev/null cat "${BASE_PATH}/tokens.signed.json" diff --git a/.internal-ci/util/tokens.base.json b/.internal-ci/util/tokens.base.json index 9cfc81dd98..a03072bb56 100644 --- a/.internal-ci/util/tokens.base.json +++ b/.internal-ci/util/tokens.base.json @@ -5,6 +5,14 @@ "token_id": 0, "minimum_fee": 400000000 }, + { + "token_id": 1, + "minimum_fee": 1024, + "governors": { + "signers": "", + "threshold": 1 + } + }, { "token_id": 8192, "minimum_fee": 1024,

    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%0D9In;E1VQRghFgJ_eD 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 VgJ*R{_Z?;qwcPPNV5y#v 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Ð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%0D;153 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