Skip to content

Commit

Permalink
[rpc] Get protocol config endpoint(#11510)
Browse files Browse the repository at this point in the history
## Description 

### Adds RPC support to get protocol config.
If the protocol config is not specified, the node returns the config for
the epoch its currently processing.

Examples
**1. Valid protocol version (9) specified**
```
curl --location --request POST 0.0.0.0:9000  \
--header 'Content-Type: application/json' \
--data-raw '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"sui_getProtocolConfig",
    "params":["9"]
}'| jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8546  100  8453  100    93   547k   6169 --:--:-- --:--:-- --:--:-- 1043k
{
  "jsonrpc": "2.0",
  "result": {
    "minSupportedProtocolVersion": "1",
    "maxSupportedProtocolVersion": "10",
    "protocolVersion": "9",
    "featureFlags": {
      "advance_epoch_start_time_in_safe_mode": true,
      "advance_to_highest_supported_protocol_version": true,
      "ban_entry_init": true,
      "commit_root_state_digest": false,
      .............[truncated]................... 
    },
    "attributes": {
      "address_from_bytes_cost_base": {
        "u64": "52"
      },
      "address_from_u256_cost_base": {
        "u64": "52"
      },
      "address_to_u256_cost_base": {
        "u64": "52"
      },      
     .............[truncated]................... 
```
**2. Invalid protocol version specified**
```
curl --location --request POST 0.0.0.0:9000  \
--header 'Content-Type: application/json' \
--data-raw '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"sui_getProtocolConfig",
    "params":["19"]
}'| jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   230  100   136  100    94   9841   6802 --:--:-- --:--:-- --:--:--  224k
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32000,
    "message": "Unsupported protocol version requested. Min supported: 1, max supported: 10"
  },
  "id": 1
}
```
**3. No protocol version specified**
Although this node supports protocol version 1-10, it is currently
syncing TXs at version 1, so it returns 1 as thats the highest it can
process currently given its objects state.
```
curl --location --request POST 0.0.0.0:9000  \
--header 'Content-Type: application/json' \
--data-raw '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"sui_getProtocolConfig" 
}'| jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8469  100  8396  100    73  1022k   9107 --:--:-- --:--:-- --:--:-- 4135k
{
  "jsonrpc": "2.0",
  "result": {
    "minSupportedProtocolVersion": "1",
    "maxSupportedProtocolVersion": "10",
    "protocolVersion": "1",
    "featureFlags": {
      "advance_epoch_start_time_in_safe_mode": false,
      "advance_to_highest_supported_protocol_version": false,
      "ban_entry_init": false,
      "commit_root_state_digest": false,
      .............[truncated]................... 
    },
    "attributes": {
      "address_from_bytes_cost_base": {
        "u64": "52"
      },
      "address_from_u256_cost_base": {
        "u64": "52"
      },
      "address_to_u256_cost_base": {
     .............[truncated]................... 
```


### Other utilities
Adds some utilities useful for CLI and protocol config attr discovery.
Needed to support RPC queries of protocol config info.

First a wrapper enum is introduced since config value types are
heterogenous.
The wrapper will automatically pick up the type for all config
attributes and add it to the enum variant
```
pub enum ProtocolConfigValue {
    u32(u32),
    u64(u64),
    ....
}
```

**1. Logic to lookup protocol config attributes by string repr**
`lookup_attr(&self, attr_as_string) -> Option<ProtocolConfigValue>`
```
  let prot: ProtocolConfig = ProtocolConfig::get_for_version(ProtocolVersion::new(9));

  // Result should be Some(128)
  assert!(
      prot.lookup_attr("max_move_identifier_len".to_string())
          == Some(ProtocolConfigValue::u64(prot.max_move_identifier_len()))
  );
```
**2. Logic to return a BTreeMap of config attrs to their values**
`attr_map(&self) -> BTreeMap<String, Option<ProtocolConfigValue>>`
This is equivalent to looping over all entries of `lookup_attr(value)`
and putting them in a map
```
    // attr_map() returns BTreeMap<String, Option<ProtocolConfigValue>>
    // where each key is the string repr of the attribute
  assert!(
    prot.attr_map().get("max_arguments").unwrap()
        == &Some(ProtocolConfigValue::u32(prot.max_arguments()))
     );
```

## Test Plan 

Unit tests

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
  • Loading branch information
oxade authored May 5, 2023
1 parent d18e012 commit 8f5fcfa
Show file tree
Hide file tree
Showing 14 changed files with 1,074 additions and 22 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

20 changes: 17 additions & 3 deletions crates/sui-indexer/src/apis/read_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use jsonrpsee::RpcModule;
use sui_json_rpc::api::{ReadApiClient, ReadApiServer};
use sui_json_rpc::SuiRpcModule;
use sui_json_rpc_types::{
Checkpoint, CheckpointId, CheckpointPage, SuiEvent, SuiGetPastObjectRequest,
SuiObjectDataOptions, SuiObjectResponse, SuiPastObjectResponse, SuiTransactionBlockResponse,
SuiTransactionBlockResponseOptions,
Checkpoint, CheckpointId, CheckpointPage, ProtocolConfigResponse, SuiEvent,
SuiGetPastObjectRequest, SuiObjectDataOptions, SuiObjectResponse, SuiPastObjectResponse,
SuiTransactionBlockResponse, SuiTransactionBlockResponseOptions,
};
use sui_open_rpc::Module;
use sui_types::base_types::{ObjectID, SequenceNumber};
Expand Down Expand Up @@ -353,6 +353,20 @@ where
dynamic_fields_load_obj_guard.stop_and_record();
dyn_fields_resp
}

