Skip to content

Commit

Permalink
Merge pull request MystenLabs#292 from MystenLabs/add-authenticator
Browse files Browse the repository at this point in the history
[Object Ownership MystenLabs#1] Add Authenticator
  • Loading branch information
lxfind authored Jan 31, 2022
2 parents 650daaf + b8f6ea7 commit 7f7c115
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 65 deletions.
4 changes: 2 additions & 2 deletions fastpay_core/src/authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl AuthorityState {
// Additional checks for mutable objects
// Check the transaction sender is also the object owner
fp_ensure!(
order.sender() == &object.owner,
object.owner.is_address(order.sender()),
FastPayError::IncorrectSigner
);

Expand Down Expand Up @@ -340,7 +340,7 @@ impl AuthorityState {
});
}

output_object.transfer(recipient);
output_object.transfer(Authenticator::Address(recipient));
temporary_store.write_object(output_object);
Ok(ExecutionStatus::Success)
}
Expand Down
10 changes: 5 additions & 5 deletions fastpay_core/src/authority/authority_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct AuthorityStore {
/// composite key of the FastPayAddress of their owner and the object ID of the object.
/// This composite index allows an efficient iterator to list all objected currently owned
/// by a specific user, and their object reference.
owner_index: DBMap<(FastPayAddress, ObjectID), ObjectRef>,
owner_index: DBMap<(Authenticator, ObjectID), ObjectRef>,

/// This is map between the transaction digest and signed orders found in the `order_lock`.
/// NOTE: after a lock is deleted the corresponding entry here could be deleted, but right
Expand Down Expand Up @@ -105,17 +105,17 @@ impl AuthorityStore {

// Methods to read the store

// TODO: add object owner index to improve performance https://github.com/MystenLabs/fastnft/issues/127
pub fn get_account_objects(
&self,
account: FastPayAddress,
) -> Result<Vec<ObjectRef>, FastPayError> {
let auth = Authenticator::Address(account);
Ok(self
.owner_index
.iter()
// The object id [0; 16] is the smallest possible
.skip_to(&(account, AccountAddress::ZERO))?
.take_while(|((owner, _id), _object_ref)| (owner == &account))
// The object id 0 is the smallest possible
.skip_to(&(auth, ObjectID::ZERO))?
.take_while(|((owner, _id), _object_ref)| (owner == &auth))
.map(|((_owner, _id), object_ref)| object_ref)
.collect())
}
Expand Down
6 changes: 3 additions & 3 deletions fastpay_core/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ where
async fn get_strong_majority_owner(
&self,
object_id: ObjectID,
) -> Option<(FastPayAddress, SequenceNumber)> {
) -> Option<(Authenticator, SequenceNumber)> {
let request = ObjectInfoRequest {
object_id,
request_sequence_number: None,
Expand Down Expand Up @@ -1073,12 +1073,12 @@ where
.unwrap_or_default();
// only update if data is new
if old_seq < seq {
if owner == self.address {
if owner.is_address(&self.address) {
self.insert_object(&object_ref, &digest);
} else {
self.remove_object(&object_id);
}
} else if old_seq == seq && owner == self.address {
} else if old_seq == seq && owner.is_address(&self.address) {
// ObjectRef can be 1 version behind because it's only updated after confirmation.
self.object_refs.insert(object_id, object_ref);
}
Expand Down
18 changes: 9 additions & 9 deletions fastpay_core/src/unit_tests/authority_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ async fn test_handle_move_order() {
.object_state(&created_object_id)
.await
.unwrap();
assert_eq!(created_obj.owner, sender,);
assert!(created_obj.owner.is_address(&sender));
assert_eq!(created_obj.id(), created_object_id);
assert_eq!(created_obj.version(), OBJECT_START_VERSION);

Expand Down Expand Up @@ -808,7 +808,7 @@ async fn test_handle_confirmation_order_ok() {
// Key check: the ownership has changed

let new_account = authority_state.object_state(&object_id).await.unwrap();
assert_eq!(recipient, new_account.owner);
assert!(new_account.owner.is_address(&recipient));
assert_eq!(next_sequence_number, new_account.version());
assert_eq!(None, info.signed_order);
let opt_cert = {
Expand Down Expand Up @@ -1068,7 +1068,7 @@ async fn test_authority_persist() {

// Check the object is present
assert_eq!(obj2.id(), object_id);
assert_eq!(obj2.owner, recipient);
assert!(obj2.owner.is_address(&recipient));
}

async fn call_move(
Expand Down Expand Up @@ -1169,7 +1169,7 @@ async fn test_hero() {
.await;
assert_eq!(effects.status, ExecutionStatus::Success);
let (admin_object, admin_object_owner) = effects.created[0];
assert_eq!(admin_object_owner, admin);
assert!(admin_object_owner.is_address(&admin));

// 5. Create Trusted Coin Treasury.
let effects = call_move(
Expand All @@ -1186,7 +1186,7 @@ async fn test_hero() {
.await;
assert_eq!(effects.status, ExecutionStatus::Success);
let (cap, cap_owner) = effects.created[0];
assert_eq!(cap_owner, player);
assert!(cap_owner.is_address(&player));

// 6. Mint 500 EXAMPLE TrustedCoin.
let effects = call_move(
Expand All @@ -1204,7 +1204,7 @@ async fn test_hero() {
assert_eq!(effects.status, ExecutionStatus::Success);
assert_eq!(effects.mutated.len(), 1); // cap
let (coin, coin_owner) = effects.created[0];
assert_eq!(coin_owner, player);
assert!(coin_owner.is_address(&player));

// 7. Purchase a sword using 500 coin. This sword will have magic = 4, sword_strength = 5.
let effects = call_move(
Expand All @@ -1222,9 +1222,9 @@ async fn test_hero() {
assert_eq!(effects.status, ExecutionStatus::Success);
assert_eq!(effects.mutated.len(), 1); // coin
let (hero, hero_owner) = effects.created[0];
assert_eq!(hero_owner, player);
assert!(hero_owner.is_address(&player));
// The payment goes to the admin.
assert_eq!(effects.mutated[0].1, admin);
assert!(effects.mutated[0].1.is_address(&admin));

// 8. Verify the hero is what we exepct with strength 5.
let effects = call_move(
Expand Down Expand Up @@ -1261,7 +1261,7 @@ async fn test_hero() {
.await;
assert_eq!(effects.status, ExecutionStatus::Success);
let (boar, boar_owner) = effects.created[0];
assert_eq!(boar_owner, player);
assert!(boar_owner.is_address(&player));

// 10. Slay the boar!
let effects = call_move(
Expand Down
99 changes: 78 additions & 21 deletions fastpay_core/src/unit_tests/client_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,17 @@ fn test_get_strong_majority_owner() {
let client = init_local_client_state(authority_objects).await;
assert_eq!(
client.get_strong_majority_owner(object_id_1).await,
Some((client.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(client.address),
SequenceNumber::from(0)
))
);
assert_eq!(
client.get_strong_majority_owner(object_id_2).await,
Some((client.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(client.address),
SequenceNumber::from(0)
))
);

let object_id_1 = ObjectID::random();
Expand All @@ -276,7 +282,10 @@ fn test_get_strong_majority_owner() {
assert_eq!(client.get_strong_majority_owner(object_id_2).await, None);
assert_eq!(
client.get_strong_majority_owner(object_id_3).await,
Some((client.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(client.address),
SequenceNumber::from(0)
))
);
});
}
Expand All @@ -298,11 +307,17 @@ fn test_initiating_valid_transfer() {
let mut sender = rt.block_on(init_local_client_state(authority_objects));
assert_eq!(
rt.block_on(sender.get_strong_majority_owner(object_id_1)),
Some((sender.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(sender.address),
SequenceNumber::from(0)
))
);
assert_eq!(
rt.block_on(sender.get_strong_majority_owner(object_id_2)),
Some((sender.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(sender.address),
SequenceNumber::from(0)
))
);
let certificate = rt
.block_on(sender.transfer_object(object_id_1, gas_object, recipient))
Expand All @@ -316,11 +331,14 @@ fn test_initiating_valid_transfer() {
assert_eq!(sender.pending_transfer, None);
assert_eq!(
rt.block_on(sender.get_strong_majority_owner(object_id_1)),
Some((recipient, SequenceNumber::from(1)))
Some((Authenticator::Address(recipient), SequenceNumber::from(1)))
);
assert_eq!(
rt.block_on(sender.get_strong_majority_owner(object_id_2)),
Some((sender.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(sender.address),
SequenceNumber::from(0)
))
);
// valid since our test authority should not update its certificate set
compare_certified_orders(
Expand Down Expand Up @@ -359,7 +377,7 @@ fn test_initiating_valid_transfer_despite_bad_authority() {
assert_eq!(sender.pending_transfer, None);
assert_eq!(
rt.block_on(sender.get_strong_majority_owner(object_id)),
Some((recipient, SequenceNumber::from(1)))
Some((Authenticator::Address(recipient), SequenceNumber::from(1)))
);
// valid since our test authority shouldn't update its certificate set
compare_certified_orders(
Expand Down Expand Up @@ -398,7 +416,10 @@ fn test_initiating_transfer_low_funds() {
// assert_eq!(sender.pending_transfer, None);
assert_eq!(
rt.block_on(sender.get_strong_majority_owner(object_id_1)),
Some((sender.address, SequenceNumber::from(0))),
Some((
Authenticator::Address(sender.address),
SequenceNumber::from(0)
)),
);
assert_eq!(
rt.block_on(sender.get_strong_majority_owner(object_id_2)),
Expand Down Expand Up @@ -432,12 +453,18 @@ async fn test_bidirectional_transfer() {
// Confirm client1 have ownership of the object.
assert_eq!(
client1.get_strong_majority_owner(object_id).await,
Some((client1.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(client1.address),
SequenceNumber::from(0)
))
);
// Confirm client2 doesn't have ownership of the object.
assert_eq!(
client2.get_strong_majority_owner(object_id).await,
Some((client1.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(client1.address),
SequenceNumber::from(0)
))
);
// Transfer object to client2.
let certificate = client1
Expand All @@ -450,12 +477,18 @@ async fn test_bidirectional_transfer() {
// Confirm client1 lose ownership of the object.
assert_eq!(
client1.get_strong_majority_owner(object_id).await,
Some((client2.address, SequenceNumber::from(1)))
Some((
Authenticator::Address(client2.address),
SequenceNumber::from(1)
))
);
// Confirm client2 acquired ownership of the object.
assert_eq!(
client2.get_strong_majority_owner(object_id).await,
Some((client2.address, SequenceNumber::from(1)))
Some((
Authenticator::Address(client2.address),
SequenceNumber::from(1)
))
);

// Confirm certificate is consistent between authorities and client.
Expand All @@ -474,7 +507,10 @@ async fn test_bidirectional_transfer() {
// Confirm sequence number are consistent between clients.
assert_eq!(
client2.get_strong_majority_owner(object_id).await,
Some((client2.address, SequenceNumber::from(1)))
Some((
Authenticator::Address(client2.address),
SequenceNumber::from(1)
))
);

// Transfer the object back to Client1
Expand All @@ -488,7 +524,10 @@ async fn test_bidirectional_transfer() {
// Confirm client2 lose ownership of the object.
assert_eq!(
client2.get_strong_majority_owner(object_id).await,
Some((client1.address, SequenceNumber::from(2)))
Some((
Authenticator::Address(client1.address),
SequenceNumber::from(2)
))
);
assert_eq!(
client2.get_strong_majority_sequence_number(object_id).await,
Expand All @@ -497,7 +536,10 @@ async fn test_bidirectional_transfer() {
// Confirm client1 acquired ownership of the object.
assert_eq!(
client1.get_strong_majority_owner(object_id).await,
Some((client1.address, SequenceNumber::from(2)))
Some((
Authenticator::Address(client1.address),
SequenceNumber::from(2)
))
);

// Should fail if Client 2 double spend the object
Expand Down Expand Up @@ -539,7 +581,10 @@ fn test_receiving_unconfirmed_transfer() {
// ..but not confirmed remotely, hence an unchanged balance and sequence number.
assert_eq!(
rt.block_on(client1.get_strong_majority_owner(object_id)),
Some((client1.address, SequenceNumber::from(0)))
Some((
Authenticator::Address(client1.address),
SequenceNumber::from(0)
))
);
assert_eq!(
rt.block_on(client1.get_strong_majority_sequence_number(object_id)),
Expand All @@ -549,7 +594,10 @@ fn test_receiving_unconfirmed_transfer() {
rt.block_on(client2.receive_object(&certificate)).unwrap();
assert_eq!(
rt.block_on(client2.get_strong_majority_owner(object_id)),
Some((client2.address, SequenceNumber::from(1)))
Some((
Authenticator::Address(client2.address),
SequenceNumber::from(1)
))
);
}

Expand Down Expand Up @@ -620,7 +668,10 @@ async fn test_client_state_sync_with_transferred_object() {
// Confirm client2 acquired ownership of the object.
assert_eq!(
client2.get_strong_majority_owner(object_id).await,
Some((client2.address, SequenceNumber::from(1)))
Some((
Authenticator::Address(client2.address),
SequenceNumber::from(1)
))
);

// Client 2's local object_id and cert should be empty before sync
Expand Down Expand Up @@ -903,7 +954,10 @@ async fn test_move_calls_object_transfer() {
.unwrap();

// Confirm new owner
assert_eq!(transferred_obj_info.object.owner, client2.address);
assert!(transferred_obj_info
.object
.owner
.is_address(&client2.address));
}

#[tokio::test]
Expand Down Expand Up @@ -1378,7 +1432,10 @@ async fn test_move_calls_object_transfer_and_freeze() {
.unwrap();

// Confirm new owner
assert_eq!(transferred_obj_info.object.owner, client2.address);
assert!(transferred_obj_info
.object
.owner
.is_address(&client2.address));

// Confirm read only
assert!(transferred_obj_info.object.is_read_only());
Expand Down
Loading

0 comments on commit 7f7c115

Please sign in to comment.