Skip to content

Commit

Permalink
crypto: Add endpoint to get auth signers for a tx digest (MystenLabs#…
Browse files Browse the repository at this point in the history
  • Loading branch information
joyqvq authored Nov 30, 2022
1 parent 6602188 commit b212a76
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 50 deletions.
29 changes: 23 additions & 6 deletions crates/sui-gateway/src/unit_tests/rpc_server_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use sui_config::SUI_KEYSTORE_FILENAME;
use sui_core::test_utils::to_sender_signed_transaction;
use sui_framework_build::compiled_package::BuildConfig;
use sui_json::SuiJsonValue;
use sui_json_rpc::api::TransactionExecutionApiClient;
use sui_json_rpc::api::{RpcFullNodeReadApiClient, TransactionExecutionApiClient};
use sui_json_rpc::api::{RpcReadApiClient, RpcTransactionBuilderClient};
use sui_json_rpc_types::{
GetObjectDataResponse, SuiExecuteTransactionResponse, SuiTransactionResponse, TransactionBytes,
Expand Down Expand Up @@ -203,6 +203,7 @@ async fn test_get_transaction() -> Result<(), anyhow::Error> {
let port = get_available_port();
let cluster = TestClusterBuilder::new()
.set_fullnode_rpc_port(port)
.with_num_validators(6)
.build()
.await?;
let http_client = cluster.rpc_client().unwrap();
Expand Down Expand Up @@ -244,14 +245,30 @@ async fn test_get_transaction() -> Result<(), anyhow::Error> {
let tx: Vec<TransactionDigest> = http_client.get_transactions_in_range(1, 3).await?;
assert_eq!(2, tx.len());

// test get_transaction
for tx_digest in tx {
let response: SuiTransactionResponse = http_client.get_transaction(tx_digest).await?;
// test get_transaction
let tx_response: SuiTransactionResponse = http_client.get_transaction(tx_digest).await?;
assert!(tx_responses.iter().any(
|resp| matches!(resp, SuiExecuteTransactionResponse::EffectsCert {effects, ..} if effects.effects.transaction_digest == response.effects.transaction_digest)
))
}
|resp| matches!(resp, SuiExecuteTransactionResponse::EffectsCert {effects, ..} if effects.effects.transaction_digest == tx_response.effects.transaction_digest)
));
let response = http_client.get_transaction_auth_signers(tx_digest).await?;

// test get_transaction_auth_signers
// There are 2f+1 signers out of 6 validators.
assert_eq!(response.signers.len(), 5);

// All authorities for the tx's epoch are included as signers for the tx.
let committee = http_client
.get_committee_info(Some(tx_response.certificate.auth_sign_info.epoch))
.await?;
let authorities = committee
.committee_info
.unwrap()
.iter()
.map(|c| c.0)
.collect::<Vec<_>>();
assert!(response.signers.iter().all(|s| authorities.contains(s)));
}
Ok(())
}

Expand Down
9 changes: 7 additions & 2 deletions crates/sui-json-rpc-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ use tracing::warn;
use fastcrypto::encoding::{Base64, Encoding};
use sui_json::SuiJsonValue;
use sui_types::base_types::{
ObjectDigest, ObjectID, ObjectInfo, ObjectRef, SequenceNumber, SuiAddress, TransactionDigest,
TransactionEffectsDigest,
AuthorityName, ObjectDigest, ObjectID, ObjectInfo, ObjectRef, SequenceNumber, SuiAddress,
TransactionDigest, TransactionEffectsDigest,
};
use sui_types::committee::EpochId;
use sui_types::crypto::{AuthorityStrongQuorumSignInfo, SignableBytes, Signature};
Expand Down Expand Up @@ -324,6 +324,11 @@ pub struct SuiTransactionResponse {
pub parsed_data: Option<SuiParsedTransactionResponse>,
}

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
pub struct SuiTransactionAuthSignersResponse {
pub signers: Vec<AuthorityName>,
}

