Merge branch 'staging' into grim

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	api/Cargo.toml
#	api/src/foreign.rs
#	config/Cargo.toml
#	controller/Cargo.toml
#	impls/Cargo.toml
#	libwallet/Cargo.toml
#	libwallet/src/api_impl/owner.rs
#	libwallet/src/backend.rs
#	libwallet/src/internal/updater.rs
#	libwallet/src/types.rs
#	util/Cargo.toml
This commit is contained in:
ardocrat
2026-06-11 10:14:04 +03:00
18 changed files with 384 additions and 320 deletions
Generated
+8
View File
@@ -1279,6 +1279,7 @@ dependencies = [
[[package]]
name = "grin_api"
version = "5.4.0"
source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f"
dependencies = [
"async-stream",
"bytes 1.11.1",
@@ -1312,6 +1313,7 @@ dependencies = [
[[package]]
name = "grin_chain"
version = "5.4.0"
source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f"
dependencies = [
"bit-vec",
"bitflags 1.3.2",
@@ -1334,6 +1336,7 @@ dependencies = [
[[package]]
name = "grin_core"
version = "5.4.0"
source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f"
dependencies = [
"blake2-rfc",
"byteorder",
@@ -1359,6 +1362,7 @@ dependencies = [
[[package]]
name = "grin_keychain"
version = "5.4.0"
source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f"
dependencies = [
"blake2-rfc",
"byteorder",
@@ -1380,6 +1384,7 @@ dependencies = [
[[package]]
name = "grin_p2p"
version = "5.4.0"
source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f"
dependencies = [
"bitflags 1.3.2",
"built",
@@ -1402,6 +1407,7 @@ dependencies = [
[[package]]
name = "grin_pool"
version = "5.4.0"
source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f"
dependencies = [
"blake2-rfc",
"chrono",
@@ -1433,6 +1439,7 @@ dependencies = [
[[package]]
name = "grin_store"
version = "5.4.0"
source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f"
dependencies = [
"byteorder",
"croaring",
@@ -1451,6 +1458,7 @@ dependencies = [
[[package]]
name = "grin_util"
version = "5.4.0"
source = "git+https://github.com/mimblewimble/grin?rev=cf2ed3f3becd62b5e754ec964fd90e332b9a021f#cf2ed3f3becd62b5e754ec964fd90e332b9a021f"
dependencies = [
"anyhow",
"backtrace",
+5 -11
View File
@@ -54,10 +54,10 @@ grin_wallet_util = { path = "./util", version = "5.4.0-alpha.1" }
# grin_api = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" }
# For bleeding edge
#grin_core = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_util = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_api = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_api = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
# For local testing
# grin_core = { path = "../grin/core"}
@@ -65,13 +65,7 @@ grin_wallet_util = { path = "./util", version = "5.4.0-alpha.1" }
# grin_util = { path = "../grin/util"}
# grin_api = { path = "../grin/api"}
# Grim monorepo
grin_core = { path = "../node/core"}
grin_keychain = { path = "../node/keychain"}
grin_util = { path = "../node/util"}
grin_api = { path = "../node/api"}
######
######
[build-dependencies]
built = { version = "0.8.0", features = ["git2"]}
+3 -8
View File
@@ -41,20 +41,15 @@ grin_wallet_util = { path = "../util", version = "5.4.0-alpha.1" }
# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" }
# For bleeding edge
#grin_core = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_util = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
# For local testing
# grin_core = { path = "../../grin/core"}
# grin_keychain = { path = "../../grin/keychain"}
# grin_util = { path = "../../grin/util"}
# Monorepo deps
grin_core = { path = "../../node/core"}
grin_keychain = { path = "../../node/keychain"}
grin_util = { path = "../../node/util"}
#####
[dev-dependencies]
+3 -8
View File
@@ -380,8 +380,8 @@ where
self.doctest_mode,
);
match res {
Ok(s) => return Ok(s.unwrap()),
Err(_) => return Ok(ret_slate),
Ok(s) => Ok(s.unwrap()),
Err(_) => Ok(ret_slate),
}
}
None => Ok(ret_slate),
@@ -443,12 +443,7 @@ where
true => false,
false => post_automatically,
};
foreign::finalize_tx(
w,
(&self.keychain_mask).as_ref(),
slate,
post_automatically,
)
foreign::finalize_tx(w, (&self.keychain_mask).as_ref(), slate, post_automatically)
}
}
+4
View File
@@ -272,6 +272,7 @@ pub trait OwnerRpc {
"stored_tx": null,
"ttl_cutoff_height": null,
"tx_slate_id": null,
"tx_slate_state": null,
"payment_proof": null,
"reverted_after": null,
"tx_type": "ConfirmedCoinbase"
@@ -294,6 +295,7 @@ pub trait OwnerRpc {
"payment_proof": null,
"reverted_after": null,
"tx_slate_id": null,
"tx_slate_state": null,
"tx_type": "ConfirmedCoinbase"
}
]
@@ -363,6 +365,7 @@ pub trait OwnerRpc {
"stored_tx": null,
"ttl_cutoff_height": null,
"tx_slate_id": null,
"tx_slate_state": null,
"payment_proof": null,
"reverted_after": null,
"tx_type": "ConfirmedCoinbase"
@@ -385,6 +388,7 @@ pub trait OwnerRpc {
"payment_proof": null,
"reverted_after": null,
"tx_slate_id": null,
"tx_slate_state": null,
"tx_type": "ConfirmedCoinbase"
}
]
+2 -6
View File
@@ -30,17 +30,13 @@ grin_wallet_util = { path = "../util", version = "5.4.0-alpha.1" }
#grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" }
# For bleeding edge
#grin_core = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_util = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
# For local testing
# grin_core = { path = "../../grin/core"}
# grin_util = { path = "../../grin/util"}
# Monorepo deps
grin_core = { path = "../../node/core"}
grin_util = { path = "../../node/util"}
#####
[dev-dependencies]
+6 -13
View File
@@ -8,7 +8,7 @@ repository = "https://github.com/mimblewimble/grin-wallet"
keywords = [ "crypto", "grin", "mimblewimble" ]
exclude = ["**/*.grin", "**/*.grin2"]
#build = "src/build/build.rs"
edition = "2018"
edition = "2021"
[dependencies]
futures = "0.3"
@@ -54,11 +54,11 @@ grin_wallet_config = { path = "../config", version = "5.4.0-alpha.1" }
# grin_chain = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" }
# For bleeding edge
#grin_core = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_util = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_api = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_chain = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_api = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_chain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
# For local testing
# grin_core = { path = "../../grin/core"}
@@ -67,13 +67,6 @@ grin_wallet_config = { path = "../config", version = "5.4.0-alpha.1" }
# grin_api = { path = "../../grin/api"}
# grin_chain = { path = "../../grin/chain"}
# Monorepo deps
grin_core = { path = "../../node/core"}
grin_keychain = { path = "../../node/keychain"}
grin_util = { path = "../../node/util"}
grin_api = { path = "../../node/api"}
grin_chain = { path = "../../node/chain"}
#####
[dev-dependencies]
+6
View File
@@ -152,6 +152,7 @@ pub fn txs(
table.set_titles(row![
bMG->"Id",
bMG->"Type",
bMG->"State",
bMG->"Shared Transaction Id",
bMG->"Creation Time",
bMG->"TTL Cutoff Height",
@@ -174,6 +175,10 @@ pub fn txs(
Some(m) => format!("{}", m),
None => "None".to_owned(),
};
let slate_state = match t.tx_slate_state.as_ref() {
Some(m) => format!("{}", m),
None => "None".to_owned(),
};
let entry_type = format!("{}", t.tx_type);
let creation_ts = format!("{}", t.creation_ts.format("%Y-%m-%d %H:%M:%S"));
let ttl_cutoff_height = match t.ttl_cutoff_height {
@@ -220,6 +225,7 @@ pub fn txs(
table.add_row(row![
bFC->id,
bFC->entry_type,
bFC->slate_state,
bFC->slate_id,
bFB->creation_ts,
bFB->ttl_cutoff_height,
+6 -14
View File
@@ -60,12 +60,12 @@ grin_wallet_libwallet = { path = "../libwallet", version = "5.4.0-alpha.1" }
# grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" }
# For bleeding edge
#grin_core = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_chain = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_util = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_api = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
#grin_store = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_chain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_api = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_store = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
# For local testing
# grin_core = { path = "../../grin/core"}
@@ -75,14 +75,6 @@ grin_wallet_libwallet = { path = "../libwallet", version = "5.4.0-alpha.1" }
# grin_api = { path = "../../grin/api"}
# grin_store = { path = "../../grin/store"}
# Monorepo deps
grin_core = { path = "../../node/core"}
grin_keychain = { path = "../../node/keychain"}
grin_chain = { path = "../../node/chain"}
grin_util = { path = "../../node/util"}
grin_api = { path = "../../node/api"}
grin_store = { path = "../../node/store"}
#####
[dev-dependencies]
+5 -11
View File
@@ -8,7 +8,7 @@ repository = "https://github.com/mimblewimble/grin-wallet"
keywords = [ "crypto", "grin", "mimblewimble" ]
exclude = ["**/*.grin", "**/*.grin2"]
#build = "src/build/build.rs"
edition = "2018"
edition = "2021"
[dependencies]
blake2-rfc = "0.2"
@@ -59,10 +59,10 @@ grin_wallet_config = { path = "../config", version = "5.4.0-alpha.1" }
# grin_store = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" }
# For bleeding edge
# grin_core = { git = "https://github.com/mimblewimble/grin", branch = "master" }
# grin_keychain = { git = "https://github.com/mimblewimble/grin", branch = "master" }
# grin_util = { git = "https://github.com/mimblewimble/grin", branch = "master" }
# grin_store = { git = "https://github.com/mimblewimble/grin", branch = "master" }
grin_core = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_keychain = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
grin_store = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
# For local testing
# grin_core = { path = "../../grin/core"}
@@ -70,10 +70,4 @@ grin_wallet_config = { path = "../config", version = "5.4.0-alpha.1" }
# grin_util = { path = "../../grin/util"}
# grin_store = { path = "../../grin/store"}
# Monorepo deps
grin_core = { path = "../../node/core"}
grin_keychain = { path = "../../node/keychain"}
grin_util = { path = "../../node/util"}
grin_store = { path = "../../node/store"}
#####
+56 -11
View File
@@ -13,6 +13,8 @@
// limitations under the License.
//! Generic implementation of owner API functions
use grin_keychain::Identifier;
use strum::IntoEnumIterator;
use super::owner::tx_lock_outputs;
@@ -48,7 +50,7 @@ where
C: NodeClient,
K: Keychain,
{
updater::build_coinbase(&mut *w, keychain_mask, block_fees, test_mode)
updater::build_coinbase(w, keychain_mask, block_fees, test_mode)
}
/// Receive a tx as recipient
@@ -77,7 +79,7 @@ where
};
// Don't do this multiple times
let tx = updater::retrieve_txs(
&mut *w,
w,
None,
Some(ret_slate.id),
None,
@@ -96,7 +98,7 @@ where
let keychain = w.keychain(keychain_mask)?;
let context = tx::add_output_to_slate(
&mut *w,
w,
keychain_mask,
&mut ret_slate,
height,
@@ -124,7 +126,9 @@ where
ret_slate.amount = 0;
ret_slate.fee_fields = FeeFields::zero();
ret_slate.remove_other_sigdata(&keychain, &context.sec_nonce, &context.sec_key)?;
ret_slate.state = SlateState::Standard2;
update_tx_slate_state(w, keychain_mask, &parent_key_id, &ret_slate)?;
Ok(ret_slate)
}
@@ -150,10 +154,10 @@ where
let mut temp_ctx = context.clone();
temp_ctx.sec_key = context.initial_sec_key.clone();
temp_ctx.sec_nonce = context.initial_sec_nonce.clone();
selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &temp_ctx, false)?;
selection::repopulate_tx(w, keychain_mask, &mut sl, &temp_ctx, false)?;
tx::complete_tx(&mut *w, keychain_mask, &mut sl, &context)?;
tx::update_stored_tx(&mut *w, keychain_mask, &context, &mut sl, true)?;
tx::complete_tx(w, keychain_mask, &mut sl, &context)?;
tx::update_stored_tx(w, keychain_mask, &context, &mut sl, true)?;
{
let mut batch = w.batch(keychain_mask)?;
batch.delete_private_context(sl.id.as_bytes())?;
@@ -161,6 +165,9 @@ where
}
sl.state = SlateState::Invoice3;
sl.amount = 0;
let parent_key_id = w.parent_key_id();
update_tx_slate_state(w, keychain_mask, &parent_key_id, &sl)?;
} else if sl.state == SlateState::Standard2 {
let keychain = w.keychain(keychain_mask)?;
let parent_key_id = w.parent_key_id();
@@ -171,7 +178,7 @@ where
let current_height = w.w2n_client().get_chain_tip()?.0;
let mut temp_sl =
tx::new_tx_slate(&mut *w, context.amount, false, 2, false, args.ttl_blocks)?;
tx::new_tx_slate(w, context.amount, false, 2, false, args.ttl_blocks)?;
let temp_context = selection::build_send_tx(
w,
&keychain,
@@ -207,11 +214,11 @@ where
// Add our contribution to the offset
sl.adjust_offset(&keychain, &context)?;
selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &context, true)?;
selection::repopulate_tx(w, keychain_mask, &mut sl, &context, true)?;
tx::complete_tx(&mut *w, keychain_mask, &mut sl, &context)?;
tx::verify_slate_payment_proof(&mut *w, keychain_mask, &parent_key_id, &context, &sl)?;
tx::update_stored_tx(&mut *w, keychain_mask, &context, &sl, false)?;
tx::complete_tx(w, keychain_mask, &mut sl, &context)?;
tx::verify_slate_payment_proof(w, keychain_mask, &parent_key_id, &context, &sl)?;
tx::update_stored_tx(w, keychain_mask, &context, &sl, false)?;
{
let mut batch = w.batch(keychain_mask)?;
batch.delete_private_context(sl.id.as_bytes())?;
@@ -219,6 +226,8 @@ where
}
sl.state = SlateState::Standard3;
sl.amount = 0;
update_tx_slate_state(w, keychain_mask, &parent_key_id, &sl)?;
} else {
return Err(Error::SlateState);
}
@@ -227,3 +236,39 @@ where
}
Ok(sl)
}
/// Update transaction slate state.
fn update_tx_slate_state<C, K>(
wallet: &mut WalletBackend<C, K>,
keychain_mask: Option<&SecretKey>,
parent_key_id: &Identifier,
slate: &Slate,
) -> Result<(), Error>
where
C: NodeClient,
K: Keychain,
{
let mut bad_records = 0;
let tx = wallet
.tx_log_iter()?
.filter(|tx| {
if tx.is_err() {
bad_records += 1;
}
tx.is_ok()
})
.map(|tx| tx.unwrap())
.find(|tx| tx.tx_slate_id == Some(slate.id));
if let Some(mut tx) = tx {
let mut batch = wallet.batch(keychain_mask)?;
tx.tx_slate_state = Some(slate.state.clone());
batch.save_tx_log_entry(tx.clone(), parent_key_id)?;
batch.commit()?;
} else {
return Err(Error::Backend(format!(
"Tx log entry with slate id {} not found, there are {} bad tx log records",
slate.id, bad_records
)));
}
Ok(())
}
+21 -31
View File
@@ -56,7 +56,7 @@ where
C: NodeClient,
K: Keychain,
{
keys::accounts(&mut *w)
keys::accounts(w)
}
/// new account path
@@ -69,7 +69,7 @@ where
C: NodeClient,
K: Keychain,
{
keys::new_acct_path(&mut *w, keychain_mask, label)
keys::new_acct_path(w, keychain_mask, label)
}
/// set active account
@@ -490,14 +490,7 @@ where
None => w.parent_key_id(),
};
let mut slate = tx::new_tx_slate(
&mut *w,
args.amount,
false,
2,
use_test_rng,
args.ttl_blocks,
)?;
let mut slate = tx::new_tx_slate(w, args.amount, false, 2, use_test_rng, args.ttl_blocks)?;
if let Some(v) = args.target_slate_version {
slate.version_info.version = v;
@@ -507,7 +500,7 @@ where
// back
if let Some(true) = args.estimate_only {
let (total, fee) = tx::estimate_send_tx(
&mut *w,
w,
keychain_mask,
args.amount,
args.amount_includes_fee.unwrap_or(false),
@@ -525,7 +518,7 @@ where
let height = w.w2n_client().get_chain_tip()?.0;
let mut context = if args.late_lock.unwrap_or(false) {
tx::create_late_lock_context(
&mut *w,
w,
keychain_mask,
&mut slate,
height,
@@ -535,7 +528,7 @@ where
)?
} else {
tx::add_inputs_to_slate(
&mut *w,
w,
keychain_mask,
&mut slate,
height,
@@ -605,10 +598,10 @@ where
None => w.parent_key_id(),
};
let mut slate = tx::new_tx_slate(&mut *w, args.amount, true, 2, use_test_rng, None)?;
let mut slate = tx::new_tx_slate(w, args.amount, true, 2, use_test_rng, None)?;
let height = w.w2n_client().get_chain_tip()?.0;
let context = tx::add_output_to_slate(
&mut *w,
w,
keychain_mask,
&mut slate,
height,
@@ -661,7 +654,7 @@ where
};
// Don't do this multiple times
let tx = updater::retrieve_txs(
&mut *w,
w,
None,
Some(ret_slate.id),
None,
@@ -691,7 +684,7 @@ where
let context_res = w.get_private_context(keychain_mask, slate.id.as_bytes());
let mut context = tx::add_inputs_to_slate(
&mut *w,
w,
keychain_mask,
&mut ret_slate,
height,
@@ -737,7 +730,7 @@ where
}
}
selection::repopulate_tx(&mut *w, keychain_mask, &mut ret_slate, &context, false)?;
selection::repopulate_tx(w, keychain_mask, &mut ret_slate, &context, false)?;
// Save the aggsig context in our DB for when we
// recieve the transaction back
@@ -772,7 +765,7 @@ where
if sl.tx == None {
sl.tx = Some(Slate::empty_transaction());
selection::repopulate_tx(&mut *w, keychain_mask, &mut sl, &context, true)?;
selection::repopulate_tx(w, keychain_mask, &mut sl, &context, true)?;
}
if slate.participant_data.len() == 1 {
@@ -781,14 +774,7 @@ where
}
let height = w.w2n_client().get_chain_tip()?.0;
selection::lock_tx_context(
&mut *w,
keychain_mask,
&sl,
height,
&context,
excess_override,
)
selection::lock_tx_context(w, keychain_mask, &sl, height, &context, excess_override)
}
/// Finalize slate
@@ -845,7 +831,11 @@ where
{
let mut uuid = None;
if let Some(i) = tx_id {
let tx = w.tx_log_iter()?.find(|t| t.id == i);
let tx = w
.tx_log_iter()?
.filter(|tx| tx.is_ok())
.map(|tx| tx.unwrap())
.find(|t| t.id == i);
if let Some(t) = tx {
uuid = t.tx_slate_id;
}
@@ -959,7 +949,7 @@ where
// Scan every 10k heights to save data between batches in case of interruption.
let mut total_pmmr_range = None;
for h in (start_height..tip.0).step_by(10001) {
for h in (start_height..tip.0 + 1).step_by(10001) {
let batch_end_height = cmp::min(tip.0, h + 10000);
let (mut info, range) = scan::scan(
wallet_inst.clone(),
@@ -1134,7 +1124,7 @@ where
// Scan every 10k heights to save data between batches in case of interruption.
let mut total_pmmr_range = None;
for h in (start_height..tip.0).step_by(10001) {
for h in (start_height..tip.0 + 1).step_by(10001) {
let batch_end_height = cmp::min(tip.0, h + 10000);
let (mut info, range) = scan::scan(
wallet_inst.clone(),
@@ -1354,7 +1344,7 @@ where
{
let k = w.keychain(keychain_mask)?;
let key_id = keys::next_available_key(&mut *w, keychain_mask)?;
let key_id = keys::next_available_key(w, keychain_mask)?;
let blind = k.derive_key(amount, &key_id, SwitchCommitmentType::Regular)?;
let commit = k.secp().commit(amount, blind.clone())?;
+32 -46
View File
@@ -321,11 +321,8 @@ where
)
.map_err(From::from)
});
let iter = prefix_iter?
.into_iter()
.filter(|x| x.is_ok())
.map(|x| x.unwrap());
Ok(iter)
let items: Vec<OutputData> = prefix_iter?.collect::<Result<Vec<_>, _>>()?;
Ok(items.into_iter())
}
/// Get an (Optional) tx log entry by uuid.
@@ -336,21 +333,20 @@ where
}
/// Iterate over all tx log data stored by the backend.
pub fn tx_log_iter(&self) -> Result<impl Iterator<Item = TxLogEntry>, Error> {
pub fn tx_log_iter(
&self,
) -> Result<impl Iterator<Item = Result<TxLogEntry, grin_store::Error>>, Error> {
let protocol_version = self.db.protocol_version();
let prefix_iter = self.db.iter(Some(TX_LOG_ENTRY_PREFIX), move |_, mut v| {
ser::deserialize(
&mut v,
protocol_version,
ser::DeserializationMode::default(),
)
self.db
.iter(Some(TX_LOG_ENTRY_PREFIX), move |_, mut v| {
ser::deserialize(
&mut v,
protocol_version,
ser::DeserializationMode::default(),
)
.map_err(From::from)
})
.map_err(From::from)
});
let iter = prefix_iter?
.into_iter()
.filter(|x| x.is_ok())
.map(|x| x.unwrap());
Ok(iter)
}
/// Retrieve the private context associated with a given slate id.
@@ -390,11 +386,8 @@ where
)
.map_err(From::from)
});
let iter = prefix_iter?
.into_iter()
.filter(|x| x.is_ok())
.map(|x| x.unwrap());
Ok(iter)
let items: Vec<AcctPathMapping> = prefix_iter?.collect::<Result<Vec<_>, _>>()?;
Ok(items.into_iter())
}
/// Gets an account path for a given label.
@@ -584,11 +577,8 @@ where
)
.map_err(From::from)
});
let iter = prefix_iter?
.into_iter()
.filter(|x| x.is_ok())
.map(|x| x.unwrap());
Ok(iter)
let items: Vec<OutputData> = prefix_iter?.collect::<Result<Vec<_>, _>>()?;
Ok(items.into_iter())
}
/// Delete data about an output from the backend.
@@ -658,21 +648,20 @@ where
}
/// Iterate over transactions data stored by the backend.
pub fn tx_log_iter(&'a self) -> Result<impl Iterator<Item = TxLogEntry> + 'a, Error> {
pub fn tx_log_iter(
&'a self,
) -> Result<impl Iterator<Item = Result<TxLogEntry, grin_store::Error>> + 'a, Error> {
let protocol_version = self.db.protocol_version();
let prefix_iter = self.db.iter(Some(TX_LOG_ENTRY_PREFIX), move |_, mut v| {
ser::deserialize(
&mut v,
protocol_version,
ser::DeserializationMode::default(),
)
self.db
.iter(Some(TX_LOG_ENTRY_PREFIX), move |_, mut v| {
ser::deserialize(
&mut v,
protocol_version,
ser::DeserializationMode::default(),
)
.map_err(From::from)
})
.map_err(From::from)
});
let iter = prefix_iter?
.into_iter()
.filter(|x| x.is_ok())
.map(|x| x.unwrap());
Ok(iter)
}
/// Save a transaction log entry.
@@ -717,11 +706,8 @@ where
)
.map_err(From::from)
});
let iter = prefix_iter?
.into_iter()
.filter(|x| x.is_ok())
.map(|x| x.unwrap());
Ok(iter)
let items: Vec<AcctPathMapping> = prefix_iter?.collect::<Result<Vec<_>, _>>()?;
Ok(items.into_iter())
}
/// Save an output as locked in the backend.
+2
View File
@@ -157,6 +157,7 @@ where
let log_id = batch.next_tx_log_id(&parent_key_id)?;
let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxSent, log_id);
t.tx_slate_id = Some(slate_id);
t.tx_slate_state = Some(slate.state.clone());
let filename = format!("{}.grintx", slate_id);
t.stored_tx = Some(filename);
t.fee = context.fee;
@@ -281,6 +282,7 @@ where
let log_id = batch.next_tx_log_id(&parent_key_id)?;
let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxReceived, log_id);
t.tx_slate_id = Some(slate_id);
t.tx_slate_state = Some(slate.state.clone());
t.amount_credited = amount;
t.num_outputs = 1;
t.ttl_cutoff_height = match slate.ttl_cutoff_height {
+213 -149
View File
@@ -101,181 +101,190 @@ where
K: Keychain,
{
// Apply simple bool, GTE or LTE fields
let txs_iter: Box<dyn Iterator<Item = TxLogEntry>> = Box::new(
wallet
.tx_log_iter()?
.filter(|tx_entry| match parent_key_id {
Some(k) => tx_entry.parent_key_id == *k,
None => true,
})
.filter(|tx_entry| {
if let Some(v) = query_args.exclude_cancelled {
if v {
tx_entry.tx_type != TxLogEntryType::TxReceivedCancelled
&& tx_entry.tx_type != TxLogEntryType::TxSentCancelled
} else {
true
}
let mut bad_records = 0;
let txs_iter = wallet
.tx_log_iter()?
.filter(|tx| {
if tx.is_err() {
bad_records += 1;
}
tx.is_ok()
})
.map(|tx| tx.unwrap())
.filter(|tx_entry| match parent_key_id {
Some(k) => tx_entry.parent_key_id == *k,
None => true,
})
.filter(|tx_entry| {
if let Some(v) = query_args.exclude_cancelled {
if v {
tx_entry.tx_type != TxLogEntryType::TxReceivedCancelled
&& tx_entry.tx_type != TxLogEntryType::TxSentCancelled
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_outstanding_only {
if v {
!tx_entry.confirmed
} else {
true
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_outstanding_only {
if v {
!tx_entry.confirmed
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_confirmed_only {
if v {
tx_entry.confirmed
} else {
true
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_confirmed_only {
if v {
tx_entry.confirmed
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_sent_only {
if v {
tx_entry.tx_type == TxLogEntryType::TxSent
|| tx_entry.tx_type == TxLogEntryType::TxSentCancelled
} else {
true
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_received_only {
if v {
tx_entry.tx_type == TxLogEntryType::TxReceived
|| tx_entry.tx_type == TxLogEntryType::TxReceivedCancelled
} else {
true
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_coinbase_only {
if v {
tx_entry.tx_type == TxLogEntryType::ConfirmedCoinbase
} else {
true
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_reverted_only {
if v {
tx_entry.tx_type == TxLogEntryType::TxReverted
} else {
true
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_id {
tx_entry.id >= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.max_id {
tx_entry.id <= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_amount {
if tx_entry.tx_type == TxLogEntryType::TxSent
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_sent_only {
if v {
tx_entry.tx_type == TxLogEntryType::TxSent
|| tx_entry.tx_type == TxLogEntryType::TxSentCancelled
{
BigInt::from(tx_entry.amount_debited)
- BigInt::from(tx_entry.amount_credited)
>= BigInt::from(v)
} else {
BigInt::from(tx_entry.amount_credited)
- BigInt::from(tx_entry.amount_debited)
>= BigInt::from(v)
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.max_amount {
if tx_entry.tx_type == TxLogEntryType::TxSent
|| tx_entry.tx_type == TxLogEntryType::TxSentCancelled
{
BigInt::from(tx_entry.amount_debited)
- BigInt::from(tx_entry.amount_credited)
<= BigInt::from(v)
} else {
BigInt::from(tx_entry.amount_credited)
- BigInt::from(tx_entry.amount_debited)
<= BigInt::from(v)
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_received_only {
if v {
tx_entry.tx_type == TxLogEntryType::TxReceived
|| tx_entry.tx_type == TxLogEntryType::TxReceivedCancelled
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_creation_timestamp {
tx_entry.creation_ts >= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_coinbase_only {
if v {
tx_entry.tx_type == TxLogEntryType::ConfirmedCoinbase
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_confirmed_timestamp {
tx_entry.creation_ts <= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.include_reverted_only {
if v {
tx_entry.tx_type == TxLogEntryType::TxReverted
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_confirmed_timestamp {
if let Some(t) = tx_entry.confirmation_ts {
t >= v
} else {
true
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_id {
tx_entry.id >= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.max_id {
tx_entry.id <= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_amount {
if tx_entry.tx_type == TxLogEntryType::TxSent
|| tx_entry.tx_type == TxLogEntryType::TxSentCancelled
{
BigInt::from(tx_entry.amount_debited) - BigInt::from(tx_entry.amount_credited)
>= BigInt::from(v)
} else {
BigInt::from(tx_entry.amount_credited) - BigInt::from(tx_entry.amount_debited)
>= BigInt::from(v)
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.max_amount {
if tx_entry.tx_type == TxLogEntryType::TxSent
|| tx_entry.tx_type == TxLogEntryType::TxSentCancelled
{
BigInt::from(tx_entry.amount_debited) - BigInt::from(tx_entry.amount_credited)
<= BigInt::from(v)
} else {
BigInt::from(tx_entry.amount_credited) - BigInt::from(tx_entry.amount_debited)
<= BigInt::from(v)
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_creation_timestamp {
tx_entry.creation_ts >= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_confirmed_timestamp {
tx_entry.creation_ts <= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.min_confirmed_timestamp {
if let Some(t) = tx_entry.confirmation_ts {
t >= v
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.max_confirmed_timestamp {
if let Some(t) = tx_entry.confirmation_ts {
t <= v
} else {
true
}
} else {
true
}
})
.filter(|tx_entry| {
if let Some(v) = query_args.max_confirmed_timestamp {
if let Some(t) = tx_entry.confirmation_ts {
t <= v
} else {
true
}
}),
);
} else {
true
}
});
// };
//TODO: apply limit + introduce skip before collecting all records.
// Introduce comparator for LMDB to not request all records with limit.
let mut return_txs: Vec<TxLogEntry> = txs_iter.collect();
if bad_records != 0 {
error!("apply_advanced_tx_list_filtering: tx history is missing {} records, cause db read error", bad_records);
}
// Now apply requested sorting
if let Some(ref s) = query_args.sort_field {
match s {
@@ -345,8 +354,16 @@ where
if query_args.is_some() && tx_id.is_none() && tx_slate_id.is_none() {
txs = apply_advanced_tx_list_filtering(wallet, parent_key_id, &query_args.unwrap())?
} else {
let mut bad_records = 0;
txs = wallet
.tx_log_iter()?
.filter(|tx| {
if tx.is_err() {
bad_records += 1;
}
tx.is_ok()
})
.map(|tx| tx.unwrap())
.filter(|tx_entry| {
let f_pk = match parent_key_id {
Some(k) => tx_entry.parent_key_id == *k,
@@ -372,6 +389,12 @@ where
f_pk && f_tx_id && f_txs && f_outstanding
})
.collect();
if bad_records != 0 {
error!(
"retrieve_txs: tx history is missing {} records, cause db read error",
bad_records
);
}
txs.sort_by_key(|tx| tx.creation_ts);
}
Ok(txs)
@@ -547,10 +570,14 @@ where
&& (output.status == OutputStatus::Unconfirmed
|| output.status == OutputStatus::Reverted)
{
let tx = batch.tx_log_iter()?.find(|t| {
Some(t.id) == output.tx_log_entry
&& t.parent_key_id == *parent_key_id
});
let tx = batch
.tx_log_iter()?
.filter(|t| t.is_ok())
.map(|t| t.unwrap())
.find(|t| {
Some(t.id) == output.tx_log_entry
&& t.parent_key_id == *parent_key_id
});
if let Some(mut t) = tx {
if t.tx_type == TxLogEntryType::TxReverted {
t.tx_type = TxLogEntryType::TxReceived;
@@ -559,6 +586,10 @@ where
t.update_confirmation_ts();
t.confirmed = true;
batch.save_tx_log_entry(t, &parent_key_id)?;
} else {
if let Some(tx_id) = output.tx_log_entry {
error!("apply_api_outputs: tx with id {:?} not found", tx_id);
}
}
}
output.height = o.1;
@@ -582,7 +613,17 @@ where
}
let mut txs_to_save = vec![];
for mut tx in batch.tx_log_iter()? {
let mut bad_records = 0;
for mut tx in batch
.tx_log_iter()?
.filter(|tx| {
if tx.is_err() {
bad_records += 1;
}
tx.is_ok()
})
.map(|t| t.unwrap())
{
if reverted_kernels.contains(&tx.id) && tx.parent_key_id == *parent_key_id {
tx.tx_type = TxLogEntryType::TxReverted;
tx.reverted_after = tx.confirmation_ts.clone().and_then(|t| {
@@ -593,6 +634,14 @@ where
txs_to_save.push(tx);
}
}
if bad_records > 0 {
error!(
"apply_api_outputs: tx history is missing {} records, cause db read error",
bad_records
);
}
for tx in txs_to_save {
batch.save_tx_log_entry(tx, &parent_key_id)?;
}
@@ -671,8 +720,16 @@ where
}
// Get corresponding kernels
let mut bad_records = 0;
let kernels = wallet
.tx_log_iter()?
.filter(|tx| {
if tx.is_err() {
bad_records += 1;
}
tx.is_ok()
})
.map(|t| t.unwrap())
.filter(|t| {
ids.contains(&t.id)
&& t.parent_key_id == *parent_key_id
@@ -691,6 +748,13 @@ where
}
}
if bad_records > 0 {
error!(
"find_reverted_kernels: tx history is missing {} records, cause db read error",
bad_records
);
}
Ok(reverted)
}
+4 -4
View File
@@ -81,7 +81,7 @@ impl ParticipantData {
}
}
/// A 'Slate' is passed around to all parties to build up all of the public
/// A 'Slate' is passed around to all parties to build up all the public
/// transaction data needed to create a finalized transaction. Callers can pass
/// the slate around by whatever means they choose, (but we can provide some
/// binary or JSON serialization helpers here).
@@ -115,7 +115,7 @@ pub struct Slate {
/// 2: height_locked
/// 3: NRD
pub kernel_features: u8,
/// Offset, needed when posting of transasction is deferred
/// Offset, needed when posting of transaction is deferred
pub offset: BlindingFactor,
/// Participant data, each participant in the transaction will
/// insert their public data here. For now, 0 is sender and 1
@@ -134,7 +134,7 @@ impl fmt::Display for Slate {
}
/// Slate state definition
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum SlateState {
/// Unknown, coming from earlier slate versions
Unknown,
@@ -148,7 +148,7 @@ pub enum SlateState {
Invoice1,
///Invoice flow, return journey
Invoice2,
/// Invoice flow, ready for tranasction posting
/// Invoice flow, ready for transaction posting
Invoice3,
}
+7 -4
View File
@@ -28,7 +28,7 @@ use crate::grin_util::secp::key::{PublicKey, SecretKey};
use crate::grin_util::secp::{self, pedersen, Secp256k1};
use crate::grin_util::{ToHex, ZeroingString};
use crate::slate_versions::ser as dalek_ser;
use crate::{InitTxArgs, WalletBackend};
use crate::{InitTxArgs, SlateState, WalletBackend};
use chrono::prelude::*;
use ed25519_dalek::PublicKey as DalekPublicKey;
use ed25519_dalek::Signature as DalekSignature;
@@ -623,6 +623,8 @@ pub struct TxLogEntry {
pub id: u32,
/// Slate transaction this entry is associated with, if any
pub tx_slate_id: Option<Uuid>,
/// Transaction slate state
pub tx_slate_state: Option<SlateState>,
/// Transaction type (as above)
pub tx_type: TxLogEntryType,
/// Time this tx entry was created
@@ -686,10 +688,11 @@ impl TxLogEntry {
/// Return a new blank with TS initialised with next entry
pub fn new(parent_key_id: Identifier, t: TxLogEntryType, id: u32) -> Self {
TxLogEntry {
parent_key_id: parent_key_id,
parent_key_id,
tx_type: t,
id: id,
id,
tx_slate_id: None,
tx_slate_state: None,
creation_ts: Utc::now(),
confirmation_ts: None,
confirmed: false,
@@ -878,7 +881,7 @@ pub struct ViewWalletOutputResult {
impl ViewWalletOutputResult {
pub fn num_confirmations(&self, tip_height: u64) -> u64 {
if self.height > tip_height {
return 0;
0
} else {
1 + (tip_height - self.height)
}
+1 -4
View File
@@ -28,15 +28,12 @@ thiserror = "1"
# grin_util = { git = "https://github.com/mimblewimble/grin", tag = "v5.2.0-beta.3" }
# For bleeding edge
#grin_util = { git = "https://github.com/mimblewimble/grin", rev = "110e0e143fdf188b69ac56c2f378c4121859703b" }
grin_util = { git = "https://github.com/mimblewimble/grin", rev = "cf2ed3f3becd62b5e754ec964fd90e332b9a021f" }
# For local testing
# grin_util = { path = "../../grin/util"}
# Monorepo deps
grin_util = { path = "../../node/util"}
#####
[dev-dependencies]