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

Supports multiple accounts with the same Passkey #17

Merged
merged 25 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions l1-contracts/scripts/upgrade-consistency-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ const maxNumberOfHyperchains = 100;
const expectedStoredBatchHashZero = "0x1574fa776dec8da2071e5f20d71840bfcbd82c2bca9ad68680edfedde1710bc4";
const expectedL2BridgeAddress = "0x11f943b2c77b743AB90f4A0Ae7d5A4e7FCA3E102";
const expectedL1LegacyBridge = "0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063";
const expectedGenesisBatchCommitment = "0xd35d307517352f1d30fbf1bc69275e465c713ab9a4683ca1979fb26857ebbd59";
const expectedGenesisBatchCommitment = "0x6e98202335f42b75a15c864849a5d60a9acbbb8fb992c37b0d08c11d1ba416b9";
const expectedIndexRepeatedStorageChanges = BigNumber.from(56);
const expectedProtocolVersion = BigNumber.from(2).pow(32).mul(24);

const expectedGenesisRoot = "0xa67cf425c525514dd007c84c4ef6b3fa48773018172074fa8f04aaca56803046";
const expectedGenesisRoot = "0xeb50f8acddfe196e2219c2c1bca2264316d895f2c8ab666556e9870923bc55a3";
const expectedRecursionNodeLevelVkHash = "0xf520cd5b37e74e19fdb369c8d676a04dce8a19457497ac6686d2bb95d94109c8";
const expectedRecursionLeafLevelVkHash = "0xf9664f4324c1400fa5c3822d667f30e873f53f1b8033180cd15fe41c1e2355c6";
const expectedRecursionCircuitsSetVksHash = "0x0000000000000000000000000000000000000000000000000000000000000000";
const expectedBootloaderHash = "0x010008e742608b21bf7eb23c1a9d0602047e3618b464c9b59c0fba3b3d7ab66e";
const expectedDefaultAccountHash = "0x010008af9fae3a9468529c82b7d217b7287b0842b43a1ec80dcdae91d4c4d4fa";
const expectedDefaultAccountHash = "0x010008a95b449ac82e20793b81c505f8483a4e1b6caaac598b6e416f6d845f4b";

const validatorOne = process.env.ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR!;

Expand Down
8 changes: 4 additions & 4 deletions system-contracts/SystemContractsHashes.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
"contractName": "DefaultAccount",
"bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json",
"sourceCodePath": "contracts-preprocessed/DefaultAccount.sol",
"bytecodeHash": "0x010008af9fae3a9468529c82b7d217b7287b0842b43a1ec80dcdae91d4c4d4fa",
"sourceCodeHash": "0xff15862747e3f4c7bd7494fb36c859f42f582740a8f39ecce1feca01927f140c"
"bytecodeHash": "0x010008a95b449ac82e20793b81c505f8483a4e1b6caaac598b6e416f6d845f4b",
"sourceCodeHash": "0x114a721e1744fb10db1f33daf1301f5d2c168717ee44fe912a01bdcd4d1e202d"
},
{
"contractName": "EmptyContract",
Expand Down Expand Up @@ -101,8 +101,8 @@
"contractName": "PasskeyBinder",
"bytecodePath": "artifacts-zk/contracts-preprocessed/PasskeyBinder.sol/PasskeyBinder.json",
"sourceCodePath": "contracts-preprocessed/PasskeyBinder.sol",
"bytecodeHash": "0x010001159da38a1521785c5c97690aa34020d8a7436f563f21ef20a05149cc39",
"sourceCodeHash": "0x60baf72f69451fd70244dae59d6fd7ce32e902f410766bea0b663d802b3f76ca"
"bytecodeHash": "0x010001118ac50d2751a65e989bf6bceb653d22b8fe10ba3bca42aeac5bcada26",
"sourceCodeHash": "0x392d0034f12d22358783f7a88866352c45c5ce5332ee41b1d044b905b202e237"
},
{
"contractName": "PubdataChunkPublisher",
Expand Down
5 changes: 2 additions & 3 deletions system-contracts/contracts/DefaultAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,9 @@ contract DefaultAccount is IAccount {
uint32(gasleft()),
address(PASSKEY_BINDER),
0,
abi.encodeCall(IPasskeyBinder.getAuthorizedKey, (_credentialIdHash))
abi.encodeCall(IPasskeyBinder.getAuthorizedKey, (address(this), _credentialIdHash))
);
(address passkeyOwner, uint256 x, uint256 y) = abi.decode(returnData, (address, uint256, uint256));
require(passkeyOwner == address(this), "Passkey is not owned by the account");
(uint256 x, uint256 y) = abi.decode(returnData, (uint256, uint256));
require(x != 0 && y != 0, "Passkey is not set");
return (x, y);
}
Expand Down
64 changes: 30 additions & 34 deletions system-contracts/contracts/PasskeyBinder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,23 @@ contract PasskeyBinder is IPasskeyBinder {
}

mapping(address account => EnumerableSet.Bytes32Set credentialIdHashSet) private accountToCredentialIdHashSet;
mapping(bytes32 credentialIdHash => AuthorizedKey) private authorizedKeys;
mapping(bytes32 keyIdHash => AuthorizedKey) private authorizedKeys;

/// @dev Event emitted when a P256 key is added
event AddedP256PublicKey(bytes32 indexed credentialIdHash, address indexed owner, uint256 x, uint256 y);

