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

Add EthAccount #853

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
cd13579
feat: add eth_account main logic
ericnordelo Dec 12, 2023
19ce07d
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Dec 12, 2023
463d663
feat: add tests
ericnordelo Dec 15, 2023
6ce5a08
fix: workflow
ericnordelo Dec 15, 2023
e2ee218
feat: change EthPublicKey to Secp256k1Point
ericnordelo Dec 19, 2023
3fdaf15
feat: add more tests
ericnordelo Dec 20, 2023
6cdbac9
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Dec 20, 2023
16427fc
feat: add entry to CHANGELOG
ericnordelo Dec 20, 2023
135e8f1
feat: add tests for preset
ericnordelo Dec 20, 2023
f9c811a
docs: add API Reference entries
ericnordelo Dec 20, 2023
b883c6b
Update src/account/eth_account/eth_account.cairo
ericnordelo Dec 21, 2023
3c396de
feat: apply review updates
ericnordelo Dec 21, 2023
ba60238
Merge branch 'feat/migrate-eth-account-#573' of github.com:ericnordel…
ericnordelo Dec 21, 2023
34e3010
refactor: test
ericnordelo Dec 21, 2023
b40970b
feat: apply review updates
ericnordelo Dec 28, 2023
e960a4a
feat: update error messages
ericnordelo Jan 3, 2024
79c64a2
feat: apply review updates
ericnordelo Jan 5, 2024
facf8ab
Update docs/modules/ROOT/pages/api/account.adoc
ericnordelo Jan 17, 2024
ebc2e9d
feat: add tests for upgrade
ericnordelo Jan 17, 2024
1ef85b9
feat: add tests for signature
ericnordelo Jan 17, 2024
9c99ffb
Merge branch 'feat/migrate-eth-account-#573' of github.com:ericnordel…
ericnordelo Jan 17, 2024
a723d53
refactor: drop X.Y.Z in favor of last released version
ericnordelo Jan 17, 2024
f17f151
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Jan 22, 2024
ef4128c
feat: updated class hashes
ericnordelo Jan 22, 2024
de0c40c
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Jan 29, 2024
73144d5
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Jan 29, 2024
42abd67
fix: casm target
ericnordelo Jan 29, 2024
26651b3
fix: versions
ericnordelo Jan 30, 2024
97151fd
refactor: account directory
ericnordelo Jan 30, 2024
c9d50e4
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Jan 31, 2024
8a3939b
fix: comments
ericnordelo Jan 31, 2024
0f9b41c
fix: class hashes
ericnordelo Jan 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- uses: actions/checkout@v3
- uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.4.0"
scarb-version: "2.4.2"
- name: Markdown lint
uses: DavidAnson/markdownlint-cli2-action@5b7c9f74fec47e6b15667b2cc23c63dff11e449e # v9
with:
Expand Down
4 changes: 2 additions & 2 deletions Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "openzeppelin"
version = "0.8.0"
edition = "2023_01"
cairo-version = "2.4.0"
cairo-version = "2.4.2"
authors = ["OpenZeppelin Community <maintainers@openzeppelin.org>"]
description = "OpenZeppelin Contracts written in Cairo for StarkNet, a decentralized ZK Rollup"
documentation = "https://docs.openzeppelin.com/contracts-cairo"
Expand All @@ -12,7 +12,7 @@ license-file = "LICENSE"
keywords = ["openzeppelin", "starknet", "cairo", "contracts", "security", "standards"]

[dependencies]
starknet = "2.4.0"
starknet = "2.4.2"

[lib]

Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/api/account.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Account component implementing xref:ISRC6[`ISRC6`].

NOTE: Implementing xref:api/introspection.adoc#SRC5Component[SRC5Component] is a requirement for this component to be implemented.

NOTE: Every function involving signature verification, verifies with the account's current public key, using the {starknet-curve}.
NOTE: Every function involving signature verification verifies with the account's current public key using the {starknet-curve}.
ericnordelo marked this conversation as resolved.
Show resolved Hide resolved

