Skip to content

Commit

Permalink
Merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
ameba23 committed Dec 5, 2024
2 parents a2c9cd7 + 765a86e commit 5b8db51
Show file tree
Hide file tree
Showing 92 changed files with 961 additions and 956 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ At the moment this project **does not** adhere to
- In [#1128](https://github.com/entropyxyz/entropy-core/pull/1128) mnemonics can no longer be passed
in via a command line argument, file, or environment variable. Instead they are randomly generated
internally.
- In [#1179](https://github.com/entropyxyz/entropy-core/pull/1179) the format of TDX Quote input data has
been changed.
- In [#1147](https://github.com/entropyxyz/entropy-core/pull/1147) a field is added to the
chainspec: `jump_started_signers` which allows the chain to be started in a pre-jumpstarted state
for testing. If this is not desired it should be set to `None`.

### Added
- [#1128](https://github.com/entropyxyz/entropy-core/pull/1128) adds an `/info` route to `entropy-tss`
Expand All @@ -32,6 +37,8 @@ At the moment this project **does not** adhere to
multiple oracle inputs, this means any programs that were compiled and used need to be recompiled to the new
runtime
- Protocol message versioning ([#1140](https://github.com/entropyxyz/entropy-core/pull/1140))
- CLI command to get oracle headings ([#1170](https://github.com/entropyxyz/entropy-core/pull/1170))
- Add TSS endpoint to get TDX quote ([#1173](https://github.com/entropyxyz/entropy-core/pull/1173))

### Changed
- Use correct key rotation endpoint in OCW ([#1104](https://github.com/entropyxyz/entropy-core/pull/1104))
Expand All @@ -40,6 +47,12 @@ runtime
- Add quote guards to `ServerInfo` related extrinsics ([#1123](https://github.com/entropyxyz/entropy-core/pull/1123/))
- Remove declare synced ([#1134](https://github.com/entropyxyz/entropy-core/pull/1134/))
- Update programs to accept multiple oracle data ([#1153](https://github.com/entropyxyz/entropy-core/pull/1153/))
- Use context, not block number in TDX quote input data ([#1179](https://github.com/entropyxyz/entropy-core/pull/1179))
- Allow offchain worker requests to all TSS nodes in entropy-tss test environment ([#1147](https://github.com/entropyxyz/entropy-core/pull/1147))

### Fixed

- Reshare in a spawned task and fix propagation pallet rotate keyshares endpoint lookup key ([#1185](https://github.com/entropyxyz/entropy-core/pull/1185))

## [0.3.0](https://github.com/entropyxyz/entropy-core/compare/release/v0.2.0...release/v0.3.0) - 2024-10-22

Expand Down
30 changes: 16 additions & 14 deletions crates/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,28 @@ serde ={ version="1.0", default-features=false, features=["derive"] }
entropy-shared={ version="0.3.0", path="../shared", default-features=false }
subxt ={ version="0.35.3", default-features=false, features=["jsonrpsee"] }
num ="0.4.3"
thiserror ="2.0.3"
thiserror ="2.0.4"
futures ="0.3"
sp-core ={ version="31.0.0", default-features=false, features=["full_crypto", "serde"] }
tracing ="0.1.37"
tracing ="0.1.41"
rand ={ version="0.8", default-features=false }
anyhow ="1.0.94"

# Present when "full-client" feature is active
blake2 ={ version="0.10.4", optional=true }
rand_core ={ version="0.6.4", optional=true }
serde_json ={ version="1.0", optional=true }
x25519-dalek ={ version="2.0.1", features=["static_secrets"], optional=true }
entropy-protocol={ version="0.3.0", path="../protocol", optional=true, default-features=false }
reqwest ={ version="0.12.9", features=["json", "stream"], optional=true }
base64 ={ version="0.22.0", optional=true }
synedrion ={ version="0.2.0-beta.0", optional=true }
hex ={ version="0.4.3", optional=true }
anyhow ="1.0.93"
blake2 ={ version="0.10.4", optional=true }
rand_core ={ version="0.6.4", optional=true }
serde_json ={ version="1.0", optional=true }
x25519-dalek ={ version="2.0.1", features=["static_secrets"], optional=true }
entropy-protocol ={ version="0.3.0", path="../protocol", optional=true, default-features=false }
reqwest ={ version="0.12.9", features=["json", "stream"], optional=true }
base64 ={ version="0.22.0", optional=true }
synedrion ={ version="0.2.0", optional=true }
hex ={ version="0.4.3", optional=true }
parity-scale-codec={ version="3.6.3", default-features=false, optional=true }

# Only for the browser
js-sys={ version="0.3.72", optional=true }
tokio ={ version="1.41", features=["time"] }
js-sys={ version="0.3.74", optional=true }
tokio ={ version="1.42", features=["time"] }

[dev-dependencies]
serial_test ="3.2.0"
Expand Down Expand Up @@ -64,6 +65,7 @@ full-client=[
"dep:base64",
"dep:synedrion",
"dep:hex",
"dep:parity-scale-codec",
]
full-client-native=["full-client", "entropy-protocol/server"]
full-client-wasm=["full-client", "entropy-protocol/wasm", "dep:js-sys"]
Binary file modified crates/client/entropy_metadata.scale
Binary file not shown.
42 changes: 27 additions & 15 deletions crates/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use crate::{
};
use anyhow::anyhow;
pub use entropy_protocol::{sign_and_encrypt::EncryptedSignedMessage, KeyParams};
use parity_scale_codec::Decode;
use rand::Rng;
use std::str::FromStr;
pub use synedrion::KeyShare;
Expand All @@ -39,7 +40,9 @@ use crate::{
},
client::entropy::staking_extension::events::{EndpointChanged, ThresholdAccountChanged},
substrate::{get_registered_details, submit_transaction_with_pair},
user::{get_all_signers_from_chain, get_validators_not_signer_for_relay, UserSignatureRequest},
user::{
self, get_all_signers_from_chain, get_validators_not_signer_for_relay, UserSignatureRequest,
},
Hasher,
};

Expand Down Expand Up @@ -426,6 +429,9 @@ async fn jumpstart_inner(
/// some point in the near future.
///
/// The returned `nonce` must be used when generating a `quote` for the chain.
///
/// This wraps [user::request_attestation] to convert the error to a [ClientError] consistant with
/// other functions in this module
#[tracing::instrument(
skip_all,
fields(
Expand All @@ -435,19 +441,25 @@ async fn jumpstart_inner(
pub async fn request_attestation(
api: &OnlineClient<EntropyConfig>,
rpc: &LegacyRpcMethods<EntropyConfig>,
attestee: sr25519::Pair,
) -> Result<Vec<u8>, ClientError> {
tracing::debug!("{} is requesting an attestation.", attestee.public());

let request_attestation = entropy::tx().attestation().request_attestation();

let result =
submit_transaction_with_pair(api, rpc, &attestee, &request_attestation, None).await?;
let result_event = result
.find_first::<entropy::attestation::events::AttestationIssued>()?
.ok_or(crate::errors::SubstrateError::NoEvent)?;

let nonce = result_event.0;
attestee: &sr25519::Pair,
) -> Result<[u8; 32], ClientError> {
Ok(user::request_attestation(api, rpc, attestee).await?)
}

Ok(nonce)
/// Get oracle data headings
/// This is useful for program developers to know what oracle data is available
pub async fn get_oracle_headings(
api: &OnlineClient<EntropyConfig>,
_rpc: &LegacyRpcMethods<EntropyConfig>,
) -> Result<Vec<String>, ClientError> {
let storage_address = entropy::storage().oracle().oracle_data_iter();
let mut iter = api.storage().at_latest().await?.iter(storage_address).await?;
let mut headings = Vec::new();
while let Some(Ok(kv)) = iter.next().await {
// Key is: storage_address || 128 bit hash || key
let mut input = &kv.key_bytes[32 + 16 + 1..];
let heading = String::decode(&mut input)?;
headings.push(heading);
}
Ok(headings)
}
15 changes: 15 additions & 0 deletions crates/client/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ pub enum SubgroupGetError {
JoinError(#[from] tokio::task::JoinError),
}

/// An error when making an attestation request
#[derive(Debug, Error)]
pub enum AttestationRequestError {
#[error("Generic Substrate error: {0}")]
GenericSubstrate(#[from] subxt::error::Error),
#[error("Substrate client: {0}")]
SubstrateClient(#[from] crate::substrate::SubstrateError),
#[error("Recieved nonce is not 32 bytes")]
BadNonce,
}

#[cfg(feature = "full-client")]
#[derive(Debug, Error)]
pub enum ClientError {
Expand Down Expand Up @@ -108,4 +119,8 @@ pub enum ClientError {
BadVerifyingKeyLength,
#[error("There are no validators which can act as a relay node for signature requests")]
NoNonSigningValidators,
#[error("Scale decode: {0}")]
Codec(#[from] parity_scale_codec::Error),
#[error("Attestation request: {0}")]
AttestationRequest(#[from] AttestationRequestError),
}
59 changes: 32 additions & 27 deletions crates/client/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ use crate::{
},
staking_extension::events,
},
get_api, get_rpc, EntropyConfig,
get_api, get_rpc,
},
change_endpoint, change_threshold_accounts, register, remove_program, request_attestation,
store_program,
change_endpoint, change_threshold_accounts, get_oracle_headings, register, remove_program,
request_attestation, store_program,
substrate::query_chain,
update_programs,
};

use entropy_shared::{QuoteContext, QuoteInputData};
use entropy_testing_utils::{
constants::{TEST_PROGRAM_WASM_BYTECODE, TSS_ACCOUNTS, X25519_PUBLIC_KEYS},
helpers::encode_verifying_key,
jump_start_network, spawn_testing_validators,
helpers::{encode_verifying_key, spawn_tss_nodes_and_start_chain},
substrate_context::test_context_stationary,
test_node_process_testing_state, ChainSpecType,
};
Expand All @@ -31,7 +31,7 @@ use rand::{
use serial_test::serial;
use sp_core::{sr25519, Pair, H256};
use sp_keyring::AccountKeyring;
use subxt::{tx::PairSigner, utils::AccountId32};
use subxt::utils::AccountId32;

#[tokio::test]
#[serial]
Expand All @@ -54,11 +54,8 @@ async fn test_change_endpoint() {
let signing_key = tdx_quote::SigningKey::random(&mut OsRng);
let public_key = sr25519::Public(tss_account_id.0);

// We need to add `1` here since the quote is being checked in the next block
let block_number = rpc.chain_get_header(None).await.unwrap().unwrap().number + 1;

let input_data =
entropy_shared::QuoteInputData::new(public_key, x25519_public_key, nonce, block_number);
QuoteInputData::new(public_key, x25519_public_key, nonce, QuoteContext::ChangeEndpoint);

let mut pck_seeder = StdRng::from_seed(public_key.0);
let pck = tdx_quote::SigningKey::random(&mut pck_seeder);
Expand Down Expand Up @@ -116,7 +113,7 @@ async fn test_change_threshold_accounts() {
.unwrap();

// When we request an attestation we get a nonce back that we must use when generating our quote.
let nonce = request_attestation(&api, &rpc, tss_signer_pair.signer().clone()).await.unwrap();
let nonce = request_attestation(&api, &rpc, tss_signer_pair.signer()).await.unwrap();
let nonce: [u8; 32] = nonce.try_into().unwrap();

let mut pck_seeder = StdRng::from_seed(tss_public_key.0.clone());
Expand All @@ -129,14 +126,11 @@ async fn test_change_threshold_accounts() {
let pck_certificate_chain = vec![tss_public_key.0.to_vec()];

let quote = {
// We need to add `1` here since the quote is being checked in the next block
let block_number = rpc.chain_get_header(None).await.unwrap().unwrap().number + 1;

let input_data = entropy_shared::QuoteInputData::new(
tss_public_key,
*x25519_public_key.as_bytes(),
nonce,
block_number,
QuoteContext::ChangeThresholdAccounts,
);

let signing_key = tdx_quote::SigningKey::random(&mut OsRng);
Expand Down Expand Up @@ -216,18 +210,8 @@ async fn test_store_and_remove_program() {
async fn test_remove_program_reference_counter() {
let program_owner = AccountKeyring::Ferdie.pair();

let (_validator_ips, _validator_ids) =
spawn_testing_validators(ChainSpecType::Integration).await;

let force_authoring = true;
let substrate_context = &test_node_process_testing_state(force_authoring).await[0];
let api = get_api(&substrate_context.ws_url).await.unwrap();
let rpc = get_rpc(&substrate_context.ws_url).await.unwrap();

// Jumpstart the network
let alice = AccountKeyring::Alice;
let signer = PairSigner::<EntropyConfig, sr25519::Pair>::new(alice.clone().into());
jump_start_network(&api, &rpc, &signer).await;
let (_ctx, api, rpc, _validator_ips, _validator_ids) =
spawn_tss_nodes_and_start_chain(ChainSpecType::IntegrationJumpStarted).await;

// Store a program
let program_pointer = store_program(
Expand Down Expand Up @@ -274,3 +258,24 @@ async fn test_remove_program_reference_counter() {
// We can now remove the program because no-one is using it
remove_program(&api, &rpc, &program_owner, program_pointer).await.unwrap();
}

#[tokio::test]
#[serial]
async fn test_get_oracle_headings() {
let force_authoring = true;
let context =
test_node_process_testing_state(ChainSpecType::IntegrationJumpStarted, force_authoring)
.await;
let api = get_api(&context[0].ws_url).await.unwrap();
let rpc = get_rpc(&context[0].ws_url).await.unwrap();

let mut current_block = 0;
while current_block < 2 {
let finalized_head = rpc.chain_get_finalized_head().await.unwrap();
current_block = rpc.chain_get_header(Some(finalized_head)).await.unwrap().unwrap().number;
}

let headings = get_oracle_headings(&api, &rpc).await.unwrap();

assert_eq!(headings, vec!["block_number_entropy".to_string()]);
}
35 changes: 33 additions & 2 deletions crates/client/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
//! User interaction related
use crate::{
chain_api::{entropy, EntropyConfig},
substrate::query_chain,
substrate::{query_chain, submit_transaction_with_pair},
};
use entropy_shared::{user::ValidatorInfo, BlockNumber, HashingAlgorithm};
use serde::{Deserialize, Serialize};
use sp_core::{sr25519, Pair};
use subxt::{backend::legacy::LegacyRpcMethods, OnlineClient};

pub use crate::errors::SubgroupGetError;
pub use crate::errors::{AttestationRequestError, SubgroupGetError};

/// Represents an unparsed, transaction request coming from the client.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
Expand Down Expand Up @@ -143,3 +144,33 @@ pub async fn get_all_signers_from_chain(

Ok(all_signers)
}

/// An extrinsic to indicate to the chain that it should expect an attestation from the `signer` at
/// some point in the near future.
///
/// The returned `nonce` must be used when generating a `quote` for the chain.
#[tracing::instrument(
skip_all,
fields(
attestee = ?attestee.public(),
)
)]
pub async fn request_attestation(
api: &OnlineClient<EntropyConfig>,
rpc: &LegacyRpcMethods<EntropyConfig>,
attestee: &sr25519::Pair,
) -> Result<[u8; 32], AttestationRequestError> {
tracing::debug!("{:?} is requesting an attestation.", attestee.public());

let request_attestation = entropy::tx().attestation().request_attestation();

let result =
submit_transaction_with_pair(api, rpc, attestee, &request_attestation, None).await?;
let result_event = result
.find_first::<entropy::attestation::events::AttestationIssued>()?
.ok_or(crate::errors::SubstrateError::NoEvent)?;

let nonce = result_event.0.try_into().map_err(|_| AttestationRequestError::BadNonce)?;

Ok(nonce)
}
6 changes: 3 additions & 3 deletions crates/kvdb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ edition ='2021'
# Common
rand ={ version="0.8", default-features=false }
serde ={ version="1.0", features=["derive"] }
thiserror="2.0.3"
thiserror="2.0.4"
hex ="0.4.3"

# Substrate
Expand All @@ -23,10 +23,10 @@ zeroize ={ version="1.8", features=["zeroize_derive"], default-features=
rpassword ={ version="7.3.1", default-features=false }
scrypt ={ version="0.11.0", default-features=false, features=["std"] }
chacha20poly1305={ version="0.9", features=["alloc"], default-features=false }
synedrion ={ version="0.2.0-beta.0" }
synedrion ="0.2.0"

# Async
tokio ={ version="1.41", features=["macros", "sync", "fs", "rt-multi-thread", "io-util"] }
tokio ={ version="1.42", features=["macros", "sync", "fs", "rt-multi-thread", "io-util"] }
tracing={ version="0.1", default-features=false }

# Misc
Expand Down
Loading

0 comments on commit 5b8db51

Please sign in to comment.