Skip to content

Commit

Permalink
feat: support specification of private key to claimer
Browse files Browse the repository at this point in the history
  • Loading branch information
tuler committed Mar 13, 2024
1 parent 01cf64d commit 93fbe8a
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Added verification to ensure CARTESI_BLOCKCHAIN_ID matches the id returned from the Ethereum node
- Added support for CARTESI_AUTH_PRIVATE_KEY

## Changed

Expand Down
3 changes: 3 additions & 0 deletions cmd/cartesi-rollups-node/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ func newAuthorityClaimer() services.CommandService {
s.Env = append(s.Env,
fmt.Sprintf("AUTHORITY_CLAIMER_HTTP_SERVER_PORT=%v", getPort(portOffsetAuthorityClaimer)))
switch auth := config.GetAuth().(type) {
case config.AuthPrivateKey:
s.Env = append(s.Env,
fmt.Sprintf("TX_SIGNING_PRIVATE_KEY=%v", auth.PrivateKey))
case config.AuthMnemonic:
s.Env = append(s.Env,
fmt.Sprintf("TX_SIGNING_MNEMONIC=%v", auth.Mnemonic))
Expand Down
5 changes: 5 additions & 0 deletions internal/config/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ package config
// Auth objects are used to sign transactions.
type Auth any

// Allows signing through private keys.
type AuthPrivateKey struct {
PrivateKey string
}

// Allows signing through mnemonics.
type AuthMnemonic struct {
Mnemonic string
Expand Down
5 changes: 5 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ var (
// ------------------------------------------------------------------------------------------------

func GetAuth() Auth {
// if private key is coming from an environment variable
if privateKey, ok := getCartesiAuthPrivateKey(); ok {
return AuthPrivateKey{PrivateKey: privateKey}
}

// getting the (optional) account index
index, _ := getCartesiAuthMnemonicAccountIndex()

Expand Down
9 changes: 9 additions & 0 deletions internal/config/generate/Config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,15 @@ description = """
When using mnemonics to sign transactions,
the node will use this account index to generate the private key."""

[auth.CARTESI_AUTH_PRIVATE_KEY]
go-type = "string"
export = false
redact = true
description = """
The node will use this private key to sign transactions.
Overrides `CARTESI_AUTH_MNEMONIC`, `CARTESI_AUTH_MNEMONIC_FILE` and `CARTESI_AUTH_AWS_KMS_*`."""

[auth.CARTESI_AUTH_AWS_KMS_KEY_ID]
go-type = "string"
export = false
Expand Down
5 changes: 5 additions & 0 deletions internal/config/get.go

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

10 changes: 9 additions & 1 deletion offchain/authority-claimer/src/config/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ impl TryFrom<AuthorityClaimerCLI> for AuthorityClaimerConfig {
#[derive(Debug, Parser)]
#[command(name = "tx_signing_config")]
pub(crate) struct TxSigningCLIConfig {
/// Signer private key, overrides `tx_signing_mnemonic` , `tx_signing_mnemonic_file` and `tx_signing_aws_kms_*`
#[arg(long, env)]
tx_signing_private_key: Option<String>,

/// Signer mnemonic, overrides `tx_signing_mnemonic_file` and `tx_signing_aws_kms_*`
#[arg(long, env)]
tx_signing_mnemonic: Option<String>,
Expand All @@ -117,7 +121,11 @@ impl TryFrom<TxSigningCLIConfig> for TxSigningConfig {

fn try_from(cli: TxSigningCLIConfig) -> Result<Self, Self::Error> {
let account_index = cli.tx_signing_mnemonic_account_index;
if let Some(mnemonic) = cli.tx_signing_mnemonic {
if let Some(private_key) = cli.tx_signing_private_key {
Ok(TxSigningConfig::PrivateKey {
private_key: Redacted::new(private_key)
})
} else if let Some(mnemonic) = cli.tx_signing_mnemonic {
Ok(TxSigningConfig::Mnemonic {
mnemonic: Redacted::new(mnemonic),
account_index,
Expand Down
4 changes: 4 additions & 0 deletions offchain/authority-claimer/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ pub struct AuthorityClaimerConfig {

#[derive(Debug, Clone)]
pub enum TxSigningConfig {
PrivateKey {
private_key: Redacted<String>
},

Mnemonic {
mnemonic: Redacted<String>,
account_index: Option<u32>,
Expand Down
53 changes: 48 additions & 5 deletions offchain/authority-claimer/src/signer/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ impl ConditionalSigner {
tx_signing_config: &TxSigningConfig,
) -> Result<Self, ConditionalSignerError> {
match tx_signing_config.clone() {
TxSigningConfig::PrivateKey { private_key } => {
let wallet = private_key
.inner()
.as_str()
.parse::<LocalWallet>()
.context(LocalWalletSnafu)?
.with_chain_id(chain_id);
Ok(ConditionalSigner::LocalWallet(wallet))
}
TxSigningConfig::Mnemonic {
mnemonic,
account_index,
Expand Down Expand Up @@ -162,8 +171,19 @@ mod tests {
// --------------------------------------------------------------------------------------------

#[tokio::test]
async fn new_local_wallet_conditional_signer() {
let conditional_signer = local_wallet_conditional_signer().await;
async fn new_local_wallet_mnemonic_conditional_signer() {
let conditional_signer =
local_wallet_mnemonic_conditional_signer().await;
assert!(matches!(
conditional_signer,
ConditionalSigner::LocalWallet(_)
));
}

#[tokio::test]
async fn new_local_wallet_private_key_conditional_signer() {
let conditional_signer =
local_wallet_private_key_conditional_signer().await;
assert!(matches!(
conditional_signer,
ConditionalSigner::LocalWallet(_)
Expand All @@ -175,8 +195,19 @@ mod tests {
// --------------------------------------------------------------------------------------------

#[tokio::test]
async fn sign_transaction_with_local_wallet_conditional_signer() {
let conditional_signer = local_wallet_conditional_signer().await;
async fn sign_transaction_with_mnemonic_local_wallet_conditional_signer() {
let conditional_signer =
local_wallet_mnemonic_conditional_signer().await;
let message = eip1559_message();
let result = conditional_signer.sign_transaction(&message).await;
assert!(result.is_ok());
}

#[tokio::test]
async fn sign_transaction_with_private_key_local_wallet_conditional_signer()
{
let conditional_signer =
local_wallet_private_key_conditional_signer().await;
let message = eip1559_message();
let result = conditional_signer.sign_transaction(&message).await;
assert!(result.is_ok());
Expand All @@ -187,10 +218,12 @@ mod tests {
// --------------------------------------------------------------------------------------------

const CHAIN_ID: u64 = 1;
const PRIVATE_KEY: &str =
"59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
const MNEMONIC: &str =
"indoor dish desk flag debris potato excuse depart ticket judge file exit";

async fn local_wallet_conditional_signer() -> ConditionalSigner {
async fn local_wallet_mnemonic_conditional_signer() -> ConditionalSigner {
let tx_signing_config = TxSigningConfig::Mnemonic {
mnemonic: Redacted::new(MNEMONIC.to_string()),
account_index: Some(1),
Expand All @@ -200,6 +233,16 @@ mod tests {
.unwrap()
}

async fn local_wallet_private_key_conditional_signer() -> ConditionalSigner
{
let tx_signing_config = TxSigningConfig::PrivateKey {
private_key: Redacted::new(PRIVATE_KEY.to_string()),
};
ConditionalSigner::new(CHAIN_ID, &tx_signing_config)
.await
.unwrap()
}

fn eip1559_message() -> TypedTransaction {
TypedTransaction::Eip1559(
Eip1559TransactionRequest::new()
Expand Down

0 comments on commit 93fbe8a

Please sign in to comment.