[.contract-index#AccountComponent-Embeddable-Impls]
.Embeddable Implementations
Expand Down
4 changes: 2 additions & 2 deletions src/account/account/account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
mod AccountComponent {
use openzeppelin::account::interface;
use openzeppelin::account::utils::{TRANSACTION_VERSION, QUERY_VERSION};
use openzeppelin::account::utils::{execute_calls, is_valid_signature};
use openzeppelin::account::utils::{execute_calls, is_valid_stark_signature};
use openzeppelin::introspection::src5::SRC5Component::InternalTrait as SRC5InternalTrait;
use openzeppelin::introspection::src5::SRC5Component;
use starknet::account::Call;
Expand Down Expand Up @@ -236,7 +236,7 @@ mod AccountComponent {
self: @ComponentState<TContractState>, hash: felt252, signature: Span<felt252>
) -> bool {
let public_key = self.Account_public_key.read();
is_valid_signature(hash, public_key, signature)
is_valid_stark_signature(hash, public_key, signature)
}
}
}
2 changes: 1 addition & 1 deletion src/account/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
mod secp256k1;
mod signature;

use signature::{is_valid_signature, is_valid_eth_signature};
use signature::{is_valid_stark_signature, is_valid_eth_signature};
use starknet::account::Call;

const TRANSACTION_VERSION: felt252 = 1;
Expand Down
146 changes: 5 additions & 141 deletions src/account/utils/secp256k1.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts for Cairo vX.Y.Z (account/utils/secp256k1.cairo)

use core::fmt::{Debug, Formatter, Error};
use starknet::SyscallResultTrait;
use starknet::secp256_trait::Secp256PointTrait;
use starknet::secp256k1::{
Expand Down Expand Up @@ -60,146 +61,9 @@ impl Secp256k1PointPartialEq of PartialEq<Secp256k1Point> {
}
}

