Skip to content

Commit

Permalink
Merge pull request #1753 from multiversx/adder-keystore-signing-example
Browse files Browse the repository at this point in the history
Modified the adder interactor example to work with keystore-signing
  • Loading branch information
JustEatAnApple authored Sep 3, 2024
2 parents c1a459a + 3e46541 commit 5724b7d
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 44 deletions.
1 change: 1 addition & 0 deletions contracts/examples/adder/interact/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Pem files are used for interactions, but shouldn't be committed
*.pem
*.json
!adder-owner.pem

# Temporary storage of deployed contract address, so we can preserve the context between executions.
Expand Down
23 changes: 23 additions & 0 deletions contracts/examples/adder/interact/alice.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"version": 4,
"kind": "secretKey",
"id": "f2c5e236-9039-46cd-8df5-1efcd9466ead",
"address": "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1",
"bech32": "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th",
"crypto": {
"ciphertext": "45de5198c6c477725abc17d26c6b5fc88b1ff22a67a8c4784b297d426d351cf5c891a4c92d63e04cf23f602f660b7b606ed1c5293c85ff40216d9e53c9a07c23",
"cipherparams": {
"iv": "d6442fb1d4c49106152baeb3c539ed2c"
},
"cipher": "aes-128-ctr",
"kdf": "scrypt",
"kdfparams": {
"dklen": 32,
"salt": "dd69d88742b9d27a0438a4554d4180b070d9af224ea8ff8225fdf74c8e272adb",
"n": 4096,
"r": 8,
"p": 1
},
"mac": "b277984f71d0e9b4a6597911775c0ee6d598002645b29f22021e595c2725d204"
}
}
125 changes: 89 additions & 36 deletions contracts/examples/adder/interact/src/basic_interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ async fn main() {
basic_interact.print_sum().await;
},
Some(basic_interact_cli::InteractCliCommand::Upgrade(args)) => {
basic_interact.upgrade(args.value).await
let owner_address = basic_interact.adder_owner_address.clone();
basic_interact
.upgrade(args.value, &owner_address, None)
.await
},
None => {},
}
Expand All @@ -65,7 +68,15 @@ impl AdderInteract {

let adder_owner_address =
interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap());
let wallet_address = interactor.register_wallet(test_wallets::mike());
// PASSWORD: "alice"
// InsertPassword::Plaintext("alice".to_string()) || InsertPassword::StandardInput
let wallet_address = interactor.register_wallet(
Wallet::from_keystore_secret(
"alice.json",
InsertPassword::Plaintext("alice".to_string()),
)
.unwrap(),
);

Self {
interactor,
Expand Down Expand Up @@ -93,7 +104,7 @@ impl AdderInteract {
.interactor
.tx()
.from(&self.adder_owner_address)
.gas(3_000_000)
.gas(6_000_000)
.typed(adder_proxy::AdderProxy)
.init(0u32)
.code(ADDER_CODE_PATH)
Expand Down Expand Up @@ -123,7 +134,7 @@ impl AdderInteract {
.typed(adder_proxy::AdderProxy)
.init(0u32)
.code(ADDER_CODE_PATH)
.gas(3_000_000)
.gas(6_000_000)
.returns(ReturnsNewBech32Address)
});
}
Expand Down Expand Up @@ -151,7 +162,7 @@ impl AdderInteract {
.to(self.state.current_adder_address())
.typed(adder_proxy::AdderProxy)
.add(value)
.gas(3_000_000)
.gas(6_000_000)
});
}

