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

Full transaction format with signer integration #74

Merged
merged 24 commits into from
Apr 30, 2024

Conversation

koxu1996
Copy link
Contributor

@koxu1996 koxu1996 commented Apr 22, 2024

This PR updates ASN.1 schema to compose full transaction data, and integrate Signer module with it.

Most importantly, this will unblock:

Transaction format

The following top-level type was added to kairos-tx:

  Transaction ::= SEQUENCE {
    publicKey PublicKey,
    payload SigningPayload,
    hash PayloadHash,
    algorithm SigningAlgorithm,
    signature Signature,
    ...
  }

It represents full transaction data, including public key, hash (constructed from payload), algorithm (used for signing), and signature.

Notably, kairos_tx::asn::Transaction - similarly to payload - can be deterministically serialized and deserialized from bytes.

Signer integration

Interacting with full transaction is now included in the kairos-crypto package (under tx feature flag, enabled by default). The following methods are available in a signer trait:

  • Create full transaction - CryptoSigner::sign_tx_payload(&self, payload: SigningPayload) -> Result<Transaction, CryptoError>.
  • Validate transaction signature - CryptoSigner::verify_tx(&self, tx: Transaction) -> Result<(), CryptoError>.

Those are implemented for Casper signer, with full ed25519 and secp256k1 support.

@koxu1996 koxu1996 added the demo Required for our first demo label Apr 22, 2024
@koxu1996 koxu1996 self-assigned this Apr 22, 2024
@koxu1996 koxu1996 marked this pull request as ready for review April 22, 2024 13:04
Copy link

github-actions bot commented Apr 22, 2024

File Coverage
All files 52%
kairos-test-utils/src/cctl/parsers.rs 66%
kairos-server/src/config.rs 0%
kairos-server/src/errors.rs 12%
kairos-server/src/state.rs 90%
kairos-server/src/utils.rs 22%
kairos-test-utils/src/cctl.rs 87%
kairos-test-utils/src/kairos.rs 95%
kairos-tx/src/asn.rs 48%
kairos-tx/src/error.rs 0%
kairos-server/tests/transactions.rs 85%
kairos-server/src/state/transactions.rs 57%
kairos-server/src/state/trie.rs 35%
kairos-crypto/src/implementations/casper.rs 6%
kairos-server/src/routes/deposit.rs 88%
kairos-server/src/routes/transfer.rs 90%
kairos-server/src/state/transactions/batch_state.rs 42%

Minimum allowed coverage is 60%

Generated by 🐒 cobertura-action against 578f520

Copy link
Collaborator

@marijanp marijanp left a comment

Choose a reason for hiding this comment

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

Some tests would be great

payload: kairos_tx::asn::SigningPayload,
) -> Result<kairos_tx::asn::Transaction, CryptoError> {
// Validate payload signature.
let tx_hash = kairos_tx::hash(&payload).map_err(|_e| CryptoError::TxHashingError)?;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would be great if all of these error types could take anything that is Debug and one could be able to propagate the inner errors message. I.e. I want to see what exact hashing error happened. The one that _e.to_string() would give me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 0242e4c.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't see a benefit to this CryptoSigner trait. It should instead be replaced with a sign and verify generic function.
It also does too much at this point.

  1. from_private_key_file and from_public_key should be removed and replaced with From trait implementations
  2. to_public_key can be extracted to a From trait implementation too.
  3. sign and verify could be extracted in a trait, but I would be surprised that there is nothing like this already somewhere.

Instead of all these steps, I would remove the CryptoSigner trait completely, and implement a generic function that says "if these traits are implemented ..." I will produce either this signed result or an error.

sign_tx could moreover be an alias for calling sign(tx.into()). If the ASN1 type would have a respective From trait implementation. And would moreover not require us to introduce a tx feature.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer if from_private_key_file remain a method, not a From impl.
I don't like From/Into doing IO.

I agree we don't need the CryptoSigner trait, since there is only one implementation just keep the Signer struct.

Currently this implementation signs transaction hashes.
I have my doubts about signing transaction hashes rather than transactions bodies.
It is more general, but I suspect it's a lot of overhead in a zkVM on simple transfer/withdraw payloads.

Choose a reason for hiding this comment

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

I have my doubts about signing transaction hashes rather than transactions bodies.

You have to hash the input before signing; signing algorithms take 255-bit input (for secp256k1) or 256-bit input (for ed25519). See https://crypto.stackexchange.com/a/59203

#[non_exhaustive]
pub struct Transaction {
pub public_key: PublicKey, // NOTE: Field name can be different than defined in schema, as only **order** is crucial
pub payload: SigningPayload,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I understand that you can compute the PayloadHash, I'm just wondering where the according computation happens? Or should it be added as a field here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for catching it, I forgot to add hash field - added in 3003e72.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Computing PayloadHash happens in crypto module in sign_tx_payload(). This is the only safe method of constructing fully validated transaction.

}

// Constructor for non-exhaustive transaction struct.
pub fn make_tx(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand the purpose of this function. it is basically new for a Transaction type. Not saying it should be a new.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right. I replaced this helper with constructor in 52b2854.

@Avi-D-coder
Copy link
Contributor

Slightly off topic, but could we remove nonce from deposit?
What does it mean for the nonce of a deposit to not match account nonce.
Does the L1 contract have to reverse the deposit?
I think it would be simpler to remove it and denormalize the txn encoding.

I have to do that anyway for the trie/risc0 encoding representation of transactions.

@koxu1996 koxu1996 marked this pull request as draft April 29, 2024 11:46
@koxu1996 koxu1996 marked this pull request as ready for review April 29, 2024 16:31
@koxu1996 koxu1996 requested a review from marijanp April 29, 2024 16:32
@koxu1996
Copy link
Contributor Author

Ready for re-review, tests are missing though.

Comment on lines +23 to +30
#[cfg(feature = "tx")]
fn verify_tx(&self, tx: kairos_tx::asn::Transaction) -> Result<(), CryptoError>;
#[cfg(feature = "tx")]
fn sign_tx_payload(
&self,
payload: kairos_tx::asn::SigningPayload,
) -> Result<kairos_tx::asn::Transaction, CryptoError>;

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't love feature gated parts of traits.
Generally they should be separated out into a separate trait.

I also don't like having a trait with a single impl, but these issues can be addressed in followup at a much latter date.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created follow up task - #86.

Copy link
Contributor

@Avi-D-coder Avi-D-coder left a comment

Choose a reason for hiding this comment

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

Let's merge

Copy link
Contributor

@Rom3dius Rom3dius left a comment

Choose a reason for hiding this comment

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

Good code

@koxu1996
Copy link
Contributor Author

Some tests would be great

Follow up task created - #87.

@koxu1996 koxu1996 merged commit f5fb2a6 into main Apr 30, 2024
7 checks passed
@marijanp marijanp deleted the feature/full-tx-format branch April 30, 2024 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
demo Required for our first demo
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants