keystore.sign_message: add optional script_type argument
this is used by trezor (and also by bitbox02, which was using a workaround previously) fixes https://github.com/spesmilo/electrum/issues/7670
This commit is contained in:
@@ -499,7 +499,12 @@ class ECPrivkey(ECPubkey):
|
||||
def sign_transaction(self, hashed_preimage: bytes) -> bytes:
|
||||
return self.sign(hashed_preimage, sigencode=der_sig_from_r_and_s)
|
||||
|
||||
def sign_message(self, message: bytes, is_compressed: bool, algo=lambda x: sha256d(msg_magic(x))) -> bytes:
|
||||
def sign_message(
|
||||
self,
|
||||
message: Union[bytes, str],
|
||||
is_compressed: bool,
|
||||
algo=lambda x: sha256d(msg_magic(x)),
|
||||
) -> bytes:
|
||||
def bruteforce_recid(sig_string):
|
||||
for recid in range(4):
|
||||
sig65 = construct_sig65(sig_string, recid, is_compressed)
|
||||
|
||||
@@ -127,7 +127,14 @@ class KeyStore(Logger, ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def sign_message(self, sequence: 'AddressIndexGeneric', message, password) -> bytes:
|
||||
def sign_message(
|
||||
self,
|
||||
sequence: 'AddressIndexGeneric',
|
||||
message: str,
|
||||
password,
|
||||
*,
|
||||
script_type: Optional[str] = None,
|
||||
) -> bytes:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
@@ -175,7 +182,7 @@ class Software_KeyStore(KeyStore):
|
||||
def may_have_password(self):
|
||||
return not self.is_watching_only()
|
||||
|
||||
def sign_message(self, sequence, message, password) -> bytes:
|
||||
def sign_message(self, sequence, message, password, *, script_type=None) -> bytes:
|
||||
privkey, compressed = self.get_private_key(sequence, password)
|
||||
key = ecc.ECPrivkey(privkey)
|
||||
return key.sign_message(message, compressed)
|
||||
|
||||
@@ -524,7 +524,7 @@ class BitBox02Client(HardwareClientBase):
|
||||
signatures = [bh2u(ecc.der_sig_from_sig_string(x[1])) + "01" for x in sigs]
|
||||
tx.update_signatures(signatures)
|
||||
|
||||
def sign_message(self, keypath: str, message: bytes, xtype: str) -> bytes:
|
||||
def sign_message(self, keypath: str, message: bytes, script_type: str) -> bytes:
|
||||
if self.bitbox02_device is None:
|
||||
raise Exception(
|
||||
"Need to setup communication first before attempting any BitBox02 calls"
|
||||
@@ -534,9 +534,9 @@ class BitBox02Client(HardwareClientBase):
|
||||
simple_type = {
|
||||
"p2wpkh-p2sh":bitbox02.btc.BTCScriptConfig.P2WPKH_P2SH,
|
||||
"p2wpkh": bitbox02.btc.BTCScriptConfig.P2WPKH,
|
||||
}[xtype]
|
||||
}[script_type]
|
||||
except KeyError:
|
||||
raise UserFacingException("The BitBox02 does not support signing messages for this address type: {}".format(xtype))
|
||||
raise UserFacingException("The BitBox02 does not support signing messages for this address type: {}".format(script_type))
|
||||
|
||||
_, _, signature = self.bitbox02_device.btc_sign_msg(
|
||||
self._get_coin(),
|
||||
@@ -560,7 +560,7 @@ class BitBox02_KeyStore(Hardware_KeyStore):
|
||||
self.force_watching_only = False
|
||||
self.ux_busy = False
|
||||
|
||||
def get_client(self):
|
||||
def get_client(self) -> Optional['BitBox02Client']:
|
||||
return self.plugin.get_client(self)
|
||||
|
||||
def give_error(self, message: Exception, clear_client: bool = False):
|
||||
@@ -580,13 +580,12 @@ class BitBox02_KeyStore(Hardware_KeyStore):
|
||||
).format(self.device)
|
||||
)
|
||||
|
||||
def sign_message(self, sequence, message, password):
|
||||
def sign_message(self, sequence, message, password, *, script_type=None):
|
||||
if password:
|
||||
raise Exception("BitBox02 does not accept a password from the host")
|
||||
client = self.get_client()
|
||||
keypath = self.get_derivation_prefix() + "/%d/%d" % sequence
|
||||
xtype = self.get_bip32_node_for_xpub().xtype
|
||||
return client.sign_message(keypath, message.encode("utf-8"), xtype)
|
||||
return client.sign_message(keypath, message.encode("utf-8"), script_type)
|
||||
|
||||
|
||||
@runs_in_hwd_thread
|
||||
|
||||
@@ -308,7 +308,7 @@ class Coldcard_KeyStore(Hardware_KeyStore):
|
||||
raise UserFacingException(_('Encryption and decryption are currently not supported for {}').format(self.device))
|
||||
|
||||
@wrap_busy
|
||||
def sign_message(self, sequence, message, password):
|
||||
def sign_message(self, sequence, message, password, *, script_type=None):
|
||||
# Sign a message on device. Since we have big screen, of course we
|
||||
# have to show the message unabiguously there first!
|
||||
try:
|
||||
|
||||
@@ -455,7 +455,7 @@ class DigitalBitbox_KeyStore(Hardware_KeyStore):
|
||||
raise RuntimeError(_('Encryption and decryption are currently not supported for {}').format(self.device))
|
||||
|
||||
|
||||
def sign_message(self, sequence, message, password):
|
||||
def sign_message(self, sequence, message, password, *, script_type=None):
|
||||
sig = None
|
||||
try:
|
||||
message = message.encode('utf8')
|
||||
|
||||
@@ -38,7 +38,7 @@ class KeepKey_KeyStore(Hardware_KeyStore):
|
||||
raise UserFacingException(_('Encryption and decryption are not implemented by {}').format(self.device))
|
||||
|
||||
@runs_in_hwd_thread
|
||||
def sign_message(self, sequence, message, password):
|
||||
def sign_message(self, sequence, message, password, *, script_type=None):
|
||||
client = self.get_client()
|
||||
address_path = self.get_derivation_prefix() + "/%d/%d"%sequence
|
||||
address_n = client.expand_path(address_path)
|
||||
|
||||
@@ -290,7 +290,7 @@ class Ledger_KeyStore(Hardware_KeyStore):
|
||||
@runs_in_hwd_thread
|
||||
@test_pin_unlocked
|
||||
@set_and_unset_signing
|
||||
def sign_message(self, sequence, message, password):
|
||||
def sign_message(self, sequence, message, password, *, script_type=None):
|
||||
message = message.encode('utf8')
|
||||
message_hash = hashlib.sha256(message).hexdigest().upper()
|
||||
# prompt for the PIN before displaying the dialog if necessary
|
||||
|
||||
@@ -36,7 +36,7 @@ class SafeTKeyStore(Hardware_KeyStore):
|
||||
raise UserFacingException(_('Encryption and decryption are not implemented by {}').format(self.device))
|
||||
|
||||
@runs_in_hwd_thread
|
||||
def sign_message(self, sequence, message, password):
|
||||
def sign_message(self, sequence, message, password, *, script_type=None):
|
||||
client = self.get_client()
|
||||
address_path = self.get_derivation_prefix() + "/%d/%d"%sequence
|
||||
address_n = client.expand_path(address_path)
|
||||
|
||||
@@ -228,7 +228,7 @@ class TrezorClientBase(HardwareClientBase, Logger):
|
||||
multisig=multisig)
|
||||
|
||||
@runs_in_hwd_thread
|
||||
def sign_message(self, address_str, message):
|
||||
def sign_message(self, address_str, message, *, script_type):
|
||||
coin_name = self.plugin.get_coin_name()
|
||||
address_n = parse_path(address_str)
|
||||
with self.run_flow():
|
||||
@@ -236,7 +236,9 @@ class TrezorClientBase(HardwareClientBase, Logger):
|
||||
self.client,
|
||||
coin_name,
|
||||
address_n,
|
||||
message)
|
||||
message,
|
||||
script_type=script_type,
|
||||
no_script_type=True)
|
||||
|
||||
@runs_in_hwd_thread
|
||||
def recover_device(self, recovery_type, *args, **kwargs):
|
||||
|
||||
@@ -77,10 +77,11 @@ class TrezorKeyStore(Hardware_KeyStore):
|
||||
def decrypt_message(self, sequence, message, password):
|
||||
raise UserFacingException(_('Encryption and decryption are not implemented by {}').format(self.device))
|
||||
|
||||
def sign_message(self, sequence, message, password):
|
||||
def sign_message(self, sequence, message, password, *, script_type=None):
|
||||
client = self.get_client()
|
||||
address_path = self.get_derivation_prefix() + "/%d/%d"%sequence
|
||||
msg_sig = client.sign_message(address_path, message)
|
||||
script_type = self.plugin.get_trezor_input_script_type(script_type)
|
||||
msg_sig = client.sign_message(address_path, message, script_type=script_type)
|
||||
return msg_sig.signature
|
||||
|
||||
def sign_transaction(self, tx, password):
|
||||
|
||||
@@ -2452,9 +2452,11 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
|
||||
def _update_password_for_keystore(self, old_pw: Optional[str], new_pw: Optional[str]) -> None:
|
||||
pass
|
||||
|
||||
def sign_message(self, address, message, password):
|
||||
def sign_message(self, address: str, message: str, password) -> bytes:
|
||||
index = self.get_address_index(address)
|
||||
return self.keystore.sign_message(index, message, password)
|
||||
script_type = self.get_txin_type(address)
|
||||
assert script_type != "address"
|
||||
return self.keystore.sign_message(index, message, password, script_type=script_type)
|
||||
|
||||
def decrypt_message(self, pubkey: str, message, password) -> bytes:
|
||||
addr = self.pubkeys_to_address([pubkey])
|
||||
|
||||
Reference in New Issue
Block a user