async fn get_protocol_config(
&self,
version: Option<BigInt<u64>>,
) -> RpcResult<ProtocolConfigResponse> {
let protocol_config_guard = self
.state
.indexer_metrics()
.get_protocol_config_latency
.start_timer();
let protocol_config_resp = self.fullnode.get_protocol_config(version).await;
protocol_config_guard.stop_and_record();
protocol_config_resp
}
}

impl<S> SuiRpcModule for ReadApi<S>
Expand Down
8 changes: 8 additions & 0 deletions crates/sui-indexer/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub struct IndexerMetrics {
pub query_events_latency: Histogram,
pub get_dynamic_fields_latency: Histogram,
pub get_dynamic_field_object_latency: Histogram,
pub get_protocol_config_latency: Histogram,
}

impl IndexerMetrics {
Expand Down Expand Up @@ -321,6 +322,13 @@ impl IndexerMetrics {
registry
)
.unwrap(),
get_protocol_config_latency: register_histogram_with_registry!(
"get_protocol_config_latency",
"Time spent in get_protocol_config_latency on the fullnode behind.",
LATENCY_SEC_BUCKETS.to_vec(),
registry
)
.unwrap(),
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/sui-json-rpc-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub use sui_extended::*;
pub use sui_governance::*;
pub use sui_move::*;
pub use sui_object::*;
pub use sui_protocol::*;
pub use sui_transaction::*;
use sui_types::base_types::ObjectID;
use sui_types::dynamic_field::DynamicFieldInfo;
Expand All @@ -30,6 +31,7 @@ mod sui_extended;
mod sui_governance;
mod sui_move;
mod sui_object;
mod sui_protocol;
mod sui_transaction;

pub type DynamicFieldPage = Page<DynamicFieldInfo, ObjectID>;
Expand Down
76 changes: 76 additions & 0 deletions crates/sui-json-rpc-types/src/sui_protocol.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use std::collections::BTreeMap;

use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use serde_with::DisplayFromStr;
use sui_protocol_config::{ProtocolConfig, ProtocolConfigValue, ProtocolVersion};
use sui_types::sui_serde::Readable;
use sui_types::sui_serde::{AsProtocolVersion, BigInt};

#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, PartialEq)]
#[serde(rename_all = "camelCase", rename = "ProtocolConfigValue")]
pub enum SuiProtocolConfigValue {
U32(
#[schemars(with = "BigInt<u32>")]
#[serde_as(as = "BigInt<u32>")]
u32,
),
U64(
#[schemars(with = "BigInt<u64>")]
#[serde_as(as = "BigInt<u64>")]
u64,
),
F64(
#[schemars(with = "String")]
#[serde_as(as = "DisplayFromStr")]
f64,
),
}

impl From<ProtocolConfigValue> for SuiProtocolConfigValue {
fn from(value: ProtocolConfigValue) -> Self {
match value {
ProtocolConfigValue::u32(y) => SuiProtocolConfigValue::U32(y),
ProtocolConfigValue::u64(x) => SuiProtocolConfigValue::U64(x),
ProtocolConfigValue::f64(z) => SuiProtocolConfigValue::F64(z),
}
}
}

#[serde_as]
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, PartialEq)]
#[serde(rename_all = "camelCase", rename = "ProtocolConfig")]
pub struct ProtocolConfigResponse {
#[schemars(with = "AsProtocolVersion")]
#[serde_as(as = "Readable<AsProtocolVersion, _>")]
pub min_supported_protocol_version: ProtocolVersion,
#[schemars(with = "AsProtocolVersion")]
#[serde_as(as = "Readable<AsProtocolVersion, _>")]
pub max_supported_protocol_version: ProtocolVersion,
#[schemars(with = "AsProtocolVersion")]
#[serde_as(as = "Readable<AsProtocolVersion, _>")]
pub protocol_version: ProtocolVersion,
pub feature_flags: BTreeMap<String, bool>,
pub attributes: BTreeMap<String, Option<SuiProtocolConfigValue>>,
}

