diff --git a/Cargo.lock b/Cargo.lock index b743427..0611770 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index a9fb76c..acef614 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"]} diff --git a/api/Cargo.toml b/api/Cargo.toml index 47aed3f..b86cfbd 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -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] diff --git a/api/src/foreign.rs b/api/src/foreign.rs index d90ad14..f5e8276 100644 --- a/api/src/foreign.rs +++ b/api/src/foreign.rs @@ -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) } } diff --git a/api/src/owner_rpc.rs b/api/src/owner_rpc.rs index bd862fe..d1c31f7 100644 --- a/api/src/owner_rpc.rs +++ b/api/src/owner_rpc.rs @@ -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" } ] diff --git a/config/Cargo.toml b/config/Cargo.toml index a97bc99..137dc36 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -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] diff --git a/controller/Cargo.toml b/controller/Cargo.toml index 19d953b..3425119 100644 --- a/controller/Cargo.toml +++ b/controller/Cargo.toml @@ -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] diff --git a/controller/src/display.rs b/controller/src/display.rs index 5668485..e5f2f88 100644 --- a/controller/src/display.rs +++ b/controller/src/display.rs @@ -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, diff --git a/impls/Cargo.toml b/impls/Cargo.toml index eab96d8..9625570 100644 --- a/impls/Cargo.toml +++ b/impls/Cargo.toml @@ -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] diff --git a/libwallet/Cargo.toml b/libwallet/Cargo.toml index 9496f9d..65354a6 100644 --- a/libwallet/Cargo.toml +++ b/libwallet/Cargo.toml @@ -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"} - ##### diff --git a/libwallet/src/api_impl/foreign.rs b/libwallet/src/api_impl/foreign.rs index a116b84..f3cb611 100644 --- a/libwallet/src/api_impl/foreign.rs +++ b/libwallet/src/api_impl/foreign.rs @@ -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( + wallet: &mut WalletBackend, + 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(()) +} diff --git a/libwallet/src/api_impl/owner.rs b/libwallet/src/api_impl/owner.rs index 95f4dc9..67f642e 100644 --- a/libwallet/src/api_impl/owner.rs +++ b/libwallet/src/api_impl/owner.rs @@ -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())?; diff --git a/libwallet/src/backend.rs b/libwallet/src/backend.rs index a9f37c9..2fa0a08 100644 --- a/libwallet/src/backend.rs +++ b/libwallet/src/backend.rs @@ -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 = prefix_iter?.collect::, _>>()?; + 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, Error> { + pub fn tx_log_iter( + &self, + ) -> Result>, 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 = prefix_iter?.collect::, _>>()?; + 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 = prefix_iter?.collect::, _>>()?; + 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 + 'a, Error> { + pub fn tx_log_iter( + &'a self, + ) -> Result> + '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 = prefix_iter?.collect::, _>>()?; + Ok(items.into_iter()) } /// Save an output as locked in the backend. diff --git a/libwallet/src/internal/selection.rs b/libwallet/src/internal/selection.rs index 3b420bc..a145662 100644 --- a/libwallet/src/internal/selection.rs +++ b/libwallet/src/internal/selection.rs @@ -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 { diff --git a/libwallet/src/internal/updater.rs b/libwallet/src/internal/updater.rs index f7b053d..3383d9e 100644 --- a/libwallet/src/internal/updater.rs +++ b/libwallet/src/internal/updater.rs @@ -101,181 +101,190 @@ where K: Keychain, { // Apply simple bool, GTE or LTE fields - let txs_iter: Box> = 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 = 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) } diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index 43a7ba9..a29233c 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -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, } diff --git a/libwallet/src/types.rs b/libwallet/src/types.rs index dff9a66..41ca9a5 100644 --- a/libwallet/src/types.rs +++ b/libwallet/src/types.rs @@ -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, + /// Transaction slate state + pub tx_slate_state: Option, /// 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) } diff --git a/util/Cargo.toml b/util/Cargo.toml index 172f686..1cb5aa8 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -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]