Skip to content

Commit

Permalink
Transaction signing (#71)
Browse files Browse the repository at this point in the history
* move BinarySerializer and BinaryParser

* add STObject

* current state of txn signing

* current state of sign

* current state of sign

* use String instead of Cow<'a, str> for structs using serde_with_tag macro due to lifetime issues when deserializing

* utilize Cow for models

* utilize Cow for models

* cargo fmt

* add simple test

* add devcontainer

* fix async client tests

* fix github workflow

* fix tests with --all-features

* fix --no-default-features tests with embedded-ws

* try fix colliding embebedded-websocket feature with dep: syntax

* fix ambiguous name error

* Revise Models (#74)

* current state

* initial

* initial

* add to changelog

* impl LedgerObject trait

* remove .DS_Store

* add documentation

* cargo fix

* add Default trait to FlagCollection

* refactoring of models

* fix serde tests

* fix serde tests

* Delete src/models/.DS_Store

* remove dafault_none

* resolve comments

* revise dependencies

* remove old clients

* add new clients

* add codec for std embedded websocket

* move websocket exceptions

* add WebsocketBase

* add Client and AsyncClient traits

* add XRPLWebsocketIO as standardized trait

* adjust clients mod

* add XRPLResponse

* revise the Request trait to have methods to get a resut models common fields

* cargo fmt

* add get_random_id utility function

* add xrpl testnet uri

* revise the tests to work with the changes

* error handling

* improve testing

* implement websocket client request

* implement websocket client request for embedded websocket

* update rand trying to get rid of cargo check: OsRng: rand_core::RngCore is not satisfied error

* fix github workflow build and tests

* fix github workflow build and tests

* run linters

* add json rpc client

* add json rpc for std and tests

* cargo fmt

* add pre-commit test with json-rpc-std

* cargo fmt

* cargo fix

* improve client code

* refactor features

* fix tungstenite example

* fix clients

* fix client tests

* fix tests

* rename features in github workflow

* add transaction auto filling as in #76 (#80)

* current state of txn signing

* current state of sign

* current state of sign

* add simple test

* resolve errors caused by updating branch

* resolve errors caused by updating branch

* add autofill_and_sign

* make tx signing work

* improve sign test

* handle unwraps

* add autofill_and_sign

* add sign and submit

* fix errors caused by solving merge conflicts

* rename SerializedDict and SerializedList to STObject and STArray

* rename SerializedDict and SerializedList to STObject and STArray

* handle unwraps

* fix tests

* fix tests

* fix tests

* add multisigning

* add multisigning

* fix tests

* fix tests

---------

Co-authored-by: LimpidCrypto <[email protected]>
  • Loading branch information
LimpidCrypto and LimpidCrypto committed Oct 6, 2024
1 parent 4320497 commit 6a9589b
Show file tree
Hide file tree
Showing 30 changed files with 2,153 additions and 900 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,13 @@ thiserror-no-std = "2.0.2"
anyhow = { version = "1.0.69", default-features = false }

# networking
url = { version = "2.2.1", default-features = false, optional = true }
url = { version = "2.2.2", default-features = false, optional = true }
# websocket
embassy-sync = { version = "0.6.0", optional = true }
embedded-io-async = { version = "0.6.1", optional = true }
embedded-websocket = { version = "0.9.3", default-features = false, optional = true }
futures = { version = "0.3.30", optional = true }
rand_core = { version = "0.6.4", default-features = false }
# websocket-codec
bytes = { version = "1.7.1", default-features = false, optional = true }
tokio-util = { version = "0.7.11", features = ["codec"], optional = true }
Expand All @@ -90,6 +91,7 @@ reqwest = { version = "0.12.5", features = ["json"], optional = true }
[dev-dependencies]
criterion = "0.5.1"
tokio = { version = "1.0", features = ["full"] }
tokio-util = { version = "0.7.11", features = ["codec"] }

[[bench]]
name = "benchmarks"
Expand All @@ -114,6 +116,7 @@ helpers = ["account-helpers", "ledger-helpers", "transaction-helpers"]
account-helpers = ["amounts", "currencies", "requests", "results"]
ledger-helpers = ["amounts", "currencies", "requests", "results"]
transaction-helpers = [
"wallet",
"amounts",
"currencies",
"requests",
Expand Down
59 changes: 59 additions & 0 deletions rustc-ice-2024-08-27T11_36_40-17775.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
thread 'rustc' panicked at /rustc/80eb5a8e910e5185d47cdefe3732d839c78a5e7e/compiler/rustc_query_system/src/query/plumbing.rs:727:9:
Found unstable fingerprints for evaluate_obligation(9acaf53e42db4106-b70f9be4bd000590): Ok(EvaluatedToAmbig)
stack backtrace:
0: 0x7f2385fa3de5 - std::backtrace::Backtrace::create::h5fc94655595d7e27
1: 0x7f2384710fe5 - std::backtrace::Backtrace::force_capture::h3ae8cd2c99c0732c
2: 0x7f23838b111e - std[edc1ba278773f0d3]::panicking::update_hook::<alloc[168ee4b9ac58f8b8]::boxed::Box<rustc_driver_impl[734e2c9770122f8]::install_ice_hook::{closure#0}>>::{closure#0}
3: 0x7f2384728e27 - std::panicking::rust_panic_with_hook::h9e59a429b59b11d4
4: 0x7f2384728ae7 - std::panicking::begin_panic_handler::{{closure}}::h97d6e0922a833e87
5: 0x7f23847262e9 - std::sys::backtrace::__rust_end_short_backtrace::ha09625205ff6b122
6: 0x7f23847287b4 - rust_begin_unwind
7: 0x7f2381922f53 - core::panicking::panic_fmt::h089121e4cbbc3220
8: 0x7f23841d9c41 - rustc_query_system[cb6aa6728468b543]::query::plumbing::incremental_verify_ich_failed::<rustc_middle[354bbee2ce4c460]::ty::context::TyCtxt>
9: 0x7f238558c6af - rustc_query_system[cb6aa6728468b543]::query::plumbing::try_execute_query::<rustc_query_impl[2dfeb81381ece16c]::DynamicConfig<rustc_query_system[cb6aa6728468b543]::query::caches::DefaultCache<rustc_type_ir[90a0fdc985334425]::canonical::Canonical<rustc_middle[354bbee2ce4c460]::ty::context::TyCtxt, rustc_middle[354bbee2ce4c460]::ty::ParamEnvAnd<rustc_middle[354bbee2ce4c460]::ty::predicate::Predicate>>, rustc_middle[354bbee2ce4c460]::query::erase::Erased<[u8; 2usize]>>, false, false, false>, rustc_query_impl[2dfeb81381ece16c]::plumbing::QueryCtxt, true>
10: 0x7f238558ab62 - rustc_query_impl[2dfeb81381ece16c]::query_impl::evaluate_obligation::get_query_incr::__rust_end_short_backtrace
11: 0x7f238246b63e - <rustc_infer[62334800a6125f76]::infer::InferCtxt as rustc_trait_selection[9848853b4dacb81e]::traits::query::evaluate_obligation::InferCtxtExt>::evaluate_obligation_no_overflow
12: 0x7f2381749e92 - <core[8c2a069408211e69]::iter::adapters::filter::Filter<core[8c2a069408211e69]::iter::adapters::map::Map<core[8c2a069408211e69]::slice::iter::Iter<rustc_hir_typeck[d8d14d8a3ea8603d]::method::probe::Candidate>, <rustc_hir_typeck[d8d14d8a3ea8603d]::method::probe::ProbeContext>::consider_candidates::{closure#0}>, <rustc_hir_typeck[d8d14d8a3ea8603d]::method::probe::ProbeContext>::consider_candidates::{closure#1}> as core[8c2a069408211e69]::iter::traits::iterator::Iterator>::next
13: 0x7f238552a7b4 - <rustc_hir_typeck[d8d14d8a3ea8603d]::method::probe::ProbeContext>::pick_method
14: 0x7f2385529ed4 - <rustc_hir_typeck[d8d14d8a3ea8603d]::method::probe::ProbeContext>::pick_core
15: 0x7f2382485c0e - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::lookup_probe
16: 0x7f2385931fec - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
17: 0x7f23859345ae - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
18: 0x7f2385935734 - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
19: 0x7f2385935734 - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
20: 0x7f2385933b44 - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
21: 0x7f238593362e - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
22: 0x7f238592aa16 - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_block_with_expected
23: 0x7f2385931ed3 - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
24: 0x7f238593376d - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
25: 0x7f238592aa16 - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_block_with_expected
26: 0x7f2385931ed3 - <rustc_hir_typeck[d8d14d8a3ea8603d]::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
27: 0x7f23851bac37 - rustc_hir_typeck[d8d14d8a3ea8603d]::check::check_fn
28: 0x7f23852c6edf - rustc_hir_typeck[d8d14d8a3ea8603d]::typeck
29: 0x7f23852c6933 - rustc_query_impl[2dfeb81381ece16c]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[2dfeb81381ece16c]::query_impl::typeck::dynamic_query::{closure#2}::{closure#0}, rustc_middle[354bbee2ce4c460]::query::erase::Erased<[u8; 8usize]>>
30: 0x7f2385251b4a - rustc_query_system[cb6aa6728468b543]::query::plumbing::try_execute_query::<rustc_query_impl[2dfeb81381ece16c]::DynamicConfig<rustc_query_system[cb6aa6728468b543]::query::caches::VecCache<rustc_span[e1b931742f0b02c1]::def_id::LocalDefId, rustc_middle[354bbee2ce4c460]::query::erase::Erased<[u8; 8usize]>>, false, false, false>, rustc_query_impl[2dfeb81381ece16c]::plumbing::QueryCtxt, true>
31: 0x7f2385334054 - rustc_query_impl[2dfeb81381ece16c]::query_impl::typeck::get_query_incr::__rust_end_short_backtrace
32: 0x7f238524da5b - <rustc_middle[354bbee2ce4c460]::hir::map::Map>::par_body_owners::<rustc_hir_analysis[618f1997a162b265]::check_crate::{closure#4}>::{closure#0}
33: 0x7f238524b7a4 - rustc_hir_analysis[618f1997a162b265]::check_crate
34: 0x7f238572bcbf - rustc_interface[fc21679c26087701]::passes::run_required_analyses
35: 0x7f2385a97e5e - rustc_interface[fc21679c26087701]::passes::analysis
36: 0x7f2385a97e31 - rustc_query_impl[2dfeb81381ece16c]::plumbing::__rust_begin_short_backtrace::<rustc_query_impl[2dfeb81381ece16c]::query_impl::analysis::dynamic_query::{closure#2}::{closure#0}, rustc_middle[354bbee2ce4c460]::query::erase::Erased<[u8; 1usize]>>
37: 0x7f2385f83c0d - rustc_query_system[cb6aa6728468b543]::query::plumbing::try_execute_query::<rustc_query_impl[2dfeb81381ece16c]::DynamicConfig<rustc_query_system[cb6aa6728468b543]::query::caches::SingleCache<rustc_middle[354bbee2ce4c460]::query::erase::Erased<[u8; 1usize]>>, false, false, false>, rustc_query_impl[2dfeb81381ece16c]::plumbing::QueryCtxt, true>
38: 0x7f2385f838ba - rustc_query_impl[2dfeb81381ece16c]::query_impl::analysis::get_query_incr::__rust_end_short_backtrace
39: 0x7f2385d12229 - rustc_interface[fc21679c26087701]::interface::run_compiler::<core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>, rustc_driver_impl[734e2c9770122f8]::run_compiler::{closure#0}>::{closure#1}
40: 0x7f2385de6f44 - std[edc1ba278773f0d3]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[fc21679c26087701]::util::run_in_thread_with_globals<rustc_interface[fc21679c26087701]::util::run_in_thread_pool_with_globals<rustc_interface[fc21679c26087701]::interface::run_compiler<core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>, rustc_driver_impl[734e2c9770122f8]::run_compiler::{closure#0}>::{closure#1}, core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>>::{closure#0}, core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>>
41: 0x7f2385de75b0 - <<std[edc1ba278773f0d3]::thread::Builder>::spawn_unchecked_<rustc_interface[fc21679c26087701]::util::run_in_thread_with_globals<rustc_interface[fc21679c26087701]::util::run_in_thread_pool_with_globals<rustc_interface[fc21679c26087701]::interface::run_compiler<core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>, rustc_driver_impl[734e2c9770122f8]::run_compiler::{closure#0}>::{closure#1}, core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>>::{closure#0}, core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[8c2a069408211e69]::result::Result<(), rustc_span[e1b931742f0b02c1]::ErrorGuaranteed>>::{closure#1} as core[8c2a069408211e69]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
42: 0x7f2385de792b - std::sys::pal::unix::thread::Thread::new::thread_start::he6ae6a1223d421a8
43: 0x7f2380330ea7 - start_thread
44: 0x7f2380250a6f - clone
45: 0x0 - <unknown>


rustc version: 1.82.0-nightly (80eb5a8e9 2024-08-13)
platform: x86_64-unknown-linux-gnu

query stack during panic:
#0 [evaluate_obligation] evaluating trait selection obligation `models::transactions::payment::Payment<'a>: models::transactions::Transaction<'b, ^1_2>`
#1 [typeck] type-checking `models::transactions::payment::<impl at src/models/transactions/payment.rs:126:1: 126:38>::_get_partial_payment_error`
#2 [analysis] running analysis passes on this crate
end of query stack
15 changes: 7 additions & 8 deletions src/asynch/clients/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,26 @@ use crate::models::{
};
#[cfg(feature = "std")]
use crate::utils::get_random_id;
use alloc::borrow::Cow;
use alloc::borrow::{Cow, ToOwned};
use anyhow::Result;

#[allow(async_fn_in_trait)]
pub trait Client {
async fn request_impl<'a: 'b, 'b>(&self, request: XRPLRequest<'a>) -> Result<XRPLResponse<'b>>;
fn set_request_id<'a: 'b, 'b>(&self, request: &mut XRPLRequest<'a>) -> Cow<'b, str> {
let common_fields = request.get_common_fields();
let request_id: Cow<'_, str> = match common_fields.id.clone() {
Some(id) => id,

fn set_request_id(&self, request: &mut XRPLRequest<'_>) -> () {
let common_fields = request.get_common_fields_mut();
common_fields.id = match &common_fields.id {
Some(id) => Some(id.to_owned()),
None => {
#[cfg(feature = "std")]
{
let mut rng = rand::thread_rng();
Cow::Owned(get_random_id(&mut rng))
Some(Cow::Owned(get_random_id(&mut rng)))
}
#[cfg(not(feature = "std"))]
unimplemented!("get_random_id is not yet implemented for no_std. Please provide an `id` in the request.");
}
};
request.get_common_fields_mut().id = Some(request_id.clone());
request_id
}
}
10 changes: 7 additions & 3 deletions src/asynch/clients/websocket/_no_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ use embedded_websocket::{
};
use futures::Sink;
use futures::Stream;
use rand::RngCore;
use rand_core::RngCore;
use url::Url;

use super::{WebsocketClosed, WebsocketOpen};
use crate::{asynch::clients::SingleExecutorMutex, models::requests::XRPLRequest};
use crate::{
asynch::clients::SingleExecutorMutex,
models::requests::{Request, XRPLRequest},
};
use crate::{
asynch::clients::{
client::Client as ClientTrait,
Expand Down Expand Up @@ -247,7 +250,8 @@ where
mut request: XRPLRequest<'a>,
) -> Result<XRPLResponse<'b>> {
// setup request future
let request_id = self.set_request_id(&mut request);
self.set_request_id(&mut request);
let request_id = request.get_common_fields().id.as_ref().unwrap();
let mut websocket_base = self.websocket_base.lock().await;
websocket_base
.setup_request_future(request_id.to_string())
Expand Down
5 changes: 3 additions & 2 deletions src/asynch/clients/websocket/_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::{WebsocketClosed, WebsocketOpen};
use crate::asynch::clients::client::Client;
use crate::asynch::clients::websocket::websocket_base::{MessageHandler, WebsocketBase};
use crate::asynch::clients::SingleExecutorMutex;
use crate::models::requests::XRPLRequest;
use crate::models::requests::{Request, XRPLRequest};
use crate::models::results::XRPLResponse;
use crate::Err;

Expand Down Expand Up @@ -204,7 +204,8 @@ where
mut request: XRPLRequest<'a>,
) -> Result<XRPLResponse<'b>> {
// setup request future
let request_id = self.set_request_id(&mut request);
self.set_request_id(&mut request);
let request_id = request.get_common_fields().id.as_ref().unwrap();
let mut websocket_base = self.websocket_base.lock().await;
websocket_base
.setup_request_future(request_id.to_string())
Expand Down
8 changes: 8 additions & 0 deletions src/asynch/transaction/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,11 @@ pub enum XRPLTransactionException<'a> {
#[error("Invalid rippled version: {0}")]
InvalidRippledVersion(Cow<'a, str>),
}

#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum XRPLSignTransactionException<'a> {
#[error("{0:?} value does not match X-Address tag")]
TagFieldMismatch(&'a str),
#[error("Fee value of {0:?} is likely entered incorrectly, since it is much larger than the typical XRP transaction cost. If this is intentional, use `check_fee=Some(false)`.")]
FeeTooHigh(Cow<'a, str>),
}
Loading

0 comments on commit 6a9589b

Please sign in to comment.