impl From<ProtocolConfig> for ProtocolConfigResponse {
fn from(config: ProtocolConfig) -> Self {
ProtocolConfigResponse {
protocol_version: config.version,
attributes: config
.attr_map()
.into_iter()
.map(|(k, v)| (k, v.map(SuiProtocolConfigValue::from)))
.collect(),
min_supported_protocol_version: ProtocolVersion::MIN,
max_supported_protocol_version: ProtocolVersion::MAX,
feature_flags: config.feature_map(),
}
}
}
11 changes: 10 additions & 1 deletion crates/sui-json-rpc/src/api/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
use jsonrpsee::core::RpcResult;
use jsonrpsee_proc_macros::rpc;

use sui_json_rpc_types::SuiLoadedChildObjectsResponse;
use sui_json_rpc_types::{
Checkpoint, CheckpointId, CheckpointPage, SuiEvent, SuiGetPastObjectRequest,
SuiObjectDataOptions, SuiObjectResponse, SuiPastObjectResponse, SuiTransactionBlockResponse,
SuiTransactionBlockResponseOptions,
};
use sui_json_rpc_types::{ProtocolConfigResponse, SuiLoadedChildObjectsResponse};
use sui_open_rpc_macros::open_rpc;
use sui_types::base_types::{ObjectID, SequenceNumber, TransactionDigest};
use sui_types::sui_serde::BigInt;
Expand Down Expand Up @@ -139,4 +139,13 @@ pub trait ReadApi {
/// Return the sequence number of the latest checkpoint that has been executed
#[method(name = "getLatestCheckpointSequenceNumber")]
async fn get_latest_checkpoint_sequence_number(&self) -> RpcResult<BigInt<u64>>;

/// Return the protocol config table for the given version number.
/// If the version number is not specified, If none is specified, the node uses the version of the latest epoch it has processed.
#[method(name = "getProtocolConfig")]
async fn get_protocol_config(
&self,
/// An optional protocol version specifier. If omitted, the latest protocol config table for the node will be returned.
version: Option<BigInt<u64>>,
) -> RpcResult<ProtocolConfigResponse>;
}
31 changes: 28 additions & 3 deletions crates/sui-json-rpc/src/read_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ use shared_crypto::intent::{AppId, Intent, IntentMessage, IntentScope, IntentVer
use sui_core::authority::AuthorityState;
use sui_json_rpc_types::{
BalanceChange, Checkpoint, CheckpointId, CheckpointPage, DisplayFieldsResponse, EventFilter,
ObjectChange, SuiEvent, SuiGetPastObjectRequest, SuiMoveStruct, SuiMoveValue,
SuiObjectDataOptions, SuiObjectResponse, SuiPastObjectResponse, SuiTransactionBlock,
SuiTransactionBlockEvents, SuiTransactionBlockResponse, SuiTransactionBlockResponseOptions,
ObjectChange, ProtocolConfigResponse, SuiEvent, SuiGetPastObjectRequest, SuiMoveStruct,
SuiMoveValue, SuiObjectDataOptions, SuiObjectResponse, SuiPastObjectResponse,
SuiTransactionBlock, SuiTransactionBlockEvents, SuiTransactionBlockResponse,
SuiTransactionBlockResponseOptions,
};
use sui_json_rpc_types::{SuiLoadedChildObject, SuiLoadedChildObjectsResponse};
use sui_open_rpc::Module;
use sui_protocol_config::{ProtocolConfig, ProtocolVersion};
use sui_types::base_types::{ObjectID, SequenceNumber, TransactionDigest};
use sui_types::collection_types::VecMap;
use sui_types::crypto::default_hash;
Expand Down Expand Up @@ -900,6 +902,29 @@ impl ReadApiServer for ReadApi {
})
})
}

#[instrument(skip(self))]
async fn get_protocol_config(
&self,
version: Option<BigInt<u64>>,
) -> RpcResult<ProtocolConfigResponse> {
with_tracing!("get_protocol_config", async move {
Ok(version
.map(|v| {
ProtocolConfig::get_for_version_if_supported((*v).into()).ok_or(anyhow!(
"Unsupported protocol version requested. Min supported: {}, max supported: {}",
ProtocolVersion::MIN.as_u64(),
ProtocolVersion::MAX.as_u64()
))
})
.unwrap_or(Ok(self
.state
.load_epoch_store_one_call_per_task()
.protocol_config()
.clone()))
.map(ProtocolConfigResponse::from)?)
})
}
}

impl SuiRpcModule for ReadApi {
Expand Down
1 change: 1 addition & 0 deletions crates/sui-open-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ sui-json-rpc = { path = "../sui-json-rpc" }
sui-json-rpc-types = { path = "../sui-json-rpc-types" }
sui-json = { path = "../sui-json" }
sui-types = { path = "../sui-types", features = ["test-utils"] }
sui-protocol-config = { path = "../sui-protocol-config" }
rand = "0.8.5"

move-core-types.workspace = true
Expand Down
Loading

0 comments on commit 8f5fcfa

Please sign in to comment.