Skip to content

Commit 523309e

Browse files
authored
Run tx simulation in restore command (#2146)
* Run tx simulation in restore command Restore command currently fails to execute, since the transaction never gets simulated. closes #2145 * Correctly read the returned meta of restore transaction * parse the changes instead of the operation before function returns * expect success in restore cookbook files * Revert "expect success in restore cookbook files" This reverts commit 6dfa531.
1 parent 3d2c261 commit 523309e

File tree

1 file changed

+56
-27
lines changed

1 file changed

+56
-27
lines changed

cmd/soroban-cli/src/commands/contract/restore.rs

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ use crate::{
44
log::extract_events,
55
xdr::{
66
Error as XdrError, ExtensionPoint, LedgerEntry, LedgerEntryChange, LedgerEntryData,
7-
LedgerFootprint, Limits, Memo, Operation, OperationBody, OperationMeta, Preconditions,
8-
RestoreFootprintOp, SequenceNumber, SorobanResources, SorobanTransactionData,
9-
SorobanTransactionDataExt, Transaction, TransactionExt, TransactionMeta, TransactionMetaV3,
7+
LedgerFootprint, Limits, Memo, Operation, OperationBody, Preconditions, RestoreFootprintOp,
8+
SequenceNumber, SorobanResources, SorobanTransactionData, SorobanTransactionDataExt,
9+
Transaction, TransactionExt, TransactionMeta, TransactionMetaV3, TransactionMetaV4,
1010
TtlEntry, WriteXdr,
1111
},
1212
};
1313
use clap::{command, Parser};
1414
use stellar_strkey::DecodeError;
1515

1616
use crate::{
17+
assembled::simulate_and_assemble_transaction,
1718
commands::{
1819
contract::extend,
1920
global,
@@ -164,7 +165,7 @@ impl NetworkRunnable for Cmd {
164165
resources: SorobanResources {
165166
footprint: LedgerFootprint {
166167
read_only: vec![].try_into()?,
167-
read_write: entry_keys.try_into()?,
168+
read_write: entry_keys.clone().try_into()?,
168169
},
169170
instructions: self.fee.instructions.unwrap_or_default(),
170171
disk_read_bytes: 0,
@@ -176,8 +177,12 @@ impl NetworkRunnable for Cmd {
176177
if self.fee.build_only {
177178
return Ok(TxnResult::Txn(tx));
178179
}
180+
let tx = simulate_and_assemble_transaction(&client, &tx)
181+
.await?
182+
.transaction()
183+
.clone();
179184
let res = client
180-
.send_transaction_polling(&config.sign(*tx).await?)
185+
.send_transaction_polling(&config.sign(tx).await?)
181186
.await?;
182187
if args.is_none_or(|a| !a.no_cache) {
183188
data::write(res.clone().try_into()?, &network.rpc_uri()?)?;
@@ -196,33 +201,57 @@ impl NetworkRunnable for Cmd {
196201

197202
// The transaction from core will succeed regardless of whether it actually found &
198203
// restored the entry, so we have to inspect the result meta to tell if it worked or not.
199-
let TransactionMeta::V3(TransactionMetaV3 { operations, .. }) = meta else {
200-
return Err(Error::LedgerEntryNotFound);
204+
let changes = match meta {
205+
TransactionMeta::V4(TransactionMetaV4 { operations, .. }) => {
206+
// Simply check if there is exactly one entry here. We only support restoring a single
207+
// entry via this command (which we should fix separately, but).
208+
if operations.is_empty() {
209+
return Err(Error::LedgerEntryNotFound);
210+
}
211+
212+
operations[0].changes.clone()
213+
}
214+
TransactionMeta::V3(TransactionMetaV3 { operations, .. }) => {
215+
// Simply check if there is exactly one entry here. We only support restoring a single
216+
// entry via this command (which we should fix separately, but).
217+
if operations.is_empty() {
218+
return Err(Error::LedgerEntryNotFound);
219+
}
220+
221+
operations[0].changes.clone()
222+
}
223+
_ => return Err(Error::LedgerEntryNotFound),
201224
};
202-
tracing::debug!("Operations:\nlen:{}\n{operations:#?}", operations.len());
225+
tracing::debug!("Changes:\nlen:{}\n{changes:#?}", changes.len());
203226

204-
// Simply check if there is exactly one entry here. We only support extending a single
205-
// entry via this command (which we should fix separately, but).
206-
if operations.is_empty() {
207-
return Err(Error::LedgerEntryNotFound);
208-
}
227+
if changes.is_empty() {
228+
let entry = client.get_full_ledger_entries(&entry_keys).await?;
229+
let extension = entry.entries[0].live_until_ledger_seq;
209230

210-
if operations.len() != 1 {
211-
tracing::warn!(
212-
"Unexpected number of operations: {}. Currently only handle one.",
213-
operations[0].changes.len()
214-
);
231+
if entry.latest_ledger < i64::from(extension) {
232+
return Ok(TxnResult::Res(extension));
233+
}
215234
}
235+
216236
Ok(TxnResult::Res(
217-
parse_operations(&operations.to_vec()).ok_or(Error::MissingOperationResult)?,
237+
parse_changes(&changes.to_vec()).ok_or(Error::LedgerEntryNotFound)?,
218238
))
219239
}
220240
}
221241

222-
fn parse_operations(ops: &[OperationMeta]) -> Option<u32> {
223-
ops.first().and_then(|op| {
224-
op.changes.iter().find_map(|entry| match entry {
225-
LedgerEntryChange::Updated(LedgerEntry {
242+
fn parse_changes(changes: &[LedgerEntryChange]) -> Option<u32> {
243+
match (&changes[0], &changes[1]) {
244+
(
245+
LedgerEntryChange::State(_),
246+
LedgerEntryChange::Restored(LedgerEntry {
247+
data:
248+
LedgerEntryData::Ttl(TtlEntry {
249+
live_until_ledger_seq,
250+
..
251+
}),
252+
..
253+
})
254+
| LedgerEntryChange::Updated(LedgerEntry {
226255
data:
227256
LedgerEntryData::Ttl(TtlEntry {
228257
live_until_ledger_seq,
@@ -237,8 +266,8 @@ fn parse_operations(ops: &[OperationMeta]) -> Option<u32> {
237266
..
238267
}),
239268
..
240-
}) => Some(*live_until_ledger_seq),
241-
_ => None,
242-
})
243-
})
269+
}),
270+
) => Some(*live_until_ledger_seq),
271+
_ => None,
272+
}
244273
}

0 commit comments

Comments
 (0)