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

Refactor backend following updated contracts #152

Merged
merged 13 commits into from
Sep 12, 2023
Merged

Conversation

sifnoc
Copy link
Member

@sifnoc sifnoc commented Sep 6, 2023

Update the backend API to reflect changes in the contracts.

Major changes include separating AddressOwnership from Snapshot, and introducing a new struct, Round, which is now included within Snapshot.

Modified gen_inclusion_verifier and gen_solvency_verifier scripts with using specific ptau file instead of using random.

@sifnoc sifnoc marked this pull request as ready for review September 7, 2023 08:48
zk_prover/examples/gen_solvency_verifier.rs Show resolved Hide resolved
backend/src/apis/ownership.rs Outdated Show resolved Hide resolved
})
}

// Make sure the input `addresses` in `address_ownership_proof` are not duplicated with addresses already registered on the contract.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what I can tell, this operation of making sure that the input 'addresses` ... is not being performed now so the comment is misleading. BTW I agree that we shouldn't do that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, that's why I also think that the address ownership should live inside the Round and Round should take care of it. (cc @sifnoc )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you think so? One of the main ideas of this PR was to separate AddressOwnership from Round as these are separated phases

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if they'll be performed separately in the real-world implementation. E.g., CEX can add more addresses in between the proving rounds but in each round it has to check if all the addresses have the ownership proofs submitted, so it makes sense just to submit new addresses in the beginning of the round. BTW I agree that it's good to separate address ownership into its own trait.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated comment at ce908f0

Both perspectives are valid. However, from my understanding, the AddressOwnership operation isn't intrinsically tied to Round. As such, it might not be fitting to merge AddressOwnership directly into Round at this juncture.
That being said, there could be value in creating a new struct that encompasses both functionalities.
Perhaps something like SummaOperator or SummaController?
For a CEX operator, a consolidated interface for both Round and AddressOwnership would undoubtedly be beneficial.

Copy link
Member Author

@sifnoc sifnoc Sep 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now understand your perspective. You're suggesting a Round structure similar to this:

pub struct Round<const LEVELS: usize, const N_ASSETS: usize, const N_BYTES: usize> {
    timestamp: u64,
    snapshot: Snapshot<LEVELS, N_ASSETS, N_BYTES>,
    address_ownership: AddressOwnership,
    signer: SummaSigner,
}

The following code segment, I see its alignment with your viewpoint on AddressOwnership:

require(
addressOwnershipProofs.length != 0,
"The CEX has not submitted any address ownership proofs"
);

However, regardless of the naming convention for Round, I believe there should be only one Signer.
If there are multiple signers, they might generate transactions with the same nonce.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm only talking about the encapsulation of AddressOwnership inside Round (Round holding an instance of AddressOwnership). As I imagine the future use of the system, CEX will not call any of Summa services from within CEX services, they will be called by the scheduler. If everything gets called with the same interval, it's all a "Round" of a proof of solvency.

My hypothesis is that Round and AddressOwnership are two very separate things and the Scheduler will only have to deal with Round. The soundness of this hypothesis depends on the frequency of address rotation performed by an Exchange. If they stick to the same address for long time, AddressOwnership is just called once and then just updated once in a while. On the contrary, if the switch addresses very frequently, it's likely that at every round a new proof of address ownership must be called.

I think we can stick to this now and challenge this hypothesis as soon as speak with customers. This will also inform the design of the Summa services.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, regardless of the naming convention for Round, I believe there should be only one Signer.
If there are multiple signers, they might generate transactions with the same nonce.

Can elaborate on that @sifnoc ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the current implementation, both Round and AddressOwnership have an instance of Signer, each.
The default middleware in ethers-rs does not provide a shared nonce counter between signers.
As a result, both signers might query the node using get_transaction_count for the same Account.

This can lead to a high likelihood that both signers will generate transactions with the same nonce for submit_proof_of_solvency and submit_proof_of_address_ownership.

Consequently, one of these transactions may not be included in the block.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the same Signer should be injected everywhere where needed.

backend/src/apis/ownership.rs Outdated Show resolved Hide resolved
backend/src/apis/ownership.rs Outdated Show resolved Hide resolved
backend/src/apis/round.rs Show resolved Hide resolved
backend/src/apis/round.rs Outdated Show resolved Hide resolved
backend/src/apis/fetch.rs Outdated Show resolved Hide resolved
backend/src/apis/round.rs Show resolved Hide resolved
backend/src/apis/round.rs Show resolved Hide resolved
backend/src/apis/ownership.rs Outdated Show resolved Hide resolved
let result = summa_signer
.submit_proof_of_address_ownership(owned_addresses)

let mut address_ownership_client = AddressOwnership::new(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the address ownership should be a part of the Round (similarly to Snapshot). While it's possible to submit it at any time before the proof, it's still enough to submit it in the beginning of a round. Most likely it wouldn't be called manually in the production implementation of Summa like you're calling it here. There should be some entity that controls it and Round seems to be a good candidate for that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#152 (comment) partially addresses your suggestion for now.
A potential alternative could be the Scheduler you introduced in the Service-Based Backend Architecture
Let's discuss this further in the document.

@sifnoc sifnoc mentioned this pull request Sep 11, 2023
Copy link
Member

@enricobottazzi enricobottazzi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just had a single comment on a variable name. LGTM!

#[derive(Debug, Deserialize)]
struct Record {
struct EntriesRecord {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename it to SignatureRecord as the other is named AssetRecord ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated at 31c3c59

Ok((addresses, signatures))
let assets_array: [Asset; N_ASSETS] = assets_vec.try_into().map_err(|v: Vec<Asset>| {
format!(
"Number of assets in CSV does not match the number of assets in the contract! {:?}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message is misleading, it should say something like "the number of assets doesn't match the expected"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated at 31c3c59

})
}

// Make sure the input `addresses` in `address_ownership_proof` are not duplicated with addresses already registered on the contract.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not talking about merging (similarly to how Snapshot can still live in a separate file and not inside the same file with Round). I'm only talking about the encapsulation of AddressOwnership inside Round (Round holding an instance of AddressOwnership). As I imagine the future use of the system, CEX will not call any of Summa services from within CEX services, they will be called by the scheduler. If everything gets called with the same interval, it's all a "Round" of a proof of solvency.

@sifnoc sifnoc mentioned this pull request Sep 12, 2023
@sifnoc sifnoc merged commit bbf4363 into master Sep 12, 2023
4 checks passed
@enricobottazzi enricobottazzi deleted the refactor-backend branch November 21, 2023 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove fetch API Refactor backend Add in backend readme description on how to run example.
3 participants