#[cfg(test)]
mod test {
use starknet::secp256_trait::Secp256PointTrait;
use starknet::secp256k1::Secp256k1Impl;
use super::{
SyscallResultTrait, Secp256k1Point, Secp256k1PointSerde, Secp256k1PointPartialEq,
Secp256k1PointStorePacking as StorePacking
};

#[test]
fn test_pack_big_secp256k1_points() {
let (big_point_1, big_point_2) = get_points();
let curve_size = Secp256k1Impl::get_curve_size();

// Check point 1

let (xlow, xhigh_and_parity) = StorePacking::pack(big_point_1);
let xhigh_and_parity: u256 = xhigh_and_parity.into();

let x = u256 {
low: xlow.try_into().unwrap(), high: (xhigh_and_parity / 2).try_into().unwrap()
};
let parity = xhigh_and_parity % 2 == 1;

assert(x == curve_size, 'Invalid x');
assert(parity == true, 'Invalid parity');

// Check point 2

let (xlow, xhigh_and_parity) = StorePacking::pack(big_point_2);
let xhigh_and_parity: u256 = xhigh_and_parity.into();

let x = u256 {
low: xlow.try_into().unwrap(), high: (xhigh_and_parity / 2).try_into().unwrap()
};
let parity = xhigh_and_parity % 2 == 1;

assert(x == curve_size, 'Invalid x');
assert(parity == false, 'Invalid parity');
}

#[test]
fn test_unpack_big_secp256k1_points() {
let (big_point_1, big_point_2) = get_points();
let curve_size = Secp256k1Impl::get_curve_size();

// Check point 1

let (expected_x, expected_y) = big_point_1.get_coordinates().unwrap();

let (xlow, xhigh_and_parity) = StorePacking::pack(big_point_1);
let (x, y) = StorePacking::unpack((xlow, xhigh_and_parity)).get_coordinates().unwrap();

assert(x == expected_x, 'Invalid x');
assert(y == expected_y, 'Invalid y');

// Check point 2

let (expected_x, expected_y) = big_point_2.get_coordinates().unwrap();

let (xlow, xhigh_and_parity) = StorePacking::pack(big_point_2);
let (x, y) = StorePacking::unpack((xlow, xhigh_and_parity)).get_coordinates().unwrap();

assert(x == expected_x, 'Invalid x');
}

#[test]
fn test_secp256k1_serialization() {
let (big_point_1, big_point_2) = get_points();
let curve_size = Secp256k1Impl::get_curve_size();

let mut serialized_point = array![];
let mut expected_serialization = array![];

// Check point 1

big_point_1.serialize(ref serialized_point);
big_point_1.get_coordinates().unwrap().serialize(ref expected_serialization);

assert(serialized_point == expected_serialization, 'Invalid serialization');

// Check point 2

big_point_2.serialize(ref serialized_point);
big_point_2.get_coordinates().unwrap().serialize(ref expected_serialization);

assert(serialized_point == expected_serialization, 'Invalid serialization');
}

#[test]
fn test_secp256k1_deserialization() {
let (big_point_1, big_point_2) = get_points();
let curve_size = Secp256k1Impl::get_curve_size();

// Check point 1

let mut expected_serialization = array![];

big_point_1.get_coordinates().unwrap().serialize(ref expected_serialization);
let mut expected_serialization = expected_serialization.span();
let deserialized_point = Secp256k1PointSerde::deserialize(ref expected_serialization)
.unwrap();

assert(big_point_1 == deserialized_point, 'Invalid deserialization');

// Check point 2

let mut expected_serialization = array![];

big_point_2.get_coordinates().unwrap().serialize(ref expected_serialization);
let mut expected_serialization = expected_serialization.span();
let deserialized_point = Secp256k1PointSerde::deserialize(ref expected_serialization)
.unwrap();

assert(big_point_2 == deserialized_point, 'Invalid deserialization');
}

#[test]
fn test_partial_eq() {
let (big_point_1, big_point_2) = get_points();

assert(big_point_1 == big_point_1, 'Invalid equality');
assert(big_point_2 == big_point_2, 'Invalid equality');
assert(big_point_1 != big_point_2, 'Invalid equality');
assert(big_point_2 != big_point_1, 'Invalid equality');
}

//
// Helpers
//

fn get_points() -> (Secp256k1Point, Secp256k1Point) {
let curve_size = Secp256k1Impl::get_curve_size();
let point_1 = Secp256k1Impl::secp256_ec_get_point_from_x_syscall(curve_size, true)
.unwrap_syscall()
.unwrap();
let point_2 = Secp256k1Impl::secp256_ec_get_point_from_x_syscall(curve_size, false)
.unwrap_syscall()
.unwrap();

(point_1, point_2)
impl DebugSecp256k1Point of core::fmt::Debug<Secp256k1Point> {
fn fmt(self: @Secp256k1Point, ref f: Formatter) -> Result<(), Error> {
let (x, y) = (*self).get_coordinates().unwrap();
write!(f, "({x:?},{y:?})")
}
}
4 changes: 3 additions & 1 deletion src/account/utils/signature.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use starknet::eth_signature::Signature;
use starknet::secp256_trait::{is_signature_entry_valid, recover_public_key};
use starknet::secp256k1::Secp256k1Point;

fn is_valid_signature(msg_hash: felt252, public_key: felt252, signature: Span<felt252>) -> bool {
fn is_valid_stark_signature(
msg_hash: felt252, public_key: felt252, signature: Span<felt252>
) -> bool {
let valid_length = signature.len() == 2;

if valid_length {
Expand Down
1 change: 1 addition & 0 deletions src/tests/account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ mod test_account;
mod test_dual_account;
mod test_dual_eth_account;
mod test_eth_account;
mod test_secp256k1;
20 changes: 11 additions & 9 deletions src/tests/account/test_dual_eth_account.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use openzeppelin::account::eth_account::dual_eth_account::{
use openzeppelin::account::eth_account::interface::{
EthAccountABIDispatcherTrait, EthAccountABIDispatcher
};
use openzeppelin::account::utils::secp256k1::{Secp256k1PointPartialEq, Secp256k1PointSerde};
use openzeppelin::account::utils::secp256k1::{
DebugSecp256k1Point, Secp256k1PointPartialEq, Secp256k1PointSerde
martriay marked this conversation as resolved.
Show resolved Hide resolved
};
use openzeppelin::introspection::interface::ISRC5_ID;
use openzeppelin::tests::account::test_eth_account::SIGNED_TX_DATA;
use openzeppelin::tests::mocks::eth_account_mocks::{
Expand Down Expand Up @@ -70,7 +72,7 @@ fn test_dual_set_public_key() {

let new_public_key = NEW_ETH_PUBKEY();
snake_dispatcher.set_public_key(new_public_key);
assert(target.get_public_key() == new_public_key, 'Should return NEW_ETH_PUBKEY');
assert_eq!(target.get_public_key(), new_public_key);
}

#[test]
Expand All @@ -90,7 +92,7 @@ fn test_dual_set_public_key_exists_and_panics() {
#[test]
fn test_dual_get_public_key() {
let (snake_dispatcher, _) = setup_snake();
assert(snake_dispatcher.get_public_key() == ETH_PUBKEY(), 'Should return ETH_PUBKEY');
assert_eq!(snake_dispatcher.get_public_key(), ETH_PUBKEY());
}

#[test]
Expand Down Expand Up @@ -120,7 +122,7 @@ fn test_dual_is_valid_signature() {
target.set_public_key(data.public_key);

let is_valid = snake_dispatcher.is_valid_signature(hash, serialized_signature);
assert(is_valid == 'VALID', 'Should accept valid signature');
assert_eq!(is_valid, starknet::VALIDATED);
}

#[test]
Expand All @@ -146,7 +148,7 @@ fn test_dual_is_valid_signature_exists_and_panics() {
#[test]
fn test_dual_supports_interface() {
let (snake_dispatcher, target) = setup_snake();
assert(snake_dispatcher.supports_interface(ISRC5_ID), 'Should implement ISRC5');
assert!(snake_dispatcher.supports_interface(ISRC5_ID), "Should implement ISRC5");
}

#[test]
Expand Down Expand Up @@ -175,7 +177,7 @@ fn test_dual_setPublicKey() {
testing::set_contract_address(camel_dispatcher.contract_address);

camel_dispatcher.set_public_key(new_public_key);
assert(target.getPublicKey() == new_public_key, 'Should return NEW_ETH_PUBKEY');
assert_eq!(target.getPublicKey(), new_public_key);
}

#[test]
Expand All @@ -188,7 +190,7 @@ fn test_dual_setPublicKey_exists_and_panics() {
#[test]
fn test_dual_getPublicKey() {
let (camel_dispatcher, _) = setup_camel();
assert(camel_dispatcher.get_public_key() == ETH_PUBKEY(), 'Should return ETH_PUBKEY');
assert_eq!(camel_dispatcher.get_public_key(), ETH_PUBKEY());
}

#[test]
Expand All @@ -211,7 +213,7 @@ fn test_dual_isValidSignature() {
target.setPublicKey(data.public_key);

let is_valid = camel_dispatcher.is_valid_signature(hash, serialized_signature);
assert(is_valid == 'VALID', 'Should accept valid signature');
assert_eq!(is_valid, starknet::VALIDATED);
ericnordelo marked this conversation as resolved.
Show resolved Hide resolved
}

#[test]
Expand All @@ -227,7 +229,7 @@ fn test_dual_isValidSignature_exists_and_panics() {
#[test]
fn test_dual_supportsInterface() {
let (camel_dispatcher, _) = setup_camel();
assert(camel_dispatcher.supports_interface(ISRC5_ID), 'Should implement ISRC5');
assert!(camel_dispatcher.supports_interface(ISRC5_ID), "Should implement ISRC5");
}

#[test]
Expand Down