#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)]
pub enum SuiParsedTransactionResponse {
Publish(SuiParsedPublishResponse),
Expand Down
13 changes: 11 additions & 2 deletions crates/sui-json-rpc/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use sui_json_rpc_types::{
EventPage, GetObjectDataResponse, GetPastObjectDataResponse, GetRawObjectDataResponse,
MoveFunctionArgType, RPCTransactionRequestParams, SuiCoinMetadata, SuiEventEnvelope,
SuiEventFilter, SuiExecuteTransactionResponse, SuiGasCostSummary, SuiMoveNormalizedFunction,
SuiMoveNormalizedModule, SuiMoveNormalizedStruct, SuiObjectInfo, SuiTransactionEffects,
SuiTransactionFilter, SuiTransactionResponse, SuiTypeTag, TransactionBytes, TransactionsPage,
SuiMoveNormalizedModule, SuiMoveNormalizedStruct, SuiObjectInfo,
SuiTransactionAuthSignersResponse, SuiTransactionEffects, SuiTransactionFilter,
SuiTransactionResponse, SuiTypeTag, TransactionBytes, TransactionsPage,
};
use sui_open_rpc_macros::open_rpc;
use sui_types::base_types::{ObjectID, SequenceNumber, SuiAddress, TransactionDigest};
Expand Down Expand Up @@ -103,6 +104,14 @@ pub trait RpcReadApi {
digest: TransactionDigest,
) -> RpcResult<SuiTransactionResponse>;

/// Return the authority public keys that commits to the authority signature of the transaction.
#[method(name = "getTransactionAuthSigners")]
async fn get_transaction_auth_signers(
&self,
/// the digest of the queried transaction
digest: TransactionDigest,
) -> RpcResult<SuiTransactionAuthSignersResponse>;

/// Return the object information for a specified object
#[method(name = "getObject")]
async fn get_object(
Expand Down
11 changes: 9 additions & 2 deletions crates/sui-json-rpc/src/gateway_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use signature::Signature;
use sui_core::gateway_state::GatewayClient;
use sui_json::SuiJsonValue;
use sui_json_rpc_types::{
GetObjectDataResponse, RPCTransactionRequestParams, SuiObjectInfo, SuiTransactionResponse,
SuiTypeTag, TransactionBytes,
GetObjectDataResponse, RPCTransactionRequestParams, SuiObjectInfo,
SuiTransactionAuthSignersResponse, SuiTransactionResponse, SuiTypeTag, TransactionBytes,
};
use sui_open_rpc::Module;
use sui_types::batch::TxSequenceNumber;
Expand Down Expand Up @@ -166,6 +166,13 @@ impl RpcReadApiServer for GatewayReadApiImpl {
) -> RpcResult<Vec<TransactionDigest>> {
Ok(self.client.get_transactions_in_range(start, end)?)
}

async fn get_transaction_auth_signers(
&self,
_digest: TransactionDigest,
) -> RpcResult<SuiTransactionAuthSignersResponse> {
todo!()
}
}

impl SuiRpcModule for GatewayReadApiImpl {
Expand Down
25 changes: 24 additions & 1 deletion crates/sui-json-rpc/src/read_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ use sui_core::authority::AuthorityState;
use sui_json_rpc_types::{
GetObjectDataResponse, GetPastObjectDataResponse, MoveFunctionArgType, ObjectValueKind, Page,
SuiCoinMetadata, SuiMoveNormalizedFunction, SuiMoveNormalizedModule, SuiMoveNormalizedStruct,
SuiObjectInfo, SuiTransactionEffects, SuiTransactionResponse, TransactionsPage,
SuiObjectInfo, SuiTransactionAuthSignersResponse, SuiTransactionEffects,
SuiTransactionResponse, TransactionsPage,
};
use sui_open_rpc::Module;
use sui_types::base_types::SequenceNumber;
Expand Down Expand Up @@ -134,6 +135,28 @@ impl RpcReadApiServer for ReadApi {
parsed_data: None,
})
}

async fn get_transaction_auth_signers(
&self,
digest: TransactionDigest,
) -> RpcResult<SuiTransactionAuthSignersResponse> {
let (cert, _effects) = self
.state
.get_transaction(digest)
.await
.tap_err(|err| debug!(tx_digest=?digest, "Failed to get transaction: {:?}", err))?;

let mut signers = Vec::new();
let committee = self.state.committee();
for authority_index in cert.auth_sig().signers_map.iter() {
let authority = committee
.authority_by_index(authority_index)
.ok_or_else(|| anyhow!("Failed to get authority"))?;
signers.push(*authority);
}

Ok(SuiTransactionAuthSignersResponse { signers })
}
}

impl SuiRpcModule for ReadApi {
Expand Down
Loading

0 comments on commit b212a76

Please sign in to comment.