Skip to content

Commit

Permalink
fix: add max bump and return current expiration if bump is too small
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal committed Sep 21, 2023
1 parent 11349bf commit 694d68d
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 115 deletions.
3 changes: 2 additions & 1 deletion cmd/crates/soroban-spec-tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,7 @@ pub fn to_string(v: &ScVal) -> Result<String, Error> {
ScVal::Symbol(v) => std::str::from_utf8(v.as_slice())
.map_err(|_| Error::InvalidValue(Some(ScType::Symbol)))?
.to_string(),
ScVal::LedgerKeyContractInstance => "LedgerKeyContractInstance".to_string(),
_ => serde_json::to_string(&to_json(v)?)?,
})
}
Expand All @@ -918,7 +919,7 @@ pub fn to_json(v: &ScVal) -> Result<Value, Error> {
let val: Value = match v {
ScVal::Bool(b) => Value::Bool(*b),
ScVal::Void => Value::Null,
ScVal::LedgerKeyContractInstance => return Err(Error::InvalidValue(None)),
ScVal::LedgerKeyContractInstance => Value::String("LedgerKeyContractInstance".to_string()),
ScVal::U64(v) => Value::Number(serde_json::Number::from(*v)),
ScVal::Timepoint(tp) => Value::Number(serde_json::Number::from(tp.0)),
ScVal::Duration(d) => Value::Number(serde_json::Number::from(d.0)),
Expand Down
54 changes: 32 additions & 22 deletions cmd/soroban-cli/src/commands/contract/bump.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,38 @@
use std::{
fmt::Debug,
path::{Path},
str::FromStr,
};
use std::{fmt::Debug, path::Path, str::FromStr};

use clap::{command, Parser};
use soroban_env_host::xdr::{
BumpFootprintExpirationOp, Error as XdrError, ExpirationEntry, ExtensionPoint,
LedgerEntry, LedgerEntryChange, LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation, OperationBody,
Preconditions, SequenceNumber, SorobanResources,
SorobanTransactionData, Transaction, TransactionExt, TransactionMeta, TransactionMetaV3,
Uint256,
BumpFootprintExpirationOp, Error as XdrError, ExpirationEntry, ExtensionPoint, LedgerEntry,
LedgerEntryChange, LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation,
OperationBody, Preconditions, SequenceNumber, SorobanResources, SorobanTransactionData,
Transaction, TransactionExt, TransactionMeta, TransactionMetaV3, Uint256,
};


use crate::{
commands::config,
rpc::{self, Client}, wasm, Pwd, key,
key,
rpc::{self, Client},
wasm, Pwd,
};

const MAX_LEDGERS_TO_EXPIRE: u32 = 535_679;

#[derive(Parser, Debug, Clone)]
#[group(skip)]
pub struct Cmd {

/// Number of ledgers to extend the entries
#[arg(long, required = true)]
ledgers_to_expire: u32,
pub ledgers_to_expire: u32,

/// Only print the new expiration ledger
#[arg(long)]
expiration_ledger_only: bool,
pub expiration_ledger_only: bool,

#[command(flatten)]
pub key: key::Args,

#[command(flatten)]
config: config::Args,
pub config: config::Args,
#[command(flatten)]
pub fee: crate::fee::Args,
}
Expand Down Expand Up @@ -100,13 +97,24 @@ impl Cmd {
Ok(())
}

fn ledgers_to_expire(&self) -> u32 {
let res = u32::min(self.ledgers_to_expire, MAX_LEDGERS_TO_EXPIRE);
if res < self.ledgers_to_expire {
tracing::warn!(
"Ledgers to expire is too large, using max value of {MAX_LEDGERS_TO_EXPIRE}"
);
}
res
}

async fn run_against_rpc_server(&self) -> Result<u32, Error> {
let network = self.config.get_network()?;
tracing::trace!(?network);
let keys = self.key.parse_keys()?;
let network = &self.config.get_network()?;
let client = Client::new(&network.rpc_url)?;
let key = self.config.key_pair()?;
let ledgers_to_expire = self.ledgers_to_expire();

// Get the account sequence number
let public_strkey = stellar_strkey::ed25519::PublicKey(key.public.to_bytes()).to_string();
Expand All @@ -123,15 +131,15 @@ impl Cmd {
source_account: None,
body: OperationBody::BumpFootprintExpiration(BumpFootprintExpirationOp {
ext: ExtensionPoint::V0,
ledgers_to_expire: self.ledgers_to_expire,
ledgers_to_expire,
}),
}]
.try_into()?,
ext: TransactionExt::V1(SorobanTransactionData {
ext: ExtensionPoint::V0,
resources: SorobanResources {
footprint: LedgerFootprint {
read_only: keys.try_into()?,
read_only: keys.clone().try_into()?,
read_write: vec![].try_into()?,
},
instructions: 0,
Expand Down Expand Up @@ -164,8 +172,12 @@ impl Cmd {
return Err(Error::LedgerEntryNotFound);
}

if operations[0].changes.len() != 2 {
return Err(Error::LedgerEntryNotFound);
if operations[0].changes.is_empty() {
let entry = client.get_full_ledger_entries(&keys).await?;
let expire = entry.entries[0].expiration.expiration_ledger_seq;
if entry.latest_ledger + i64::from(ledgers_to_expire) < i64::from(expire) {
return Ok(expire);
}
}

match (&operations[0].changes[0], &operations[0].changes[1]) {
Expand Down Expand Up @@ -226,5 +238,3 @@ impl Cmd {
Ok(new_expiration_ledger_seq)
}
}


1 change: 1 addition & 0 deletions cmd/soroban-cli/src/commands/contract/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ impl Cmd {
},
config: self.config.clone(),
fee: self.fee.clone(),
ledgers_to_expire: None,
}
.run_against_rpc_server()
.await?;
Expand Down
123 changes: 69 additions & 54 deletions cmd/soroban-cli/src/commands/contract/read.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use std::{
convert::Into,
fmt::Debug,
io::{self},
io::{self, stdout},
};

use clap::{command, Parser, ValueEnum};
use sha2::{Digest, Sha256};
use soroban_env_host::{
xdr::{
Error as XdrError, ExpirationEntry, Hash, ScVal, WriteXdr,
ContractDataEntry, Error as XdrError, ExpirationEntry, Hash, LedgerEntryData, LedgerKey,
LedgerKeyContractData, ScVal, WriteXdr,
},
HostError,
};
Expand Down Expand Up @@ -85,6 +86,8 @@ pub enum Error {
NoContractDataEntryFoundForContractID,
#[error(transparent)]
Key(#[from] key::Error),
#[error("Only contract data and code keys are allowed")]
OnlyDataAllowed,
}

impl Cmd {
Expand All @@ -103,8 +106,7 @@ impl Cmd {
let network = &self.config.get_network()?;
let client = Client::new(&network.rpc_url)?;
let keys = self.key.parse_keys()?;
tracing::trace!("{keys:#?}");
Ok(client.get_full_ledger_entries(keys.as_slice()).await?)
Ok(client.get_full_ledger_entries(&keys).await?)
}

#[allow(clippy::too_many_lines)]
Expand Down Expand Up @@ -134,57 +136,70 @@ impl Cmd {
})
}

fn output_entries(&self, raw_entries: &FullLedgerEntries) -> Result<(), Error> {
println!("{raw_entries:#?}");
// let entries = raw_entries
// .iter()
// .filter_map(|(_k, data)| {
// if let LedgerEntryData::ContractData(ContractDataEntry { key, val, .. }) = &data {
// Some((key.clone(), val.clone()))
// } else {
// None
// }
// })
// .collect::<Vec<_>>();
fn output_entries(&self, entries: &FullLedgerEntries) -> Result<(), Error> {
if entries.entries.is_empty() {
return Err(Error::NoContractDataEntryFoundForContractID);
}
tracing::trace!("{entries:#?}");
let mut out = csv::Writer::from_writer(stdout());
for FullLedgerEntry {
key,
val,
expiration,
} in &entries.entries
{
let (
LedgerKey::ContractData(LedgerKeyContractData { key, .. }),
LedgerEntryData::ContractData(ContractDataEntry { val, .. }),
) = (key, val)
else {
return Err(Error::OnlyDataAllowed);
};
let expiration = expiration.expiration_ledger_seq;

// if entries.is_empty() {
// return Err(Error::NoContractDataEntryFoundForContractID);
// }

// let mut out = csv::Writer::from_writer(stdout());
// for (key, val) in entries {
// let output = match self.output {
// Output::String => [
// soroban_spec_tools::to_string(&key).map_err(|e| Error::CannotPrintResult {
// result: key.clone(),
// error: e,
// })?,
// soroban_spec_tools::to_string(&val).map_err(|e| Error::CannotPrintResult {
// result: val.clone(),
// error: e,
// })?,
// ],
// Output::Json => [
// serde_json::to_string_pretty(&key).map_err(|e| {
// Error::CannotPrintJsonResult {
// result: key.clone(),
// error: e,
// }
// })?,
// serde_json::to_string_pretty(&val).map_err(|e| {
// Error::CannotPrintJsonResult {
// result: val.clone(),
// error: e,
// }
// })?,
// ],
// Output::Xdr => [key.to_xdr_base64()?, val.to_xdr_base64()?],
// };
// out.write_record(output)
// .map_err(|e| Error::CannotPrintAsCsv { error: e })?;
// }
// out.flush()
// .map_err(|e| Error::CannotPrintFlush { error: e })?;
let output = match self.output {
Output::String => [
soroban_spec_tools::to_string(key).map_err(|e| Error::CannotPrintResult {
result: key.clone(),
error: e,
})?,
soroban_spec_tools::to_string(val).map_err(|e| Error::CannotPrintResult {
result: val.clone(),
error: e,
})?,
expiration.to_string(),
],
Output::Json => [
serde_json::to_string_pretty(&key).map_err(|error| {
Error::CannotPrintJsonResult {
result: key.clone(),
error,
}
})?,
serde_json::to_string_pretty(&val).map_err(|error| {
Error::CannotPrintJsonResult {
result: val.clone(),
error,
}
})?,
serde_json::to_string_pretty(&expiration).map_err(|error| {
Error::CannotPrintJsonResult {
result: val.clone(),
error,
}
})?,
],
Output::Xdr => [
key.to_xdr_base64()?,
val.to_xdr_base64()?,
expiration.to_xdr_base64()?,
],
};
out.write_record(output)
.map_err(|e| Error::CannotPrintAsCsv { error: e })?;
}
out.flush()
.map_err(|e| Error::CannotPrintFlush { error: e })?;
Ok(())
}
}
36 changes: 28 additions & 8 deletions cmd/soroban-cli/src/commands/contract/restore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,31 @@ use std::{fmt::Debug, path::Path, str::FromStr};

use clap::{command, Parser};
use soroban_env_host::xdr::{
Error as XdrError, ExpirationEntry, ExtensionPoint, LedgerEntry,
LedgerEntryChange, LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation, OperationBody, OperationMeta,
Preconditions, RestoreFootprintOp, SequenceNumber,
SorobanResources, SorobanTransactionData, Transaction, TransactionExt, TransactionMeta,
TransactionMetaV3, Uint256,
Error as XdrError, ExpirationEntry, ExtensionPoint, LedgerEntry, LedgerEntryChange,
LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation, OperationBody, OperationMeta,
Preconditions, RestoreFootprintOp, SequenceNumber, SorobanResources, SorobanTransactionData,
Transaction, TransactionExt, TransactionMeta, TransactionMetaV3, Uint256,
};
use stellar_strkey::DecodeError;

use crate::{
commands::config::{self, locator},
commands::{
config::{self, locator},
contract::bump,
},
key,
rpc::{self, Client}, wasm, Pwd,
rpc::{self, Client},
wasm, Pwd,
};

#[derive(Parser, Debug, Clone)]
#[group(skip)]
pub struct Cmd {
#[command(flatten)]
pub key: key::Args,
/// Number of ledgers to extend the entry
#[arg(long)]
pub ledgers_to_expire: Option<u32>,
#[command(flatten)]
pub config: config::Args,
#[command(flatten)]
Expand Down Expand Up @@ -71,6 +77,8 @@ pub enum Error {
Wasm(#[from] wasm::Error),
#[error(transparent)]
Key(#[from] key::Error),
#[error(transparent)]
Bump(#[from] bump::Error),
}

impl Cmd {
Expand All @@ -82,7 +90,19 @@ impl Cmd {
self.run_against_rpc_server().await?
};

println!("New expiration ledger: {expiration_ledger_seq}");
if let Some(ledgers_to_expire) = self.ledgers_to_expire {
bump::Cmd {
key: self.key.clone(),
ledgers_to_expire,
config: self.config.clone(),
fee: self.fee.clone(),
expiration_ledger_only: false,
}
.run()
.await?;
} else {
println!("New expiration ledger: {expiration_ledger_seq}");
}

Ok(())
}
Expand Down
7 changes: 2 additions & 5 deletions cmd/soroban-cli/src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ use clap::arg;
use soroban_env_host::xdr::{
self, LedgerKey, LedgerKeyContractCode, LedgerKeyContractData, ReadXdr, ScAddress, ScVal,
};
use std::{
path::{PathBuf},
};
use std::path::PathBuf;

use crate::{
commands::contract::Durability,
Expand Down Expand Up @@ -65,7 +63,6 @@ pub struct Args {
}

impl Args {

pub fn parse_keys(&self) -> Result<Vec<LedgerKey>, Error> {
let keys = if let Some(keys) = &self.key {
keys.iter()
Expand All @@ -78,7 +75,7 @@ impl Args {
.collect::<Result<Vec<_>, Error>>()?
} else if let Some(keys) = &self.key_xdr {
keys.iter()
.map(|s|Ok(ScVal::from_xdr_base64(s)?))
.map(|s| Ok(ScVal::from_xdr_base64(s)?))
.collect::<Result<Vec<_>, Error>>()?
} else if let Some(wasm) = &self.wasm {
return Ok(vec![crate::wasm::Args { wasm: wasm.clone() }.try_into()?]);
Expand Down
Loading

0 comments on commit 694d68d

Please sign in to comment.