Skip to content

Commit

Permalink
feat: add genesis dfn address (#185)
Browse files Browse the repository at this point in the history
Genesis addresses were given in 'DFN' form, which essentially just encoded the K256 key as an Ethereum address instead of a principal. This address is required for the KYC process, so keysmith had an option to print it. This PR adds that functionality to quill as well.
  • Loading branch information
adamspofford-dfinity authored Mar 30, 2023
1 parent dbeff49 commit 57defe4
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 18 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- Added option to print DFN address for Genesis investors. (#184)

## [0.4.1] - 2023-03-23

- Added release binaries for linux-gnu in addition to linux-musl on amd64.
Expand Down
23 changes: 12 additions & 11 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ crc32fast = "1.3.2"
data-encoding = "2.3.3"
itertools = "0.10.5"
atty = "0.2.14"
sha3 = "0.10.6"

[dev-dependencies]
tempfile = "3.3.0"
Expand Down
7 changes: 4 additions & 3 deletions docs/cli-reference/quill-public-ids.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ quill public-ids [option]

## Flags

| Flag | Description |
|----------------|-----------------------------|
| `-h`, `--help` | Displays usage information. |
| Flag | Description |
|-----------------|----------------------------------------------------------------|
| `-h`, `--help` | Displays usage information. |
| `--genesis-dfn` | Additionally prints the legacy DFN address for Genesis claims. |

## Options

Expand Down
27 changes: 23 additions & 4 deletions src/commands/public.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,42 @@
use crate::lib::{get_account_id, get_identity, AnyhowResult, AuthInfo};
use anyhow::anyhow;
use anyhow::{anyhow, bail, Context};
use candid::Principal;
use clap::Parser;
use icp_ledger::AccountIdentifier;
use k256::{elliptic_curve::sec1::ToEncodedPoint, SecretKey};
use sha3::{Digest, Keccak256};

#[derive(Parser)]
/// Prints the principal id and the account id.
pub struct PublicOpts {
/// Principal for which to get the account_id.
#[clap(long)]
principal_id: Option<String>,
/// Additionally prints the legacy DFN address for Genesis claims.
#[clap(long, conflicts_with = "principal-id")]
genesis_dfn: bool,
}

/// Prints the account and the principal ids.
pub fn exec(auth: &AuthInfo, opts: PublicOpts) -> AnyhowResult {
let (principal_id, account_id) = get_public_ids(auth, opts)?;
let (principal_id, account_id) = get_public_ids(auth, &opts)?;
println!("Principal id: {}", principal_id.to_text());
println!("Account id: {}", account_id);
if opts.genesis_dfn {
let AuthInfo::PemFile(pem) = auth else {
bail!("Must supply a pem or seed file for the DFN address");
};
println!("DFN address: {}", get_dfn(pem)?)
}
Ok(())
}

/// Returns the account id and the principal id if the private key was provided.
fn get_public_ids(
auth: &AuthInfo,
opts: PublicOpts,
opts: &PublicOpts,
) -> AnyhowResult<(Principal, AccountIdentifier)> {
match opts.principal_id {
match &opts.principal_id {
Some(principal_id) => {
let principal_id = Principal::from_text(principal_id)?;
Ok((principal_id, get_account_id(principal_id)?))
Expand All @@ -42,6 +53,14 @@ fn get_public_ids(
}
}

fn get_dfn(pem: &str) -> AnyhowResult<String> {
let pk = SecretKey::from_sec1_pem(pem).context("DFN addresses need a secp256k1 key")?;
let pubk = pk.public_key();
let uncompressed = pubk.to_encoded_point(false);
let hash = Keccak256::digest(&uncompressed.as_bytes()[1..]);
Ok(hex::encode(&hash[12..]))
}

/// Returns the account id and the principal id if the private key was provided.
pub fn get_ids(auth: &AuthInfo) -> AnyhowResult<(Principal, AccountIdentifier)> {
let principal_id = get_identity(auth)?.sender().map_err(|e| anyhow!(e))?;
Expand Down
1 change: 1 addition & 0 deletions tests/commands/public-ids-dfn.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"$QUILL" public-ids --genesis-dfn --seed-file - <<<"fee tube anger harsh pipe pull since path erase hire ordinary display"
3 changes: 3 additions & 0 deletions tests/outputs/public-ids-dfn.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Principal id: ed6vu-jnldn-5wync-3xnlm-jzlg2-5kjds-iqbcj-5pjgi-jhbw3-qawnx-eae
Account id: 2adf562a6232efe3a3934880edb092ae481651fc961a61d845797d762f437fbd
DFN address: bfcc18caabb2b3ca17c50c0d3834e368c4e4b88f

0 comments on commit 57defe4

Please sign in to comment.