-
Notifications
You must be signed in to change notification settings - Fork 87
Support Ledger clear signing #1603
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
base: development
Are you sure you want to change the base?
Conversation
# Ledger constants | ||
STARKNET_CLA = 0x5A | ||
EIP_2645_PURPOSE = 0x80000A55 | ||
EIP_2645_PATH_LENGTH = 6 | ||
PUBLIC_KEY_RESPONSE_LENGTH = 65 | ||
SIGNATURE_RESPONSE_LENGTH = 65 | ||
VERSION_RESPONSE_LENGTH = 3 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: These variables aren't used across multiple files so let's keep them in the dedicated (ledger) one.
recipient_address = ( | ||
0x1323CACBC02B4AAED9BB6B24D121FB712D8946376040990F2F2FA0DCF17BB5B | ||
) | ||
recipient_address = 0x123 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: 0x123
is better as an example address.
@@ -2,10 +2,13 @@ | |||
"version": 1, | |||
"rules": [ | |||
{ | |||
"text": "Confirm Hash to sign", | |||
"conditions": [], | |||
"text": "Blind igning", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pytest.mark.parametrize( | ||
"transaction", | ||
[ | ||
InvokeV3( | ||
version=3, | ||
signature=[], | ||
nonce=1, | ||
resource_bounds=MAX_RESOURCE_BOUNDS_SEPOLIA, | ||
calldata=[ | ||
1, | ||
2009894490435840142178314390393166646092438090257831307886760648929397478285, | ||
232670485425082704932579856502088130646006032362877466777181098476241604910, | ||
3, | ||
0x123, | ||
100, | ||
0, | ||
], | ||
sender_address=0x123, | ||
), | ||
DeployAccountV3( | ||
class_hash=0x123, | ||
contract_address_salt=0x123, | ||
constructor_calldata=[1, 2, 3], | ||
version=3, | ||
signature=[], | ||
nonce=0, | ||
resource_bounds=MAX_RESOURCE_BOUNDS_SEPOLIA, | ||
), | ||
], | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: We can't use mocks for clear singing as under the hood we're converting values from tx fields to bytes, and we would get TypeError: can't concat Mock to bytes
.
.github/workflows/checks.yml
Outdated
DEVNET_SHA: fc5a2753a2eedcc27eed7a4fae3ecac08c2ca1b4 | ||
LEDGER_APP_SHA: db93a5e33d00bd44752fdc8c07aefcffa08d91c3 | ||
LEDGER_APP_DEV_TOOLS_SHA: a037d42181f4bed9694246256e2c9e2a899e775c302a9c6482c81f87c28e1432 | ||
DEVNET_SHA: fc5a2753a2eedcc27eed7a4fae3ecac08c2ca1b4 # v0.3.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this PR, but why devnet is not updated to the latest version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing forced us to bump it, so it wasn't urgent. Bumped it to v0.4.1.
@@ -52,13 +56,20 @@ def get_start_devnet_command(devnet_port: int, fork_mode: bool = False) -> List[ | |||
] | |||
) | |||
|
|||
if predeclare_argent: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Why not to predeclare always?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like nothing prevents use from having it always predeclared. Will change it.
|
||
def sign_transaction(self, transaction: AccountTransaction) -> List[int]: | ||
if self.signing_mode == LedgerSigningMode.CLEAR: | ||
if isinstance(transaction, DeclareV3): | ||
raise ValueError("DeclareV3 signing is not supported bye LedgerSigner") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know why declare is not supported?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really, haven't digged into the specific reason but maybe it's related with device hardware limits (considering that declare tx includes contract class) or security?
account_address_bytes = contract_address.to_bytes(32, byteorder="big") | ||
chain_id_bytes = self.chain_id.to_bytes(32, byteorder="big") | ||
nonce_bytes = tx.nonce.to_bytes(32, byteorder="big") | ||
common_tx_fields = tx.get_common_fields( | ||
tx_prefix=TransactionHashPrefix.DEPLOY, | ||
address=contract_address, | ||
chain_id=self.chain_id, | ||
) | ||
da_mode_hash_bytes = common_tx_fields.get_data_availability_modes().to_bytes( | ||
32, byteorder="big" | ||
) | ||
class_hash_bytes = tx.class_hash.to_bytes(32, byteorder="big") | ||
salt_bytes = tx.contract_address_salt.to_bytes(32, byteorder="big") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Maybe some kind of a helper function/struct to convert V3 transactions to the same struct but with fields as bytes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, potentially we could add a method for txs classes which would return their values as bytes, but that would require additional struct as the return type (cause returning as tuple of bytes wouldn't be very convenient). Tbh I'm not sure if adding extra code would improve current state, as now it's fairly simple and readable. Wdyt?
if application_name == "LedgerW": | ||
application_bytes = ( | ||
(43).to_bytes(1, byteorder="big") | ||
+ (206).to_bytes(1, byteorder="big") | ||
+ (231).to_bytes(1, byteorder="big") | ||
+ (219).to_bytes(1, byteorder="big") | ||
) | ||
else: | ||
application_bytes = _string_to_4byte_hash(application_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain this logic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like these four integers are predefined for LedgerW and in other cases we just generate the representation.
I referred to https://github.com/starknet-io/starknet.js/blob/050616221a58545d79eece7040b4abc205c220e0/src/signer/ledgerSigner221.ts#L644
Closes #1473
Introduced changes
Add support for clear singing in
LedgerSigner
. Now we're getting displayed tx details before approveing/rejecting it.LedgerSigningMode
clear_sign_example.mov