Skip to content

Commit

Permalink
Support signatures produced by Polkadot JS signRaw (#30)
Browse files Browse the repository at this point in the history
`signRaw` silently wraps the raw bytes with `<Bytes>` and `</Bytes>`
before signing it. The `verify()` functions for `SignedVoteRequest` and
`SignedRemoveVoteRequest` will try to verify with and without this
wrapping to support both cases.

The REST API has also been updated to be support hex strings beginning
with `0x`.
  • Loading branch information
shamsasari authored Jul 31, 2024
1 parent 35d4001 commit 30fdfc5
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 61 deletions.
17 changes: 7 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ resolver = "2"
[workspace.package]
homepage = "https://projectglove.io/"
repository = "https://github.com/projectglove/glove-monorepo/"
version = "0.0.7"
version = "0.0.8"

[workspace.dependencies]
anyhow = "1.0.86"
Expand Down Expand Up @@ -50,7 +50,6 @@ cfg-if = "1.0.0"
aws-nitro-enclaves-nsm-api = "0.4.0"
aws-nitro-enclaves-cose = "0.5.2"
openssl = "0.10.66"
hex = "0.4.3"
sha2 = "0.10.8"
flate2 = "1.0.30"
aws-config = "1.5.4"
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Enclave Image successfully created.
{
"Measurements": {
"HashAlgorithm": "Sha384 { ... }",
"PCR0": "2c655d5ba7f35e9e5208aff0670b9bee257cd9994cb957100fd8c9b4aa693a1d1c67f430d28c4f62a5372fe96d417d29",
"PCR0": "8ea5994148980786599301b4c583bf14d11fef3188e1496db2c7d3367a7abce2d96cee153434873ac7e26b21e1478270",
...
}
}
Expand All @@ -45,7 +45,7 @@ instructions on how to audit and verify the enclave code.

> [!NOTE]
> The enclave measurement for the latest build is
> `2c655d5ba7f35e9e5208aff0670b9bee257cd9994cb957100fd8c9b4aa693a1d1c67f430d28c4f62a5372fe96d417d29`.
> `8ea5994148980786599301b4c583bf14d11fef3188e1496db2c7d3367a7abce2d96cee153434873ac7e26b21e1478270`.
# Glove mixing

Expand Down Expand Up @@ -148,8 +148,8 @@ unique identifier.

#### `attestation_bundle`

The attestation bundle of the enclave the service is using. This is a hex-encoded string (without the `0x` prefix),
representing the [`AttestationBundle`](common/src/attestation.rs#L45) struct in
The attestation bundle of the enclave the service is using. This is a hex string representing the
[`AttestationBundle`](common/src/attestation.rs#L38) struct in
[SCALE](https://docs.substrate.io/reference/scale-codec/) encoding.

The attestation bundle is primarily used in Glove proofs when the enclave submits its mixed votes on-chain. It's
Expand All @@ -165,8 +165,8 @@ The version of the Glove service.
{
"proxy_account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"network_name": "rococo",
"attestation_bundle": "6408de7737c59c238890533af25896a2c20608d8b380bb01029acb3927...",
"version": "0.0.7"
"attestation_bundle": "0x6408de7737c59c238890533af25896a2c20608d8b380bb01029acb3927...",
"version": "0.0.8"
}
```

Expand All @@ -183,15 +183,15 @@ A JSON object with the following fields:

#### `request`

[SCALE-encoded](https://docs.substrate.io/reference/scale-codec/) [`VoteRequest`](common/src/lib.rs#L36) struct as a
hex string (without the `0x` prefix).
[SCALE-encoded](https://docs.substrate.io/reference/scale-codec/) [`VoteRequest`](common/src/lib.rs#L57) as a
hex string.

#### `signature`

[SCALE-encoded](https://docs.substrate.io/reference/scale-codec/)
[`MultiSignature`](https://docs.rs/sp-runtime/latest/sp_runtime/enum.MultiSignature.html) as a hex string (without the
`0x` prefix). Signed by`VoteRequest.account`, the signature is of the `VoteRequest` in SCALE-encoded bytes, i.e. the
`request` field without the hex-encoding.
[`MultiSignature`](https://docs.rs/sp-runtime/latest/sp_runtime/enum.MultiSignature.html) as a hex string. The
signature is of the `VoteRequest` in SCALE-encoded bytes, i.e. the `request` field without the hex-encoding, signed by
`VoteRequest.account`.

#### Example

Expand Down Expand Up @@ -219,15 +219,15 @@ A JSON object with the following fields:

#### `request`

[SCALE-encoded](https://docs.substrate.io/reference/scale-codec/) [`RemoveVoteRequest`](client-interface/src/lib.rs#L374)
struct as a hex string (without the `0x` prefix).
[SCALE-encoded](https://docs.substrate.io/reference/scale-codec/) [`RemoveVoteRequest`](client-interface/src/lib.rs#L416)
as a hex string.

#### `signature`

[SCALE-encoded](https://docs.substrate.io/reference/scale-codec/)
[`MultiSignature`](https://docs.rs/sp-runtime/latest/sp_runtime/enum.MultiSignature.html) as a hex string (without the
`0x` prefix). Signed by`RemoveVoteRequest.account`, the signature is of the `RemoveVoteRequest` in SCALE-encoded bytes,
i.e. the `request` field without the hex-encoding.
[`MultiSignature`](https://docs.rs/sp-runtime/latest/sp_runtime/enum.MultiSignature.html) as a hex string. The
signature is of the `RemoveVoteRequest` in SCALE-encoded bytes, i.e. the `request` field without the hex-encoding,
signed by `RemoveVoteRequest.account`,

### Response

Expand Down
1 change: 0 additions & 1 deletion client-interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,4 @@ tracing.workspace = true

[dev-dependencies]
serde_json.workspace = true
hex.workspace = true
rand.workspace = true
8 changes: 4 additions & 4 deletions client-interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use serde::{Deserialize, Serialize};
use sp_core::crypto::AccountId32;
use sp_runtime::{MultiAddress, MultiSignature};
use sp_runtime::traits::Verify;
use ss58_registry::{Ss58AddressFormat, Ss58AddressFormatRegistry, Token};
use subxt::Error as SubxtError;
use subxt::ext::scale_decode::DecodeAsType;
Expand All @@ -23,8 +22,8 @@ use subxt_signer::SecretUri;
use subxt_signer::sr25519;
use tokio::sync::Mutex;

use common::{ExtrinsicLocation, verify_js_payload};
use common::attestation::AttestationBundle;
use common::ExtrinsicLocation;
use metadata::proxy::events::ProxyExecuted;
use metadata::referenda::storage::types::referendum_info_for::ReferendumInfoFor;
use metadata::runtime_types::frame_support::traits::preimages::Bounded;
Expand Down Expand Up @@ -410,7 +409,7 @@ pub struct SignedRemoveVoteRequest {

impl SignedRemoveVoteRequest {
pub fn verify(&self) -> bool {
self.signature.verify(&*self.request.encode(), &self.request.account)
verify_js_payload(&self.signature, &self.request, &self.request.account)
}
}

Expand All @@ -430,6 +429,7 @@ mod tests {
use rand::random;
use serde_json::{json, Value};
use sp_core::{ed25519, Pair};
use subxt_core::utils::to_hex;
use subxt_signer::sr25519::dev;

use common::attestation::{Attestation, AttestedData};
Expand Down Expand Up @@ -460,7 +460,7 @@ mod tests {
json!({
"proxy_account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"network_name": "polkadot",
"attestation_bundle": hex::encode(&service_info.attestation_bundle.encode()),
"attestation_bundle": to_hex(&service_info.attestation_bundle.encode()),
"version": "1.0.0"
})
);
Expand Down
1 change: 0 additions & 1 deletion client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,4 @@ strum.workspace = true
sp-core.workspace = true
sp-runtime.workspace = true
thiserror.workspace = true
hex.workspace = true
ss58-registry.workspace = true
14 changes: 8 additions & 6 deletions client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ use reqwest::{Client, StatusCode, Url};
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_retry::{Jitter, RetryTransientMiddleware};
use reqwest_retry::policies::ExponentialBackoff;
use sp_core::bytes::from_hex;
use sp_core::crypto::AccountId32;
use sp_core::Encode;
use sp_runtime::MultiSignature;
use strum::Display;
use subxt::error::DispatchError;
use subxt::Error::Runtime;
use subxt_core::utils::to_hex;
use subxt_signer::sr25519::Keypair;

use client_interface::{account_to_subxt_multi_address, CallableSubstrateNetwork, is_glove_member, SignedRemoveVoteRequest, SubstrateNetwork};
Expand Down Expand Up @@ -245,18 +247,18 @@ async fn verify_vote(service_info: ServiceInfo, cmd: VerifyVoteCmd) -> Result<Su
if !cmd.enclave_measurement.is_empty() {
let enclave_match = cmd.enclave_measurement
.iter()
.any(|str| hex::decode(str).ok() == Some(image_measurement.clone()));
.any(|str| from_hex(str).ok() == Some(image_measurement.clone()));
if !enclave_match {
bail!("Unknown enclave encountered in Glove proof ({})",
hex::encode(&image_measurement))
to_hex(&image_measurement))
}
println!("Vote mixed by VERIFIED Glove enclave: {:?} with {} and conviction {:?}",
verified_glove_proof.result.direction,
network.token.amount(assigned_balance.balance),
assigned_balance.conviction);
} else {
println!("Vote mixed by POSSIBLE Glove enclave ({}): {:?} with {} and conviction {:?}",
hex::encode(&image_measurement),
to_hex(&image_measurement),
verified_glove_proof.result.direction,
network.token.amount(assigned_balance.balance),
assigned_balance.conviction);
Expand All @@ -266,7 +268,7 @@ async fn verify_vote(service_info: ServiceInfo, cmd: VerifyVoteCmd) -> Result<Su
verified_glove_proof.attested_data.version,
env!("CARGO_PKG_REPOSITORY"));
println!();
println!("And then verify 'PCR0' output is '{}':", hex::encode(&image_measurement));
println!("And then verify 'PCR0' output is '{}':", to_hex(&image_measurement));
println!("./build.sh");
}

Expand Down Expand Up @@ -300,7 +302,7 @@ fn info(service_info: ServiceInfo) -> Result<SuccessOutput> {
let ab = &service_info.attestation_bundle;
let enclave_info = match ab.verify() {
Ok(EnclaveInfo::Nitro(enclave_info)) => {
&format!("AWS Nitro Enclave ({})", hex::encode(enclave_info.image_measurement))
&format!("AWS Nitro Enclave ({})", to_hex(enclave_info.image_measurement))
},
Err(attestation::Error::InsecureMode) => match ab.attestation {
Attestation::Nitro(_) => "Debug AWS Nitro Enclave (INSECURE)",
Expand All @@ -312,7 +314,7 @@ fn info(service_info: ServiceInfo) -> Result<SuccessOutput> {
println!("Glove proxy account: {}", service_info.proxy_account);
println!("Enclave: {}", enclave_info);
println!("Substrate Network: {}", service_info.network_name);
println!("Genesis hash: {}", hex::encode(ab.attested_data.genesis_hash));
println!("Genesis hash: {}", to_hex(ab.attested_data.genesis_hash));

Ok(SuccessOutput::None)
}
Expand Down
1 change: 0 additions & 1 deletion common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ sha2.workspace = true
thiserror.workspace = true
flate2.workspace = true
subxt.workspace = true
hex.workspace = true

[dev-dependencies]
serde_json.workspace = true
Expand Down
Loading

0 comments on commit 30fdfc5

Please sign in to comment.