Open davit555 opened 2 years ago
I need same functionality . Do you able to solve it? @davit555
yes I have manually implemented it... but it is too strange that it didn't exist in sdk.... @gurd33pS1ngh
from flow_py_sdk.exceptions import PySDKError
from flow_py_sdk.client import AccessAPI
from flow_py_sdk.script import Script
from flow_py_sdk.utils import CompositeSignature
from rlp import encode
async def verify(app_identifier, account_address, nonce, blockchain_network, signature, key_id, env, port=9000):
async with flow_client(
host=blockchain_network, port=port
) as client:
account = await client.get_account(
address=account_address.to_bytes((account_address.bit_length() + 7) // 8, "big")
)
fields = encode(
[
app_identifier, # String
account.address, # Byte
bytes.fromhex(nonce) # Byte from hex number
]
)
signer = CompositeSignature(
addr=account.address.hex(),
keyId=key_id,
signature=signature
)
is_verified = await verify_account_proof_signatures(
client=client, message=bytes(fields.hex(), "utf-8"), composite_signatures=[signer], env=env
)
return is_verified
async def verify_account_proof_signatures(*, client: AccessAPI, message: bytes,
composite_signatures: list[CompositeSignature], env: str
) -> bool:
# if there is no signature return False
if len(composite_signatures) == 0:
return False
# it does not make sense for the signatures to be from different addresses
if any(x.addr != composite_signatures[0].addr for x in composite_signatures):
raise PySDKError("All signatures must be from the same address")
address = cadence.Address.from_hex(composite_signatures[0].addr)
signatures = cadence.Array(
[cadence.String(x.signature) for x in composite_signatures]
)
key_indexes = cadence.Array([cadence.Int(x.keyId) for x in composite_signatures])
cadence_message = cadence.String(str(message, "utf-8"))
if env == "Prod":
address_of_network = "0xdb6b70764af4ff68"
else:
address_of_network = "0x5b250a8a85b44a67"
script = Script(
code=
f'''
import FCLCrypto from {address_of_network}
pub fun main(address: Address,
message: String,
keyIndices: [Int],
signatures: [String]): Bool''' + '''{
return FCLCrypto.verifyAccountProofSignatures(address: address, message: message, keyIndices: keyIndices,
signatures: signatures)
}
''',
arguments=[
address,
cadence_message,
key_indexes,
signatures,
],
)
script_result = await client.execute_script(script)
if script_result is None:
return False
return script_result.as_type(cadence.Bool).value
for anyone that needs that missing code part...
It seems every other sdk has such functionality (C#, Go, Node...) and I don't know how to verify proof of account with the python SDK ...
In particular when js client sends the authentication with
.put("fcl.accountProof.resolver", resolver)
adding to the configwhere the resolver is something like this
const resolver = async () => { return { appIdentifier: "MyAppIdentifier", nonce: "75f8587e5bd5f9dcc9909d0dae1f0ac5814458b2ae129620502cb936fde7120a" }
then it gets some signature
{ "f_type": "Service", "f_vsn": "1.0.0", "type": "account-proof", "method": "DATA", "uid": "blocto#account-proof", "data": { "f_type": "account-proof", "f_vsn": "2.0.0", "signatures": [ { "f_type": "CompositeSignature", "f_vsn": "1.0.0", "addr": "0x46dfa5325a7bb983", "keyId": 1, "signature": "ce972efe49abc05a3bc8d71ff1e48e42d8d869a3ca30efb5e39ebbdb3f8a37fffb6f3bddd8eeacf803755c2726b64a9049be8360e9d2889ec914a301ab73da3d" } ], "address": "0x46dfa5325a7bb983", "timestamp": null, "nonce": "75f8587e5bd5f9dcc9909d0dae1f0ac5814458b2ae129620502cb936fde7120a" } }
then I need to somehow verify this signature from maybe
verify_user_signature
method but I don't know what to pass as message parameter...
do I need to encode the message like rlp or perform some other serialization....
Please help to figure out this