import sys, getopt import json from getpass import getpass from eth_account import Account from hexbytes import HexBytes """ Main logic extracted from: https://github.com/gnosis/gnosis-py """ def signature_to_bytes(v: int, r: int, s: int) -> bytes: """ Convert ecdsa signature to bytes :param v: :param r: :param s: :return: signature in form of {bytes32 r}{bytes32 s}{uint8 v} """ byte_order = "big" return ( r.to_bytes(32, byteorder=byte_order) + s.to_bytes(32, byteorder=byte_order) + v.to_bytes(1, byteorder=byte_order) ) def sign(private_key: str, safe_tx_hash: HexBytes) -> bytes: """ {bytes32 r}{bytes32 s}{uint8 v} :param private_key: :return: Signature """ account = Account.from_key(private_key) signature_dict = account.signHash(safe_tx_hash) signature = signature_to_bytes( signature_dict["v"], signature_dict["r"], signature_dict["s"] ) """ # Insert signature sorted if account.address not in self.signers: new_owners = self.signers + [account.address] new_owner_pos = sorted(new_owners, key=lambda x: int(x, 16)).index( account.address ) self.signatures = ( self.signatures[: 65 * new_owner_pos] + signature + self.signatures[65 * new_owner_pos :] ) """ return signature def get_private_key(keystore: str) -> str: with open(keystore) as f: encrypted = f.readlines() print(encrypted) print(type(encrypted[0])) print(json.loads(encrypted[0])) password = getpass("Enter password:") return Account.decrypt(json.loads(encrypted[0]), password) def trim_tx_hash(safe_tx_hash: str) -> str: if safe_tx_hash[0:2] == "0x": return safe_tx_hash[2:] return safe_tx_hash def get_args(argv): help_string = 'Usage: python3 safe_sign.py -s hash -k keystore' if len(argv) < 4: print(help_string) sys.exit(2) try: opts, args = getopt.getopt(argv,"hs:k:",["hash=,keystore="]) except getopt.GetoptError: print(help_string) sys.exit(2) for opt, arg in opts: if opt == '-h': print(help_string) sys.exit() elif opt in ("-s", "--hash"): safe_tx_hash = arg elif opt in ("-k", "--keystore"): keystore = arg return safe_tx_hash, keystore if __name__ == "__main__": safe_tx_hash, keystore = get_args(sys.argv[1:]) safe_tx_hash = trim_tx_hash(safe_tx_hash) pk = get_private_key(keystore) hb = HexBytes(safe_tx_hash) signature = sign(pk, hb) print(HexBytes(signature).hex())