Skip to content

Commit

Permalink
EVM address mapping endpoints (#3997)
Browse files Browse the repository at this point in the history
* update lib

* add new v2 rest api endpoints with "address_mapping/jormungandr_address", "address_mapping/evm_address" functions

* bump chain-libs

* fix clippy

* fix build

* rename v2 to evm

* fix CI

* update
  • Loading branch information
Mr-Leshiy authored May 26, 2022
1 parent 6419f81 commit ad4fce5
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 26 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: stoplightio/spectral-action@v0.6.0
- uses: stoplightio/spectral-action@v0.8.2
with:
file_glob: doc/api/*.yaml
repo_token: ${{ secrets.GITHUB_TOKEN }}
spectral_ruleset: ''
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- Add new Ethreum RPC mining endpoints: eth_mining, eth_coinbase, eth_hashrate, eth_getWork, eth_submitWork, eth_submitHashrate
- Add chain-evm as optional dependency for jcli
- Update gas price and block gas limit for EVM params
- Add new 'evm' REST API endpoints 'address_mapping/jormungandr_address', 'address_mapping/evm_address` for getting info about address mapping. They are optional for the 'evm' feature.

## Release 0.13.0

Expand Down
28 changes: 14 additions & 14 deletions Cargo.lock

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

51 changes: 51 additions & 0 deletions doc/api/v0.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ tags:
- name: stake
- name: utils
- name: vote
- name: address_mapping

paths:
'/api/v0/account/{account_id}':
Expand Down Expand Up @@ -2415,3 +2416,53 @@ components:
description: upper bound of the available options, maximum being 16 (not included)
minimum: 1
maximum: 15

# it is only enabled with the "evm" feature included during the build
path:
/api/evm/address_mapping/jormungandr_address/{evm_hex_id}:
get:
description: Gets corresponded, mapped jormungadr address for the provided evm address
operationId: AddressMappingJorId
tags:
- address_mapping
parameters:
- in: path
name: evm_hex_id
required: true
description: Hex-encoded evm address.
schema:
type: string
pattern: '[0-9a-f]+'
responses:
'200':
description: Success
content:
application/json:
schema:
type: string
description: hex encoded jormungandr address

# it is only enabled with the "evm" feature included during the build
path:
/api/evm/address_mapping/evm_address/{jor_hex_id}:
get:
description: Gets corresponded, mapped evm address for the provided jormungandr address
operationId: AddressMappingEvmId
tags:
- address_mapping
parameters:
- in: path
name: jor_hex_id
required: true
description: Hex-encoded jormungandr address.
schema:
type: string
pattern: '[0-9a-f]+'
responses:
'200':
description: Success
content:
application/json:
schema:
type: string
description: hex encoded evm address
3 changes: 2 additions & 1 deletion jormungandr/src/rest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ pub async fn start_rest_server(config: Config, context: ContextLock) {
.write()
.await
.set_rest_server_stopper(ServerStopper::new(stopper_tx));
let api = v0::filter(context.clone()).or(v1::filter(context.clone()));

let api = warp::path!("api" / ..)
.and(v0::filter(context.clone()).or(v1::filter(context.clone())))
.and(api)
.with(warp::filters::trace::trace(|info| {
use http_zipkin::get_trace_context;
use tracing::field::Empty;
Expand Down
23 changes: 23 additions & 0 deletions jormungandr/src/rest/v0/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,26 @@ pub async fn get_active_vote_plans(context: ContextLock) -> Result<impl Reply, R
.map(|r| warp::reply::json(&r))
.map_err(warp::reject::custom)
}

#[cfg(feature = "evm")]
pub async fn get_jor_address(
evm_id_hex: String,
context: ContextLock,
) -> Result<impl Reply, Rejection> {
let context = context.read().await;
logic::get_jor_address(&context, &evm_id_hex)
.await
.map_err(warp::reject::custom)
}

#[cfg(feature = "evm")]
pub async fn get_evm_address(
evm_id_hex: String,
context: ContextLock,
) -> Result<impl Reply, Rejection> {
let context = context.read().await;
logic::get_evm_address(&context, &evm_id_hex)
.await
.map_err(warp::reject::custom)
.map(|r| warp::reply::json(&r))
}
32 changes: 32 additions & 0 deletions jormungandr/src/rest/v0/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ pub enum Error {
Hex(#[from] hex::FromHexError),
#[error("Could not process fragment")]
Fragment(FragmentsProcessingSummary),
#[cfg(feature = "evm")]
#[error("Can not parse address: {0}")]
AddressParseError(String),
}

fn parse_account_id(id_hex: &str) -> Result<Identifier, Error> {
Expand Down Expand Up @@ -591,3 +594,32 @@ pub async fn get_active_vote_plans(context: &Context) -> Result<Vec<VotePlanStat
.collect();
Ok(vp)
}

#[cfg(feature = "evm")]
pub async fn get_jor_address(context: &Context, evm_id_hex: &str) -> Result<String, Error> {
Ok(context
.blockchain_tip()?
.get_ref()
.await
.ledger()
.jormungandr_mapped_address(
&chain_evm::Address::from_str(evm_id_hex)
.map_err(|e| Error::AddressParseError(e.to_string()))?,
)
.to_string())
}

#[cfg(feature = "evm")]
pub async fn get_evm_address(context: &Context, jor_id_hex: &str) -> Result<Option<String>, Error> {
Ok(context
.blockchain_tip()?
.get_ref()
.await
.ledger()
.evm_mapped_address(
&PublicKey::<AccountAlg>::from_str(jor_id_hex)
.map_err(|e| Error::AddressParseError(e.to_string()))?
.into(),
)
.map(|val| val.to_string()))
}
29 changes: 25 additions & 4 deletions jormungandr/src/rest/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,31 @@ pub fn filter(

let vote_plans = warp::path!("plans")
.and(warp::get())
.and(with_context)
.and(with_context.clone())
.and_then(handlers::get_active_vote_plans)
.boxed();
root.and(committees.or(vote_plans)).boxed()
};

#[cfg(feature = "evm")]
let address_mapping = {
let root = warp::path!("address_mapping" / ..);

let get_jor_address = warp::path!("jormungandr_address" / String)
.and(warp::get())
.and(with_context.clone())
.and_then(handlers::get_jor_address)
.boxed();

let get_evm_address = warp::path!("evm_address" / String)
.and(warp::get())
.and(with_context)
.and_then(handlers::get_evm_address)
.boxed();

root.and(get_jor_address.or(get_evm_address)).boxed()
};

let routes = shutdown
.or(account)
.or(block)
Expand All @@ -244,10 +263,12 @@ pub fn filter(
.or(rewards)
.or(utxo)
.or(diagnostic)
.or(votes)
.boxed();
.or(votes);

#[cfg(feature = "evm")]
let routes = routes.or(address_mapping);

root.and(routes).recover(handle_rejection).boxed()
root.and(routes.boxed()).recover(handle_rejection).boxed()
}

/// Convert rejections to actual HTTP errors
Expand Down
6 changes: 2 additions & 4 deletions jormungandr/src/rest/v1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,9 @@ pub fn filter(
.and(with_context)
.and_then(handlers::get_accounts_votes_count);

let routes = fragments;
let routes = fragments.or(votes_with_plan).or(votes).or(votes_count);

root.and(routes.or(votes_with_plan).or(votes).or(votes_count))
.recover(handle_rejection)
.boxed()
root.and(routes).recover(handle_rejection).boxed()
}

/// Convert rejections to actual HTTP errors
Expand Down
2 changes: 1 addition & 1 deletion jormungandr/src/topology/topology.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl LayerBuilder for CustomLayerBuilder {

impl P2pTopology {
pub fn new(config: &Configuration, stats_counter: Metrics) -> Self {
let addr = config.public_address.or(Some(*LOCAL_ADDR)).unwrap();
let addr = config.public_address.unwrap_or(*LOCAL_ADDR);
let key = secret_key_into_keynesis(config.node_key.clone());

let quarantine = ReportRecords::from_config(config.policy.clone());
Expand Down

0 comments on commit ad4fce5

Please sign in to comment.