Expand All @@ -176,7 +187,7 @@ impl AdderInteract {
.tx()
.from(&self.wallet_address)
.to(self.state.current_adder_address())
.gas(3_000_000)
.gas(6_000_000)
.typed(adder_proxy::AdderProxy)
.add(value)
.prepare_async()
Expand All @@ -201,45 +212,87 @@ impl AdderInteract {
println!("sum: {sum}");
}

async fn upgrade(&mut self, new_value: u32) {
let response = self
.interactor
.tx()
.from(&self.wallet_address)
.to(self.state.current_adder_address())
.gas(3_000_000)
.typed(adder_proxy::AdderProxy)
.upgrade(BigUint::from(new_value))
.code_metadata(CodeMetadata::UPGRADEABLE)
.code(ADDER_CODE_PATH)
.returns(ReturnsResultUnmanaged)
.prepare_async()
.run()
.await;

let sum = self
.interactor
.query()
.to(self.state.current_adder_address())
.typed(adder_proxy::AdderProxy)
.sum()
.returns(ReturnsResultUnmanaged)
.prepare_async()
.run()
.await;
assert_eq!(sum, RustBigUint::from(new_value));
async fn upgrade(
&mut self,
new_value: u32,
sender: &Bech32Address,
expected_result: Option<(u64, &str)>,
) {
match expected_result {
Some((code, msg)) => {
let response = self
.interactor
.tx()
.from(sender)
.to(self.state.current_adder_address())
.gas(6_000_000)
.typed(adder_proxy::AdderProxy)
.upgrade(new_value)
.code_metadata(CodeMetadata::UPGRADEABLE)
.code(ADDER_CODE_PATH)
.returns(ExpectError(code, msg))
.prepare_async()
.run()
.await;

println!("response: {response:?}");
},
None => {
self.interactor
.tx()
.from(sender)
.to(self.state.current_adder_address())
.gas(6_000_000)
.typed(adder_proxy::AdderProxy)
.upgrade(new_value)
.code_metadata(CodeMetadata::UPGRADEABLE)
.code(ADDER_CODE_PATH)
.prepare_async()
.run()
.await;

println!("response: {response:?}");
let sum = self
.interactor
.query()
.to(self.state.current_adder_address())
.typed(adder_proxy::AdderProxy)
.sum()
.returns(ReturnsResultUnmanaged)
.prepare_async()
.run()
.await;

assert_eq!(sum, RustBigUint::from(new_value));
},
}
}
}

#[tokio::test]
#[ignore = "run on demand"]
async fn test() {
async fn upgrade_test() {
let mut basic_interact = AdderInteract::init().await;
let wallet_address = basic_interact.wallet_address.clone();
let adder_owner_address = basic_interact.adder_owner_address.clone();
let error_not_owner = (4, "upgrade is allowed only for owner");

basic_interact.deploy().await;
basic_interact.add(1u32).await;

basic_interact.upgrade(7u32).await;
// Sum will be 1
basic_interact.print_sum().await;

basic_interact
.upgrade(7u32, &adder_owner_address, None)
.await;

// Sum will be the updated value of 7
basic_interact.print_sum().await;

basic_interact
.upgrade(10u32, &wallet_address, Some(error_not_owner))
.await;

// Sum will remain 7
basic_interact.print_sum().await;
}
5 changes: 4 additions & 1 deletion framework/snippets/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ pub use crate::{
dns_address_for_name, test_wallets, Interactor, InteractorPrepareAsync, StepBuffer,
};

pub use multiversx_sdk::wallet::Wallet;
pub use multiversx_sdk::{
wallet::Wallet,
data::keystore::InsertPassword,
};

pub use env_logger;
pub use tokio;
7 changes: 7 additions & 0 deletions sdk/core/src/data/keystore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ pub enum WalletError {
InvalidKdf,
InvalidCipher,
}

#[derive(Debug)]
pub enum InsertPassword {
Plaintext(String),
StandardInput,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CryptoParams {
pub iv: String,
Expand Down
24 changes: 17 additions & 7 deletions sdk/core/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,24 @@ impl Wallet {
(private_key_str, public_key_str)
}

pub fn from_keystore_secret(file_path: &str) -> Result<Self> {
let decyption_params =
Self::validate_keystore_password(file_path, Self::get_keystore_password())
.unwrap_or_else(|e| {
panic!("Error: {:?}", e);
});
pub fn from_keystore_secret(file_path: &str, insert_password: InsertPassword) -> Result<Self> {
let decryption_params = match insert_password {
InsertPassword::Plaintext(password) => {
Self::validate_keystore_password(file_path, password.to_string()).unwrap_or_else(
|e| {
panic!("Error: {:?}", e);
},
)
},
InsertPassword::StandardInput => {
Self::validate_keystore_password(file_path, Self::get_keystore_password())
.unwrap_or_else(|e| {
panic!("Error: {:?}", e);
})
},
};
let priv_key = PrivateKey::from_hex_str(
hex::encode(Self::decrypt_secret_key(decyption_params)).as_str(),
hex::encode(Self::decrypt_secret_key(decryption_params)).as_str(),
)?;
Ok(Self { priv_key })
}
Expand Down

0 comments on commit 5724b7d

Please sign in to comment.