Skip to content

Instantly share code, notes, and snippets.

@HRezaei
Created February 11, 2022 03:55
Show Gist options
  • Save HRezaei/fd82a4701fe115fd356f31679c516b10 to your computer and use it in GitHub Desktop.
Save HRezaei/fd82a4701fe115fd356f31679c516b10 to your computer and use it in GitHub Desktop.
import binascii
import json
import os
import subprocess
from time import sleep
import ed25519
from ecpy.curves import Curve
from solana.publickey import PublicKey
from solana.rpc.api import Client
from solana.transaction import Transaction, SigPubkeyPair
import solana.system_program as sp
from eth_utils import int_to_big_endian
from nacl import signing # type: ignore
TSS_EXECUTABLE = "/tss-ecdsa-cli/target/debug/tss_cli"
TSS_KEYS_FILE = "/tmp/ed1.store"
cv25519 = Curve.get_curve("Ed25519")
debug = {}
ed25519.SigningKey
def encodepoint(P):
x = P[0]
y = P[1]
# MSB of output equals x.b0 (=x&1)
# rest of output is little-endian y
assert 0 <= y < (1 << 255) # always < 0x7fff..ff
if x & 1:
y += 1 << 255
return binascii.unhexlify("%064x" % y)[::-1]
def create_point(x, y):
class myp: pass
mypoint = myp()
mypoint.x = x # 0x161474b35b82c2917bc483ac0516a2dbd1a85c8b582ec28f394bc49c0052e86d
mypoint.y = y
return cv25519.encode_point(mypoint)
def pad32(value: bytes) -> bytes:
return value.rjust(32, b'\x00')
def to_bytes(r, s) -> bytes:
rb = pad32(int_to_big_endian(r))
sb = pad32(int_to_big_endian(s))
return b''.join((rb, sb))
def tss_signer(hex, path):
signature_output_file = "signature.json"
try:
os.remove(signature_output_file)
except Exception as e:
print(e)
for i in range(1, 4):
command = TSS_EXECUTABLE + " sign /tmp/ed" + str(i) + ".store 2/3 \"" + hex + "\" -ceddsa"
if len(path) > 0:
command = command + " -p" + path
#command = TSS_EXECUTABLE + " sign /tmp/ed" + str(i) + ".store 2/3 -ceddsa \"" + hex + "\""
if i != 3:
command = command + ' >> /dev/null &'
else:
#command = command + ' > ' + signature_output_file
print("TSS sign command: ", command)
os.system(command)
sleep(1)
file = open(signature_output_file, "r")
#content = file.read()
#content = "{\"" + content.split("{\"")[1]
sign_output = json.load(file)
print("TSS output: ", sign_output)
file.close()
return sign_output
def generate_sig_from_rs(r_hex, s_hex):
r, s = int(r_hex, 16), int(s_hex, 16)
rb_be = pad32(int_to_big_endian(r))
sb_le = pad32(int_to_big_endian(s))
signature_rs_bytes = b''.join((rb_be, sb_le))
return signature_rs_bytes
def test_nacl_sigining():
path = '1/2'
msg = b"hi"
cmd = f'{TSS_EXECUTABLE} pubkey {TSS_KEYS_FILE} -p {path} -ceddsa'
debug['cmd'] = cmd
output = subprocess.check_output(cmd.split(' '))
debug['tss output'] = output
xy_dict = json.loads(output)
debug['x'] = xy_dict['x']
debug['y'] = xy_dict['y']
x = int(xy_dict['x'], 16)
y = int(xy_dict['y'], 16)
address_bytes = create_point(x, y)
debug['address_bytes'] = address_bytes
sender_public_key = PublicKey(address_bytes)
debug['sender public key'] = sender_public_key
verify_key = signing.VerifyKey(address_bytes)
debug['verify_key'] = verify_key
sign_dict = tss_signer(msg.hex(), path)
raw_signed = generate_sig_from_rs(sign_dict["r"], sign_dict["s"])
assert verify_key.verify(msg, raw_signed)
return
def test_solana_tss():
path = '1/2'
msg = "hi"
cmd = f'{TSS_EXECUTABLE} pubkey {TSS_KEYS_FILE} -p {path} -ceddsa'
debug['cmd'] = cmd
output = subprocess.check_output(cmd.split(' '))
debug['tss output'] = output
xy_dict = json.loads(output)
debug['x'] = xy_dict['x']
debug['y'] = xy_dict['y']
x = int(xy_dict['x'], 16)
y = int(xy_dict['y'], 16)
address_bytes = create_point(x, y)
debug['address_bytes'] = address_bytes
sender_public_key = PublicKey(address_bytes)
debug['sender public key'] = sender_public_key
verify_key = signing.VerifyKey(address_bytes)
debug['verify_key'] = verify_key
debug['on_curve'] = PublicKey._is_on_curve(bytes(sender_public_key))
debug['pub_key'] = sender_public_key.to_base58().hex()
# This is mainnet I think:
# url = 'https://solana-api.projectserum.com'
# This one is testnet
url = "https://api.devnet.solana.com"
cli = Client(url)
account_info = cli.get_account_info(sender_public_key)
debug['sender account info'] = account_info
#pub_key_for_program_id = PublicKey('CJsLwbP1iu5DuUikHEJnLfANgKy6stB2uFgvBBHoyxwz')
receiver_public_key = PublicKey('C8cZHbugbX6gQVrxqLGAgiumKh85khhM5cXXeB1rsGMc')
recent_blockhash = cli.get_recent_blockhash()['result']['value']['blockhash']
transaction = Transaction(recent_blockhash=recent_blockhash)
transaction.add(sp.transfer(sp.TransferParams(
from_pubkey=sender_public_key,
to_pubkey=receiver_public_key,
lamports=cli.get_minimum_balance_for_rent_exemption(88).get('result'),
)))
transaction.fee_payer = sender_public_key
transaction_data_to_sign = transaction.serialize_message()
sign_dict = tss_signer(transaction_data_to_sign.hex(), path)
signature = generate_sig_from_rs(sign_dict['r'], sign_dict['s'])
transaction.signatures = [SigPubkeyPair(sender_public_key)]
transaction.signatures[0].signature = signature
signed_hash = transaction.serialize()
debug['signed_with_lib'] = signed_hash
try:
debug['send_tx'] = cli.send_raw_transaction(signed_hash)
except Exception as e:
debug['error'] = e
#test_nacl_sigining()
test_solana_tss()
print(debug)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment