Skip to content

Commit 6bfe959

Browse files
sasuke0787Archibald MacRubatoSere StaccatoMontague LegatoGianna McAccelerando
authored andcommitted
[vouch] patch root trust score (#404)
Co-authored-by: Archibald MacRubato <[email protected]> Co-authored-by: Sere Staccato <[email protected]> Co-authored-by: Montague Legato <[email protected]> Co-authored-by: xyz <xyz> Co-authored-by: Gianna McAccelerando <[email protected]>
1 parent cbcdfff commit 6bfe959

File tree

5 files changed

+130
-23
lines changed

5 files changed

+130
-23
lines changed

framework/cached-packages/src/libra_framework_sdk_builder.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ pub enum EntryFunctionCall {
115115
cap_update_table: Vec<u8>,
116116
},
117117

118+
/// some accounts with transactions immediately after the v8 upgrade
119+
/// may have a malformed timestamp
120+
ActivityMaybeFixMalformed {},
121+
118122
/// User opts into burns being sent to community (recycle burn).
119123
/// default is false (burn is final).
120124
BurnSetSendCommunity {
@@ -442,6 +446,7 @@ impl EntryFunctionCall {
442446
new_public_key_bytes,
443447
cap_update_table,
444448
),
449+
ActivityMaybeFixMalformed {} => activity_maybe_fix_malformed(),
445450
BurnSetSendCommunity { community } => burn_set_send_community(community),
446451
CodePublishPackageTxn {
447452
metadata_serialized,
@@ -765,6 +770,23 @@ pub fn account_rotate_authentication_key_with_rotation_capability(
765770
))
766771
}
767772

773+
/// some accounts with transactions immediately after the v8 upgrade
774+
/// may have a malformed timestamp
775+
pub fn activity_maybe_fix_malformed() -> TransactionPayload {
776+
TransactionPayload::EntryFunction(EntryFunction::new(
777+
ModuleId::new(
778+
AccountAddress::new([
779+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
780+
0, 0, 0, 1,
781+
]),
782+
ident_str!("activity").to_owned(),
783+
),
784+
ident_str!("maybe_fix_malformed").to_owned(),
785+
vec![],
786+
vec![],
787+
))
788+
}
789+
768790
/// User opts into burns being sent to community (recycle burn).
769791
/// default is false (burn is final).
770792
pub fn burn_set_send_community(community: bool) -> TransactionPayload {
@@ -1696,6 +1718,14 @@ mod decoder {
16961718
}
16971719
}
16981720

1721+
pub fn activity_maybe_fix_malformed(payload: &TransactionPayload) -> Option<EntryFunctionCall> {
1722+
if let TransactionPayload::EntryFunction(_script) = payload {
1723+
Some(EntryFunctionCall::ActivityMaybeFixMalformed {})
1724+
} else {
1725+
None
1726+
}
1727+
}
1728+
16991729
pub fn burn_set_send_community(payload: &TransactionPayload) -> Option<EntryFunctionCall> {
17001730
if let TransactionPayload::EntryFunction(script) = payload {
17011731
Some(EntryFunctionCall::BurnSetSendCommunity {
@@ -2230,6 +2260,10 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy<EntryFunctionDecoderMa
22302260
"account_rotate_authentication_key_with_rotation_capability".to_string(),
22312261
Box::new(decoder::account_rotate_authentication_key_with_rotation_capability),
22322262
);
2263+
map.insert(
2264+
"activity_maybe_fix_malformed".to_string(),
2265+
Box::new(decoder::activity_maybe_fix_malformed),
2266+
);
22332267
map.insert(
22342268
"burn_set_send_community".to_string(),
22352269
Box::new(decoder::burn_set_send_community),

framework/libra-framework/sources/ol_sources/tests/page_rank.test.move

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,4 +510,61 @@ module ol_framework::test_page_rank {
510510

511511
}
512512

513+
514+
#[test(framework = @ol_framework)]
515+
/// a root of trust user may have their score
516+
/// reduced from the initial voting power
517+
/// scenario: two root of trust users are created
518+
/// one of them vouches for alice, who then vouches for bob
519+
/// who subsequently vouches for a root of trust user root1
520+
/// root0 -> alice -> bob -> root1
521+
fun root_score_reduction(framework: &signer) {
522+
// Set up the test base
523+
let roots_sig = test_base(framework);
524+
525+
let root0 = vector::borrow(&roots_sig, 0);
526+
vouch::init(root0);
527+
let root0_addr = signer::address_of(root0);
528+
529+
let root1 = vector::borrow(&roots_sig, 1);
530+
vouch::init(root1);
531+
let root1_addr = signer::address_of(root1);
532+
533+
534+
///////// Root 0 score is initially 0 ////////
535+
let root0_score_pre = page_rank_lazy::get_trust_score(root0_addr);
536+
assert!(root0_score_pre == 0, 7357001);
537+
let root1_score_pre = page_rank_lazy::get_trust_score(root1_addr);
538+
assert!(root1_score_pre == 0, 7357002);
539+
/////////
540+
541+
// Alice receives a vouch from root0
542+
let alice_sig = mock::create_user_from_u64(framework, 11);
543+
let alice_addr = signer::address_of(&alice_sig);
544+
vouch::init(&alice_sig);
545+
// Initialize page rank for the new user
546+
page_rank_lazy::maybe_initialize_trust_record(&alice_sig);
547+
548+
// Alice vouches for bob
549+
let bob_sig = mock::create_user_from_u64(framework, 12);
550+
vouch::init(&bob_sig);
551+
let bob_addr = signer::address_of(&bob_sig);
552+
page_rank_lazy::maybe_initialize_trust_record(&bob_sig);
553+
554+
vouch_txs::vouch_for(root0, alice_addr);
555+
vouch_txs::vouch_for(&alice_sig, bob_addr);
556+
557+
let bob_final_score = page_rank_lazy::get_trust_score(bob_addr);
558+
assert!(bob_final_score == 50_000, 7357003);
559+
560+
vouch_txs::vouch_for(&bob_sig, root1_addr);
561+
562+
let root1_cached_score = page_rank_lazy::get_cached_score(root1_addr);
563+
diem_std::debug::print(&root1_cached_score);
564+
565+
diem_std::debug::print(&7777777777777777777);
566+
567+
page_rank_lazy::refresh_cache(root1_addr);
568+
// diem_std::debug::print(&root1_score_post);
569+
}
513570
}

framework/libra-framework/sources/ol_sources/vouch_lib/page_rank_lazy.move

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ module ol_framework::page_rank_lazy {
5656

5757
// Calculate or retrieve cached trust score
5858
public(friend) fun get_trust_score(addr: address): u64 acquires UserTrustRecord {
59-
let current_timestamp = timestamp::now_seconds();
6059

6160
// If user has no trust record, they have no score
6261
assert!(exists<UserTrustRecord>(addr), error::invalid_state(ENOT_INITIALIZED));
@@ -67,18 +66,26 @@ module ol_framework::page_rank_lazy {
6766
if (!user_record.is_stale) {
6867
return user_record.cached_score
6968
};
69+
set_score(addr)
70+
}
7071

72+
// always calculate the score
73+
fun set_score(addr: address): u64 acquires UserTrustRecord {
74+
// If user has no trust record, they have no score
75+
assert!(exists<UserTrustRecord>(addr), error::invalid_state(ENOT_INITIALIZED));
7176
// Cache is stale or expired - compute fresh score
7277
// Default roots to system account if no registry
7378
let roots = root_of_trust::get_current_roots_at_registry(@diem_framework);
79+
// diem_std::debug::print(&roots);
7480

7581
// Compute score using selected algorithm
7682
let score = traverse_graph(&roots, addr);
83+
diem_std::debug::print(&score);
7784

7885
// Update the cache
7986
let user_record_mut = borrow_global_mut<UserTrustRecord>(addr);
8087
user_record_mut.cached_score = score;
81-
user_record_mut.score_computed_at_timestamp = current_timestamp;
88+
user_record_mut.score_computed_at_timestamp = timestamp::now_seconds();
8289
user_record_mut.is_stale = false;
8390

8491
score
@@ -109,6 +116,7 @@ module ol_framework::page_rank_lazy {
109116
);
110117
};
111118

119+
112120
root_idx = root_idx + 1;
113121
};
114122

@@ -141,6 +149,8 @@ module ol_framework::page_rank_lazy {
141149

142150
let (neighbors, _) = vouch::get_given_vouches(current);
143151
let neighbor_count = vector::length(&neighbors);
152+
diem_std::debug::print(&current);
153+
diem_std::debug::print(&neighbor_count);
144154

145155
// No neighbors means no path
146156
if (neighbor_count == 0) {
@@ -150,45 +160,51 @@ module ol_framework::page_rank_lazy {
150160
// Track total score from all paths
151161
let total_score = 0;
152162

163+
153164
// Calculate power passed to neighbors (50% decay)
154165
let next_power = current_power / 2;
155166

156167
// if the both current and target are a root of trust
157-
// catch the case
168+
// catch the case of a root of trust vouching for another root of trust
158169
// and exit early
159-
if(
170+
if (
160171
root_of_trust::is_root_at_registry(@diem_framework, current) &&
161-
root_of_trust::is_root_at_registry(@diem_framework, target)
162-
) {
172+
root_of_trust::is_root_at_registry(@diem_framework, target) &&
173+
current != target &&
174+
vector::contains(&neighbors, &target) // Check if current directly vouches for target
175+
) {
176+
vector::push_back(visited, current);
163177
return next_power
164178
};
165179

166180
// Check ALL neighbors for paths to target
167181
let i = 0;
168182
while (i < neighbor_count) {
183+
169184
let neighbor = *vector::borrow(&neighbors, i);
185+
diem_std::debug::print(&neighbor);
170186

171187

172188
// Only visit if not already in path (avoid cycles)
173189
if (!vector::contains(visited, &neighbor)) {
174-
// Mark as visited
175-
if (neighbor != target) {
176-
// Don't mark the target as visited
190+
if (neighbor != target) {
191+
// Mark neighbor as visited
192+
// (Don't mark the target as visited
177193
// because we want to be able to
178-
// find it again
179-
// NOTE: fixes diamond pattern not accumulating
194+
// find it again)
180195

181196
vector::push_back(visited, neighbor);
197+
// we don't re-enter the root of
198+
// trust list, because we don't
199+
// want to accumulate points from
200+
// roots vouching for each other.
201+
if(
202+
root_of_trust::is_root_at_registry(@diem_framework, neighbor)
203+
) {
204+
continue
205+
};
182206
};
183-
// we don't re-enter the root of
184-
// trust list, because we don't
185-
// want to accumulate points from
186-
// roots vouching for each other.
187-
if(
188-
root_of_trust::is_root_at_registry(@diem_framework, neighbor)
189-
) {
190-
continue
191-
};
207+
192208

193209
// Continue search from this neighbor with reduced power
194210
let path_score = walk_from_node(
@@ -281,7 +297,7 @@ module ol_framework::page_rank_lazy {
281297
// assert initialized
282298
assert!(exists<UserTrustRecord>(user), error::invalid_state(ENOT_INITIALIZED));
283299
// get_score
284-
let _score = get_trust_score(user);
300+
let _score = set_score(user);
285301
}
286302

287303
//////// GETTERS ////////

types/src/core_types/network_playlist.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub struct HostProfile {
2121
/// First does a light port check on all peers, and eliminated unresponsive
2222
/// Then from a random list fetches the first 3 nodes to respond with a waypoint.
2323
/// picks the node with the highest waypoint.
24-
/// moves that node othe top of the seed peers vector.
24+
/// moves that node to the top of the seed peers vector.
2525
/// sets it in preferences as the default peer.
2626
impl Default for HostProfile {
2727
fn default() -> Self {

types/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ pub fn global_config_dir() -> PathBuf {
1818
.join(GLOBAL_CONFIG_DIRECTORY_0L)
1919
}
2020

21-
/// The coin scaling or decimal represenation of 1 coin in the VM. 1 coin is divisible by 1,000,000, or 6 decimals precision.
21+
/// The coin scaling or decimal representation of 1 coin in the VM. 1 coin is divisible by 1,000,000, or 6 decimals precision.
2222
pub const ONCHAIN_DECIMAL_PRECISION: u8 = 6;

0 commit comments

Comments
 (0)