Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factor instances provider #15

Closed
wants to merge 76 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
9dfcdf5
doc
Sajjon Sep 20, 2024
b33d787
derive_and_analyze
Sajjon Sep 20, 2024
c57fbf4
sketch more
Sajjon Sep 20, 2024
5b29364
account recovery scan sketch
CyonAlexRDX Sep 20, 2024
90baa3f
doc
CyonAlexRDX Sep 20, 2024
f6f1533
derive and analyze input
CyonAlexRDX Sep 20, 2024
46d08fa
mock
CyonAlexRDX Sep 20, 2024
17cabf3
sketch of god method
CyonAlexRDX Sep 20, 2024
ca1dfd9
adding VirtualEntityCreatingInstances
CyonAlexRDX Sep 20, 2024
3132831
arc
Sajjon Sep 20, 2024
173b085
split
Sajjon Sep 20, 2024
e0d5b55
cleanup
Sajjon Sep 20, 2024
33e93b2
stub
Sajjon Sep 20, 2024
a54c1e1
KeysCollector is now Send / Sync
Sajjon Sep 20, 2024
aac1315
simplify
Sajjon Sep 20, 2024
74dbeb7
loop until done
Sajjon Sep 21, 2024
0056c5e
IntoIter and FroIter
Sajjon Sep 21, 2024
7994095
onchain analyzer
Sajjon Sep 21, 2024
90a6dfa
Reimplement - again - derive_and_analyze.
CyonAlexRDX Sep 23, 2024
c48bf21
abstract requests
CyonAlexRDX Sep 23, 2024
45d4858
doc
CyonAlexRDX Sep 23, 2024
24425be
split
CyonAlexRDX Sep 23, 2024
73954df
doc
CyonAlexRDX Sep 23, 2024
b16bf8d
ignore doc test
CyonAlexRDX Sep 23, 2024
5819943
intermediare analysis
Sajjon Sep 24, 2024
8f3cff7
wip
Sajjon Sep 24, 2024
480ab52
[no ci] WIP
Sajjon Sep 24, 2024
ed29e37
[no ci] WIP
CyonAlexRDX Sep 24, 2024
28ec815
[no ci] WIP
CyonAlexRDX Sep 24, 2024
0bad237
[no ci] WIP
CyonAlexRDX Sep 24, 2024
9277d96
[no ci] WIP
CyonAlexRDX Sep 25, 2024
89897e9
wip
CyonAlexRDX Sep 25, 2024
7ce6c31
[no ci] WIP
CyonAlexRDX Sep 25, 2024
d5cf525
[no ci] WIP
CyonAlexRDX Sep 25, 2024
ded6853
[no ci] WIP
CyonAlexRDX Sep 25, 2024
e9745d5
getting there
CyonAlexRDX Sep 25, 2024
20ebbae
[no ci] WIP
CyonAlexRDX Sep 25, 2024
dab4ab5
[no ci] WIP
CyonAlexRDX Sep 25, 2024
09fec6d
next index assigner with ephemeral local offsets
Sajjon Sep 26, 2024
02e6c6d
[no ci] WIP
Sajjon Sep 26, 2024
5919337
DerivationRequestWithRange from QuantifiedUnindexDerivationPAth + Pth…
CyonAlexRDX Sep 26, 2024
51ef46e
copy cache
CyonAlexRDX Sep 26, 2024
667a28a
first test passing
CyonAlexRDX Sep 26, 2024
7cab9ec
account creation tests
CyonAlexRDX Sep 26, 2024
f2368e4
second account has index 1
Sajjon Sep 26, 2024
6954232
more tests
Sajjon Sep 26, 2024
b2cccd5
Add Clear Cache method, test failing because we do not yet FILL Cache…
CyonAlexRDX Sep 27, 2024
cb6be47
Its working, its working, its wooooooooooorking
Sajjon Sep 28, 2024
c5b2286
removed debug prints and changed `DerivationRequestQuantitySelector::…
Sajjon Sep 28, 2024
85241af
clippy fix
Sajjon Sep 28, 2024
e3b53d7
derive many more
Sajjon Sep 28, 2024
8da2005
fix tests
Sajjon Sep 28, 2024
3d280db
cleanup
Sajjon Sep 28, 2024
6d44e15
multi factor
Sajjon Sep 28, 2024
45f168a
remove interactors from SargonOS
CyonAlexRDX Sep 30, 2024
adbd0c2
YAGNI: FullDerivationRequests
CyonAlexRDX Sep 30, 2024
30f5f59
YAGNI
CyonAlexRDX Sep 30, 2024
d965099
break out hidden ctor
CyonAlexRDX Sep 30, 2024
820e261
Yagni, many Recovery Types
CyonAlexRDX Sep 30, 2024
e905bda
wayni
CyonAlexRDX Sep 30, 2024
54bb566
WIP
CyonAlexRDX Sep 30, 2024
b2dbb54
[no ci] WIP
CyonAlexRDX Sep 30, 2024
5f8fc7b
WIP
CyonAlexRDX Sep 30, 2024
10d3ff1
WIP
CyonAlexRDX Sep 30, 2024
a7a7822
WIP
CyonAlexRDX Sep 30, 2024
dba3ec4
WIP
CyonAlexRDX Sep 30, 2024
f366ea0
WIP
CyonAlexRDX Sep 30, 2024
c17c724
WIP
CyonAlexRDX Sep 30, 2024
ee90f8f
WIP
CyonAlexRDX Sep 30, 2024
2312401
WIP
CyonAlexRDX Sep 30, 2024
eaa2ea8
WIP
CyonAlexRDX Sep 30, 2024
0c6f325
WIP
CyonAlexRDX Sep 30, 2024
2fe045c
WIP
CyonAlexRDX Sep 30, 2024
b48d113
WIP
CyonAlexRDX Sep 30, 2024
8edc023
WIP
CyonAlexRDX Sep 30, 2024
e4207c9
WIP
CyonAlexRDX Sep 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
{
"cSpell.words": [
"analyser",
"Banksy",
"Fulfillable",
"interactor",
"Interactors",
"Keyrings",
"preprocess",
"rola",
"scrypto",
"securifies",
"securify",
"securifying",
"substate",
"txid",
"txids",
"unfactored",
"Unindex",
"Unindexed",
"unrecovered",
"unsecurified",
"VECI",
"Yubikey"
]
}
}
2 changes: 1 addition & 1 deletion src/derivation/collector/key_derivation_outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl KeyDerivationOutcome {
}

/// ALL factor instances derived by the KeysCollector
pub fn all_factors(&self) -> IndexSet<HierarchicalDeterministicFactorInstance> {
pub fn all_factors(&self) -> FactorInstances {
self.factors_by_source
.clone()
.into_iter()
Expand Down
20 changes: 14 additions & 6 deletions src/derivation/collector/key_ring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@ use crate::prelude::*;

/// A collection of `HierarchicalDeterministicFactorInstance` derived from a
/// factor source.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub(crate) struct Keyring {
pub(crate) factor_source_id: FactorSourceIDFromHash,
pub(crate) paths: IndexSet<DerivationPath>,
derived: RefCell<IndexSet<HierarchicalDeterministicFactorInstance>>,
derived: RwLock<IndexSet<HierarchicalDeterministicFactorInstance>>,
}

impl Keyring {
pub fn clone_snapshot(&self) -> Self {
Self {
factor_source_id: self.factor_source_id,
paths: self.paths.clone(),
derived: RwLock::new(self.derived.try_read().unwrap().clone()),
}
}
pub(crate) fn new(
factor_source_id: FactorSourceIDFromHash,
paths: IndexSet<DerivationPath>,
) -> Self {
Self {
factor_source_id,
paths,
derived: RefCell::new(IndexSet::new()),
derived: RwLock::new(IndexSet::new()),
}
}
pub(crate) fn factors(&self) -> IndexSet<HierarchicalDeterministicFactorInstance> {
self.derived.borrow().clone()
self.derived.try_read().unwrap().clone()
}

pub(crate) fn process_response(
Expand All @@ -33,10 +40,11 @@ impl Keyring {
.all(|f| f.factor_source_id == self.factor_source_id
&& !self
.derived
.borrow()
.try_read()
.unwrap()
.iter()
.any(|x| x.public_key == f.public_key)));

self.derived.borrow_mut().extend(response)
self.derived.try_write().unwrap().extend(response)
}
}
20 changes: 14 additions & 6 deletions src/derivation/collector/keys_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ pub struct KeysCollector {

/// Mutable internal state of the collector which builds up the list
/// of public keys from each used factor source.
state: RefCell<KeysCollectorState>,
state: RwLock<KeysCollectorState>,
}

impl KeysCollector {
pub fn new(
all_factor_sources_in_profile: impl IntoIterator<Item = HDFactorSource>,
derivation_paths: IndexMap<FactorSourceIDFromHash, IndexSet<DerivationPath>>,
derivation_paths: impl Into<IndexMap<FactorSourceIDFromHash, IndexSet<DerivationPath>>>,
interactors: Arc<dyn KeysDerivationInteractors>,
) -> Result<Self> {
let derivation_paths = derivation_paths.into();
let preprocessor = KeysCollectorPreprocessor::new(derivation_paths);
Self::with_preprocessor(
all_factor_sources_in_profile
Expand All @@ -47,7 +48,7 @@ impl KeysCollector {

Ok(Self {
dependencies,
state: RefCell::new(state),
state: RwLock::new(state),
})
}
}
Expand All @@ -60,7 +61,7 @@ impl KeysCollector {
.derive_with_factors() // in decreasing "friction order"
.await
.inspect_err(|e| error!("Failed to use factor sources: {:#?}", e));
self.state.into_inner().outcome()
self.state.into_inner().unwrap().outcome()
}
}

Expand Down Expand Up @@ -123,7 +124,11 @@ impl KeysCollector {
&self,
factor_source_id: &FactorSourceIDFromHash,
) -> Result<MonoFactorKeyDerivationRequest> {
let keyring = self.state.borrow().keyring_for(factor_source_id)?;
let keyring = self
.state
.try_read()
.unwrap()
.keyring_for(factor_source_id)?;
assert_eq!(keyring.factors().len(), 0);
let paths = keyring.paths.clone();
Ok(MonoFactorKeyDerivationRequest::new(
Expand Down Expand Up @@ -156,6 +161,9 @@ impl KeysCollector {
}

fn process_batch_response(&self, response: KeyDerivationResponse) -> Result<()> {
self.state.borrow_mut().process_batch_response(response)
self.state
.try_write()
.unwrap()
.process_batch_response(response)
}
}
13 changes: 7 additions & 6 deletions src/derivation/collector/keys_collector_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::prelude::*;
///
/// Holds a collection of keyrings derived from various factor sources.
pub(crate) struct KeysCollectorState {
pub(super) keyrings: RefCell<IndexMap<FactorSourceIDFromHash, Keyring>>,
pub(super) keyrings: RwLock<IndexMap<FactorSourceIDFromHash, Keyring>>,
}

impl KeysCollectorState {
Expand All @@ -22,12 +22,12 @@ impl KeysCollectorState {
})
.collect::<IndexMap<FactorSourceIDFromHash, Keyring>>();
Self {
keyrings: RefCell::new(keyrings),
keyrings: RwLock::new(keyrings),
}
}

pub(crate) fn outcome(self) -> KeyDerivationOutcome {
let key_rings = self.keyrings.into_inner();
let key_rings = self.keyrings.into_inner().unwrap();
KeyDerivationOutcome::new(
key_rings
.into_iter()
Expand All @@ -38,16 +38,17 @@ impl KeysCollectorState {

pub(crate) fn keyring_for(&self, factor_source_id: &FactorSourceIDFromHash) -> Result<Keyring> {
self.keyrings
.borrow()
.try_read()
.unwrap()
.get(factor_source_id)
.cloned()
.map(|x| x.clone_snapshot())
.inspect(|k| assert_eq!(k.factor_source_id, *factor_source_id))
.ok_or(CommonError::UnknownFactorSource)
}

pub(crate) fn process_batch_response(&self, response: KeyDerivationResponse) -> Result<()> {
for (factor_source_id, factors) in response.per_factor_source.into_iter() {
let mut rings = self.keyrings.borrow_mut();
let mut rings = self.keyrings.try_write().unwrap();
let keyring = rings
.get_mut(&factor_source_id)
.ok_or(CommonError::UnknownFactorSource)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::prelude::*;
/// which it will use to update it internal state and continue with the next
/// factor source, or in case of failure the whole process will be aborted.
#[async_trait::async_trait]
pub trait MonoFactorKeyDerivationInteractor {
pub trait MonoFactorKeyDerivationInteractor: Send + Sync {
async fn derive(
&self,
request: MonoFactorKeyDerivationRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::prelude::*;
/// which it will use to update it internal state and continue with the next
/// factor source, or in case of failure the whole process will be aborted.
#[async_trait::async_trait]
pub trait PolyFactorKeyDerivationInteractor {
pub trait PolyFactorKeyDerivationInteractor: Send + Sync {
async fn derive(
&self,
request: PolyFactorKeyDerivationRequest,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::prelude::*;

/// A collection of "interactors" which can derive keys.
pub trait KeysDerivationInteractors {
pub trait KeysDerivationInteractors: Sync + Send {
fn interactor_for(&self, kind: FactorSourceKind) -> KeyDerivationInteractor;
}
6 changes: 3 additions & 3 deletions src/derivation/tests/derivation_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ mod key_derivation_tests {
)
.unwrap();
let outcome = collector.collect_keys().await;
assert!(outcome.all_factors().is_empty())
assert!(outcome.all_factors().factor_instances().is_empty())
}

mod multi_key {
Expand Down Expand Up @@ -378,7 +378,7 @@ mod key_derivation_tests {
paths
);

assert!(outcome.all_factors().len() > 200);
assert!(outcome.all_factors().factor_instances().len() > 200);

assert_eq!(
outcome
Expand Down Expand Up @@ -413,7 +413,7 @@ mod key_derivation_tests {
KeysCollector::with(factor_source, network_id, key_kind, entity_kind, key_space);

let outcome = collector.collect_keys().await;
let factors = outcome.all_factors();
let factors = outcome.all_factors().factor_instances();
assert_eq!(factors.len(), 1);
let factor = factors.first().unwrap();
assert_eq!(
Expand Down
44 changes: 44 additions & 0 deletions src/factor_instances_provider/derive_more.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::prelude::*;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum DeriveMore {
WithKnownStartIndex {
with_start_index: DerivationRequestWithRange,
number_of_instances_needed_to_fully_satisfy_request: Option<usize>,
},
WithoutKnownLastIndex {
request: QuantifiedUnindexDerivationRequest,
number_of_instances_needed_to_fully_satisfy_request: usize,
},
}

impl DeriveMore {
pub fn number_of_instances_to_use_directly(
&self,
original_purpose: FactorInstancesRequestPurpose,
) -> usize {
match original_purpose {
FactorInstancesRequestPurpose::MARS { .. } => {
DerivationRequestQuantitySelector::FILL_CACHE_QUANTITY

Check warning on line 22 in src/factor_instances_provider/derive_more.rs

View check run for this annotation

Codecov / codecov/patch

src/factor_instances_provider/derive_more.rs#L22

Added line #L22 was not covered by tests
}
FactorInstancesRequestPurpose::OARS { .. } => {
DerivationRequestQuantitySelector::FILL_CACHE_QUANTITY

Check warning on line 25 in src/factor_instances_provider/derive_more.rs

View check run for this annotation

Codecov / codecov/patch

src/factor_instances_provider/derive_more.rs#L25

Added line #L25 was not covered by tests
}
FactorInstancesRequestPurpose::UpdateOrSetSecurityShieldForAccounts {

Check warning on line 27 in src/factor_instances_provider/derive_more.rs

View check run for this annotation

Codecov / codecov/patch

src/factor_instances_provider/derive_more.rs#L27

Added line #L27 was not covered by tests
accounts,
..
} => accounts.len(),
FactorInstancesRequestPurpose::PreDeriveInstancesForNewFactorSource { .. } => 0,
FactorInstancesRequestPurpose::NewVirtualUnsecurifiedAccount { .. } => 1,
}
}

pub fn unquantified(&self) -> UnquantifiedUnindexDerivationRequest {
match self {
Self::WithKnownStartIndex {
with_start_index, ..
} => with_start_index.clone().into(),
Self::WithoutKnownLastIndex { request, .. } => request.clone().into(),
}
}
}
Loading
Loading