diff --git a/Cargo.lock b/Cargo.lock index df9c853d3..d1552ed24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2443,9 +2443,9 @@ dependencies = [ [[package]] name = "near-ledger" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7706ef5fdfc979957a58c240f7bd6e7d969550310888a3d5b18267b73d50a51" +checksum = "a8849fda5ad5da9774d313f5d28247260ff48ae89a57f281c8e65c32b64d6c99" dependencies = [ "ed25519-dalek 1.0.1", "hex 0.4.3", @@ -2453,6 +2453,7 @@ dependencies = [ "ledger-transport", "ledger-transport-hid", "log", + "near-primitives", "near-primitives-core", "slip10", ] diff --git a/Cargo.toml b/Cargo.toml index 358b1a5eb..5dd8073b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,7 +66,7 @@ bytesize = "1.1.0" prettytable = "0.10.0" textwrap = "0.16.1" -near-ledger = { version = "0.4.0", optional = true } +near-ledger = { version = "0.5.0", optional = true } near-crypto = "0.20.1" near-primitives = "0.20.1" diff --git a/src/common.rs b/src/common.rs index 1c025bf0b..486097da8 100644 --- a/src/common.rs +++ b/src/common.rs @@ -563,8 +563,13 @@ pub fn print_unsigned_transaction(transaction: &crate::commands::PrepopulatedTra "--", "create account:", &transaction.receiver_id ) } - near_primitives::transaction::Action::DeployContract(_) => { - eprintln!("{:>5} {:<20}", "--", "deploy contract") + near_primitives::transaction::Action::DeployContract(code) => { + let code_hash = CryptoHash::hash_bytes(&code.code); + eprintln!( + "{:>5} {:<70}", + "--", + format!("deploy contract {:?}", code_hash) + ) } near_primitives::transaction::Action::FunctionCall(function_call_action) => { eprintln!("{:>5} {:<20}", "--", "function call:"); diff --git a/src/transaction_signature_options/sign_with_ledger/mod.rs b/src/transaction_signature_options/sign_with_ledger/mod.rs index a332e8bf3..02ee9b87c 100644 --- a/src/transaction_signature_options/sign_with_ledger/mod.rs +++ b/src/transaction_signature_options/sign_with_ledger/mod.rs @@ -1,11 +1,17 @@ use color_eyre::eyre::{ContextCompat, WrapErr}; -use inquire::{CustomType, Select}; +use inquire::CustomType; +use near_ledger::NEARLedgerError; use near_primitives::borsh; -use slip10::BIP32Path; use crate::common::JsonRpcClientExt; use crate::common::RpcQueryResponseExt; +const SW_BUFFER_OVERFLOW: &str = "0x6990"; +const ERR_OVERFLOW_MEMO: &str = "Buffer overflow on Ledger device occured. \ +Transaction is too large for signature. \ +This is resolved in https://github.com/dj8yfo/app-near-rs . \ +The status is tracked in `About` section."; + #[derive(Debug, Clone, interactive_clap::InteractiveClap)] #[interactive_clap(input_context = crate::commands::TransactionContext)] #[interactive_clap(output_context = SignLedgerContext)] @@ -37,77 +43,8 @@ pub struct SignLedgerContext { on_after_sending_transaction_callback: crate::transaction_signature_options::OnAfterSendingTransactionCallback, } -const BLIND_SIGN_MEMO: &str = "Blind signature means that transaction is prepared by CLI, but cannot be reviewed on the Ledger device. \ - In order to be absolutely sure that the transaction you are signing is not forged, take the constructed transaction, \ - verify its content using NEAR CLI on another host or use any other tool capable of displaying unsigned NEAR transactions, \ - and confirm that the SHA256 hash matches the one displayed above and another identical one, that will be displayed on your Ledger device after confirming the prompt. \ - Following helper command on NEAR CLI can be used:"; impl SignLedgerContext { - fn input_blind_agree() -> color_eyre::eyre::Result { - let options: Vec<&str> = vec!["Yes", "No"]; - - Ok( - Select::new("Do you agree to continue with blind signature? ", options) - .prompt() - .map(|selected| selected == "Yes")?, - ) - } - - fn blind_sign_subflow( - hash: near_primitives::hash::CryptoHash, - hd_path: BIP32Path, - unsigned_transaction: near_primitives::transaction::Transaction, - ) -> color_eyre::eyre::Result { - eprintln!("\n\nBuffer overflow on Ledger device occured. Transaction is too large for normal signature."); - eprintln!("\nThe following is Base58-encoded SHA-256 hash of unsigned transaction:"); - eprintln!("{}", hash); - - eprintln!( - "\nUnsigned transaction (serialized as base64):\n{}\n", - crate::types::transaction::TransactionAsBase64::from(unsigned_transaction) - ); - eprintln!("{}", BLIND_SIGN_MEMO); - eprintln!( - "$ {} transaction print-transaction unsigned\n\n", - crate::common::get_near_exec_path() - ); - - eprintln!("Make sure to enable blind sign in NEAR app's settings on Ledger device\n"); - let agree = Self::input_blind_agree()?; - if agree { - eprintln!( - "Confirm transaction blind signing on your Ledger device (HD Path: {})", - hd_path, - ); - let result = near_ledger::blind_sign_transaction(hash, hd_path); - let signature = result.map_err(|err| { - match err { - near_ledger::NEARLedgerError::BlindSignatureDisabled => { - color_eyre::Report::msg("Blind signature is disabled in NEAR app's settings on Ledger device".to_string()) - }, - near_ledger::NEARLedgerError::BlindSignatureNotSupported => { - color_eyre::Report::msg("Blind signature is not supported by the version of NEAR app installed on Ledger device. \ - Version of the app with the feature available is tracked in https://github.com/LedgerHQ/app-near/pull/32".to_string()) - }, - err => { - color_eyre::Report::msg(format!( - "Error occurred while signing the transaction: {:?}", - err - )) - } - } - })?; - let signature = - near_crypto::Signature::from_parts(near_crypto::KeyType::ED25519, &signature) - .wrap_err("Signature is not expected to fail on deserialization")?; - - Ok(signature) - } else { - Err(color_eyre::Report::msg("signing with ledger aborted")) - } - } - pub fn from_previous_context( previous_context: crate::commands::TransactionContext, scope: &::InteractiveClapContextScope, @@ -170,12 +107,8 @@ impl SignLedgerContext { near_crypto::Signature::from_parts(near_crypto::KeyType::ED25519, &signature) .wrap_err("Signature is not expected to fail on deserialization")? } - Err(near_ledger::NEARLedgerError::BufferOverflow { transaction_hash }) => { - Self::blind_sign_subflow( - transaction_hash, - seed_phrase_hd_path, - unsigned_transaction.clone(), - )? + Err(NEARLedgerError::APDUExchangeError(msg)) if msg.contains(SW_BUFFER_OVERFLOW) => { + return Err(color_eyre::Report::msg(ERR_OVERFLOW_MEMO)); } Err(near_ledger_error) => { return Err(color_eyre::Report::msg(format!(