/// @dev Event emitted when a P256 key is removed
event RemovedP256PublicKey(bytes32 indexed credentialIdHash, address indexed owner, uint256 x, uint256 y);

event RemovedP256PublicKey(bytes32 indexed credentialIdHash, address indexed owner);
/// @dev Error emitted when a P256 key is not on the curve
error KeyNotOnCurve(uint256 x, uint256 y);
/// @dev Error emitted when an empty credential id hash is attempted to be added
error InvalidCredentialIdHash();
/// @dev Error emitted when a P256 key is already stored and attempted to be added
error KeyAlreadyExists(bytes32 credentialIdHash);
/// @dev Error emitted when a P256 key is not stored and attempted to be removed
error KeyDoesNotExist(bytes32 credentialIdHash);
/// @dev Error emitted when a P256 key is not owned by the caller
error DoesNotOwner(bytes32 credentialIdHash);
error DoesNotOwnershipOfRights(bytes32 credentialIdHash);
/// @dev Error emitted when a P256 key is attempted to be add by not EOA
error DoesNotEOA();

/**
* @notice Adds a P256 public key to the contract
* @notice Adding a P256 public key to the caller
* @param _credentialIdHash The ID Hash of the credential to add
* @param _x The X value of the public key
* @param _y The Y value of the public key
Expand All @@ -65,50 +59,52 @@ contract PasskeyBinder is IPasskeyBinder {

if (_credentialIdHash == bytes32(0)) revert InvalidCredentialIdHash();

AuthorizedKey storage authorizedKey = authorizedKeys[_credentialIdHash];

if (authorizedKey.owner != address(0)) revert KeyAlreadyExists(_credentialIdHash);
bytes32 keyIdHash = keccak256(abi.encodePacked(_credentialIdHash, sender));
address authorizedKeyOwner = authorizedKeys[keyIdHash].owner;
if (authorizedKeyOwner == address(0)) {
authorizedKeys[keyIdHash] = AuthorizedKey(sender, P256PublicKey(_x, _y));
}

authorizedKeys[_credentialIdHash] = AuthorizedKey({owner: sender, publicKey: P256PublicKey({x: _x, y: _y})});
accountToCredentialIdHashSet[sender].add(_credentialIdHash);

emit AddedP256PublicKey(_credentialIdHash, sender, _x, _y);
}

/**
* @notice Removes a P256 public key from the contract
* @notice Removes P256 public key for caller
* @param _credentialIdHash The ID Hash of the credential to remove
*/
function removeP256PublicKey(bytes32 _credentialIdHash) external {
address sender = msg.sender;
AuthorizedKey memory authorizedKey = authorizedKeys[_credentialIdHash];
address publicKeyOwner = authorizedKey.owner;

if (publicKeyOwner == address(0)) revert KeyDoesNotExist(_credentialIdHash);
if (publicKeyOwner != sender) revert DoesNotOwner(_credentialIdHash);
bool success = accountToCredentialIdHashSet[sender].remove(_credentialIdHash);
if (!success) revert DoesNotOwnershipOfRights(_credentialIdHash);

uint256 x = authorizedKey.publicKey.x;
uint256 y = authorizedKey.publicKey.y;

delete authorizedKeys[_credentialIdHash];
accountToCredentialIdHashSet[sender].remove(_credentialIdHash);

emit RemovedP256PublicKey(_credentialIdHash, sender, x, y);
emit RemovedP256PublicKey(_credentialIdHash, sender);
}

/**
* @notice Returns authorized key infos by credential id hash
* @param _account The account to get the authorized key
* @param _credentialIdHash The ID Hash of the credential to get
* @return owner The owner of the public key
* @return x The X value of the public key
* @return y The Y value of the public key
*/
function getAuthorizedKey(bytes32 _credentialIdHash) external view returns (address owner, uint256 x, uint256 y) {
AuthorizedKey memory authorizedKey = authorizedKeys[_credentialIdHash];

owner = authorizedKey.owner;
x = authorizedKey.publicKey.x;
y = authorizedKey.publicKey.y;
function getAuthorizedKey(
address _account,
bytes32 _credentialIdHash
) external view returns (uint256 x, uint256 y) {
EnumerableSet.Bytes32Set storage credentialIdHashSet = accountToCredentialIdHashSet[_account];
bool ownershipOfRight = credentialIdHashSet.contains(_credentialIdHash);

if (ownershipOfRight) {
bytes32 keyIdHash = keccak256(abi.encodePacked(_credentialIdHash, _account));
P256PublicKey memory publicKey = authorizedKeys[keyIdHash].publicKey;
x = publicKey.x;
y = publicKey.y;
} else {
x = 0;
y = 0;
}
}

/**
Expand Down
6 changes: 3 additions & 3 deletions system-contracts/contracts/interfaces/IPasskeyBinder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ pragma solidity 0.8.20;
interface IPasskeyBinder {
/**
* @notice Returns authorized key infos by credential id hash
* @param credentialIdHash The ID Hash of the credential to get
* @return owner The owner of the public key
* @param _account The account to get the authorized key
* @param _credentialIdHash The ID Hash of the credential to get
* @return x The X value of the public key
* @return y The Y value of the public key
*/
function getAuthorizedKey(bytes32 credentialIdHash) external view returns (address owner, uint256 x, uint256 y);
function getAuthorizedKey(address _account, bytes32 _credentialIdHash) external view returns (uint256 x, uint256 y);

/**
* @notice Returns the number of credential id hash set length
Expand Down
Loading