airgap-it / tezos-rust-sdk

MIT License
20 stars 10 forks source link

RPC error operation.invalid_signature #21

Closed Wicpar closed 1 year ago

Wicpar commented 1 year ago

Hi,

I'm trying to generate keys, but the tezos spec that describes exactly how it should be generated doesn't seem to exist. I'm trying to reverse engineer it from scraps here and there. This is what i got for now:

use blake2_rfc::blake2b::blake2b;
    use p256::elliptic_curve::Field;
    use p256::elliptic_curve::group::GroupEncoding;
    use p256::elliptic_curve::sec1::{ToCompactEncodedPoint, ToEncodedPoint};
    use p256::SecretKey;
    use tezos_core::types::encoded::{Encoded, ImplicitAddress, P256PublicKey, P256PublicKeyHash, P256SecretKey, PublicKey, Secp256K1PublicKeyHash};
    use tezos_rpc::client::TezosRpc;

 let secret = SecretKey::random(&mut rand::thread_rng());
        let public = secret.public_key();
        let public_bytes = public.to_encoded_point(true).to_bytes();
        let tez_private = tezos_core::types::encoded::SecretKey::from(P256SecretKey::from_bytes(secret.to_bytes().as_slice()).unwrap());
        let tez_public_prev = P256PublicKey::from_bytes(&public_bytes).unwrap();
        let public_hash = blake2b(20, &[], &tez_public_prev.to_bytes().unwrap());
        println!("{:?}, {}", secret.to_bytes().as_slice(), secret.to_bytes().as_slice().len());
        println!("{:?}, {}", public_bytes, public_bytes.len());
        println!("{:?}, {}", public_hash.as_bytes(), public_hash.as_bytes().len());
        let tez_public_hash = tezos_core::types::encoded::ImplicitAddress::from(P256PublicKeyHash::from_bytes(public_hash.as_bytes()).unwrap());
        let tez_public = tezos_core::types::encoded::PublicKey::from(tez_public_prev);
        println!("{:?}", tez_private);
        println!("{:?}", tez_public);
        println!("{:?}", tez_public_hash);

i verified the hash method with an existing key, however i can't find a valid tz3 private and public address in the wild to double check the public key generation...

I get RpcError { kind: "permanent", id: "proto.016-PtMumbai.operation.invalid_signature", message: None, msg: None, amount: None, balance: None, contract: None }

when i try to run the following on the ghost network

pub async fn originate_contract(rpc: &TezosRpc<HttpClient>) -> Result<(), tezos_rpc::Error> {
    let addr = tz3();
    let branch = rpc
        .get_block_hash()
        .block_id(&BlockId::Level(-2))
        .send()
        .await?;
    let counter = rpc.get_contract_counter(&Address::from(addr.clone())).send().await?.add(1u64);
    let mut script = create_contract();
    let mut bytes = vec![0]; // 00 for implicit (tz) or 01 for originated (KT)
    bytes.append(&mut addr.to_bytes().unwrap());
    script.storage = serde_json::from_value(json!({
        "prim": "Pair",
        "args": [
          [
            {
              "bytes": hex::encode(bytes)
            },
          ],
          {
            "string": ""
          }
        ]
    })).unwrap();
    let op = UnsignedOperation::new(branch, vec![
        Reveal::new(addr.clone(), 0u8.into(), counter.clone().into(), 0u8.into(), 0u8.into(), p2pk()).into(),
        Origination::new(addr.clone(), 0u8.into(), counter.add(1u64).into(), 0u8.into(), 0u8.into(), 0u8.into(), None, script.into()).into(),
    ]);
    println!("{:?}", op);
    let unsigned_with_fee = rpc.min_fee(op, None).await.unwrap();
    println!("{:?}", unsigned_with_fee);
    let signed_operation = unsigned_with_fee.into_signed_operation(&p2sk()).unwrap();
    println!("{:?}", signed_operation);
    let mut rpc_operation: Operation = signed_operation.into();
    rpc_operation.protocol = Some(rpc.get_block().send().await.unwrap().protocol);
    let preapply_result = rpc
        .preapply_operations(&vec![&rpc_operation])
        .send()
        .await.unwrap(); <-- error here
    println!("{:?}", preapply_result);
    Ok(())
}
Wicpar commented 1 year ago

While testing with taquito, the private key generates the correct public key and public key hash so this generator is correct. The signature error comes from somewhere else.

Wicpar commented 1 year ago

I managed to sign using the example tz1 signature, but p256 sigtnatures seem not to be working...

RomarQ commented 1 year ago

Thanks for the report @Wicpar :+1:

Will try to have a look at this during the weekend.

Wicpar commented 1 year ago

I'll try to look at it a bit more too. I hope you don't mind i pollute your test key with tests.

RomarQ commented 1 year ago

Hi @Wicpar,

I can confirm, it was a bug in the default signers. It should be fixed in https://github.com/airgap-it/tezos-rust-sdk/pull/22 (We expect to merge in on Monday)