Skip to content

Commit

Permalink
[Barz] Public API refactoring (#3212)
Browse files Browse the repository at this point in the history
* Getting rid of attestationObject in Barz public API

* remove duplicates

* Update Barz.cpp

* Update Barz.cpp

* Update BarzTests.swift

* update tests

* Update WebAuthnTests.cpp

* Update TestBarz.kt

* Update TestWebAuthn.kt

* update android tests

* Update TestBarz.kt

* Update TestBarz.kt

* Update TestBarz.kt

* fix nullability

* tests update
  • Loading branch information
rsrbk committed Jun 21, 2023
1 parent 3b42f9c commit ffe8755
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 202 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.trustwallet.core.app.utils

import com.trustwallet.core.app.utils.toHexByteArray
import org.junit.Assert.assertEquals
import org.junit.Test
import com.trustwallet.core.app.utils.Numeric
import wallet.core.jni.*

class TestWebAuthn {

init {
System.loadLibrary("TrustWalletCore")
}

@Test
fun testGetPublicKey() {
val attestationObject = Numeric.hexStringToByteArray("0xa363666d74646e6f6e656761747453746d74a068617574684461746158a4f95bc73828ee210f9fd3bbe72d97908013b0a3759e9aea3d0ae318766cd2e1ad4500000000adce000235bcc60a648b0b25f1f055030020c720eb493e167ce93183dd91f5661e1004ed8cc1be23d3340d92381da5c0c80ca5010203262001215820a620a8cfc88fd062b11eab31663e56cad95278bef612959be214d98779f645b82258204e7b905b42917570148b0432f99ba21f2e7eebe018cbf837247e38150a89f771")
val result = WebAuthn.getPublicKey(attestationObject).data()
assertEquals(Numeric.toHexString(result), "0x04a620a8cfc88fd062b11eab31663e56cad95278bef612959be214d98779f645b84e7b905b42917570148b0432f99ba21f2e7eebe018cbf837247e38150a89f771")
}
}
12 changes: 2 additions & 10 deletions include/TrustWalletCore/TWBarz.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "TWBase.h"
#include "TWData.h"
#include "TWString.h"
#include "TWPublicKey.h"

TW_EXTERN_C_BEGIN

Expand All @@ -29,16 +30,7 @@ TWString *_Nonnull TWBarzGetCounterfactualAddress(TWData *_Nonnull input);
/// \param verificationFacet Verification facet address
/// \return The address.
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWBarzGetInitCodeFromPublicKey(TWString* _Nonnull factory, TWString* _Nonnull publicKey, TWString* _Nonnull verificationFacet);

/// Returns the init code parameter of ERC-4337 User Operation
///
/// \param factory Wallet factory address (BarzFactory)
/// \param attestationObject Attestation object from created webauthn credentials
/// \param verificationFacet Verification facet address
/// \return The address.
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWBarzGetInitCodeFromAttestationObject(TWString* _Nonnull factory, TWString* _Nonnull attestationObject, TWString* _Nonnull verificationFacet);
TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKey* _Nonnull publicKey, TWString* _Nonnull verificationFacet);

/// Converts the original ASN-encoded signature from webauthn to the format accepted by Barz
///
Expand Down
23 changes: 23 additions & 0 deletions include/TrustWalletCore/TWWebAuthn.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright © 2017-2023 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.
#pragma once

#include "TWBase.h"
#include "TWData.h"
#include "TWPublicKey.h"

TW_EXTERN_C_BEGIN

TW_EXPORT_STRUCT
struct TWWebAuthn;

/// Converts attestation object to the public key on P256 curve
///
/// \param attestationObject Attestation object retrieved from webuthn.get method
/// \return Public key.
TW_EXPORT_STATIC_METHOD
struct TWPublicKey *_Nullable TWWebAuthnGetPublicKey(TWData *_Nonnull attestationObject);
TW_EXTERN_C_END
25 changes: 4 additions & 21 deletions src/Ethereum/Barz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,7 @@ std::string getCounterfactualAddress(const Proto::ContractAddressInput input) {
params.addParam(std::make_shared<Ethereum::ABI::ParamAddress>(parse_hex(input.diamond_loupe_facet())));
params.addParam(std::make_shared<Ethereum::ABI::ParamAddress>(parse_hex(input.diamond_init())));
params.addParam(std::make_shared<Ethereum::ABI::ParamAddress>(parse_hex(input.facet_registry())));

Data publicKey;
switch (input.owner().kind_case()) {
case Proto::ContractOwner::KindCase::KIND_NOT_SET:
return "";
case Proto::ContractOwner::KindCase::kPublicKey:
publicKey = parse_hex(input.owner().public_key());
break;
case Proto::ContractOwner::KindCase::kAttestationObject:
const auto attestationObject = parse_hex(input.owner().attestation_object());
publicKey = subData(WebAuthn::getPublicKey(attestationObject)->bytes, 1); // Drop the first byte which corresponds to the public key type
break;
}
params.addParam(std::make_shared<Ethereum::ABI::ParamByteArray>(publicKey));
params.addParam(std::make_shared<Ethereum::ABI::ParamByteArray>(parse_hex(input.public_key())));

Data encoded;
params.encode(encoded);
Expand All @@ -54,10 +41,11 @@ std::string getCounterfactualAddress(const Proto::ContractAddressInput input) {
return Ethereum::checksumed(Ethereum::Address(hexEncoded(Ethereum::create2Address(input.factory(), salt, initCodeHash))));
}

Data getInitCodeFromPublicKey(const std::string& factoryAddress, const std::string& publicKey, const std::string& verificationFacet) {
Data getInitCode(const std::string& factoryAddress, const PublicKey& publicKey, const std::string& verificationFacet) {
const auto rawPublicKey = subData(publicKey.bytes, 1);
auto createAccountFunc = Ethereum::ABI::Function("createAccount", ParamCollection{
std::make_shared<Ethereum::ABI::ParamAddress>(parse_hex(verificationFacet)),
std::make_shared<Ethereum::ABI::ParamByteArray>(parse_hex(publicKey)),
std::make_shared<Ethereum::ABI::ParamByteArray>(rawPublicKey),
std::make_shared<Ethereum::ABI::ParamUInt256>(0)});
Data createAccountFuncEncoded;
createAccountFunc.encode(createAccountFuncEncoded);
Expand All @@ -68,11 +56,6 @@ Data getInitCodeFromPublicKey(const std::string& factoryAddress, const std::stri
return envelope;
}

Data getInitCodeFromAttestationObject(const std::string& factoryAddress, const std::string& attestationObject, const std::string& verificationFacet) {
const auto publicKey = subData(WebAuthn::getPublicKey(parse_hex(attestationObject))->bytes, 1);
return getInitCodeFromPublicKey(factoryAddress, hexEncoded(publicKey), verificationFacet);
}

Data getFormattedSignature(const Data& signature, const Data challenge, const Data& authenticatorData, const std::string& clientDataJSON) {
std::string challengeBase64 = TW::Base64::encodeBase64Url(challenge);
while (challengeBase64.back() == '=') {
Expand Down
4 changes: 2 additions & 2 deletions src/Ethereum/Barz.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

#include "Data.h"
#include "uint256.h"
#include "PublicKey.h"
#include "../proto/Barz.pb.h"

namespace TW::Barz {

std::string getCounterfactualAddress(const Proto::ContractAddressInput input);
Data getInitCodeFromPublicKey(const std::string& factoryAddress, const std::string& owner, const std::string& verificationFacet);
Data getInitCodeFromAttestationObject(const std::string& factoryAddress, const std::string& attestationObject, const std::string& verificationFacet);
Data getInitCode(const std::string& factoryAddress, const PublicKey& publicKey, const std::string& verificationFacet);
Data getFormattedSignature(const Data& signature, const Data challenge, const Data& authenticatorData, const std::string& clientDataJSON);

}
14 changes: 3 additions & 11 deletions src/interface/TWBarz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,12 @@ TWString *_Nonnull TWBarzGetCounterfactualAddress(TWData *_Nonnull input) {
return TWStringCreateWithUTF8Bytes(TW::Barz::getCounterfactualAddress(inputProto).c_str());
}

TWData *_Nonnull TWBarzGetInitCodeFromPublicKey(TWString* _Nonnull factory, TWString* _Nonnull publicKey, TWString* _Nonnull verificationFacet) {
TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKey* _Nonnull publicKey, TWString* _Nonnull verificationFacet) {
const auto& factoryStr = *reinterpret_cast<const std::string*>(factory);
const auto& publicKeyStr = *reinterpret_cast<const std::string*>(publicKey);
const auto& publicKeyConverted = *reinterpret_cast<const TW::PublicKey*>(publicKey);
const auto& verificationFacetStr = *reinterpret_cast<const std::string*>(verificationFacet);

const auto initCode = TW::Barz::getInitCodeFromPublicKey(factoryStr, publicKeyStr, verificationFacetStr);
return TWDataCreateWithData(&initCode);
}

TWData *_Nonnull TWBarzGetInitCodeFromAttestationObject(TWString* _Nonnull factory, TWString* _Nonnull attestationObject, TWString* _Nonnull verificationFacet) {
const auto& factoryStr = *reinterpret_cast<const std::string*>(factory);
const auto& attestationObjectStr = *reinterpret_cast<const std::string*>(attestationObject);
const auto& verificationFacetStr = *reinterpret_cast<const std::string*>(verificationFacet);
const auto initCode = TW::Barz::getInitCodeFromAttestationObject(factoryStr, attestationObjectStr, verificationFacetStr);
const auto initCode = TW::Barz::getInitCode(factoryStr, publicKeyConverted, verificationFacetStr);
return TWDataCreateWithData(&initCode);
}

Expand Down
19 changes: 19 additions & 0 deletions src/interface/TWWebAuthn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright © 2017-2023 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

#include <TrustWalletCore/TWWebAuthn.h>
#include <string>
#include "WebAuthn.h"

struct TWPublicKey *_Nullable TWWebAuthnGetPublicKey(TWData *_Nonnull attestationObject) {
const auto& attestationObjectData = *reinterpret_cast<const TW::Data*>(attestationObject);
const auto publicKey = TW::WebAuthn::getPublicKey(attestationObjectData);
if (publicKey.has_value()) {
return new TWPublicKey{ TW::PublicKey(publicKey.value()) };
} else {
return nullptr;
}
}
12 changes: 2 additions & 10 deletions src/proto/Barz.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ syntax = "proto3";
package TW.Barz.Proto;
option java_package = "wallet.core.jni.proto";

// Represents the access control to the wallet
message ContractOwner {
oneof kind {
string public_key = 1;
string attestation_object = 2;
}
}

// Input parameters for calculating a counterfactual address for ERC-4337 based smart contract wallet
message ContractAddressInput {
// Address of the contract factory
Expand All @@ -42,6 +34,6 @@ message ContractAddressInput {
// Bytecode of the smart contract to deploy
string bytecode = 9;

// Owner of the wallet
ContractOwner owner = 10;
// PublicKey of the wallet
string public_key = 10;
}
49 changes: 11 additions & 38 deletions swift/Tests/BarzTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,18 @@ import WalletCore

class BarzTests: XCTestCase {

// https://testnet.bscscan.com/tx/0x434f5861b7d14b3bf790b57e5eb1be98355d77f528defe732f2994fc9d6d3f2e
func testInitCodeFromPublicKey() {
let factoryAddress = "0x3fC708630d85A3B5ec217E53100eC2b735d4f800"
let publicKey = "0x1dba683ee34242c993f7588c30099969a1e58e64bdd0657958ced8e4220f69678a77e6fdf4633151105bdb1a9dd419fbd65f7d8b7a39923757534d4a578e9b58"
let verificationFacet = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf"
let result = Barz.getInitCodeFromPublicKey(factory: factoryAddress, publicKey: publicKey, verificationFacet: verificationFacet)
XCTAssertEqual(result.hexString, "3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401dba683ee34242c993f7588c30099969a1e58e64bdd0657958ced8e4220f69678a77e6fdf4633151105bdb1a9dd419fbd65f7d8b7a39923757534d4a578e9b58")
}

// https://testnet.bscscan.com/tx/0x6c6e1fe81c722c0abce1856b9b4e078ab2cad06d51f2d1b04945e5ba2286d1b4
func testInitCodeFromAttestationObject() {
func testInitCode() {
let factoryAddress = "0x3fC708630d85A3B5ec217E53100eC2b735d4f800"
let attestationObject = "0xa363666d74646e6f6e656761747453746d74a068617574684461746158981a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e075d0000000000000000000000000000000000000000001464193b58d01d4047694ba4634750047a5fcd637ea5010203262001215820e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79225820eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02"
let publicKeyData = Data(hexString: "0x04e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02")!
let publicKey = PublicKey(data: publicKeyData, type: .nist256p1Extended)!
let verificationFacet = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf"
let result = Barz.getInitCodeFromAttestationObject(factory: factoryAddress, attestationObject: attestationObject, verificationFacet: verificationFacet)
let result = Barz.getInitCode(factory: factoryAddress, publicKey: publicKey, verificationFacet: verificationFacet)
XCTAssertEqual(result.hexString, "3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02")
}

// https://testnet.bscscan.com/address/0x5d51930e0ce5cc08a67a1763fadb66892c0994d1
func testCounterfactualAddressFromPublicKey() {
func testCounterfactualAddress() {
let verificationFacet = "0xDcfbDE24847FdF29E6d0311f4bAEb2b49ae8B5a3"
let input = BarzContractAddressInput.with {
$0.factory = factory
Expand All @@ -40,34 +32,12 @@ class BarzTests: XCTestCase {
$0.diamondInit = diamondInit
$0.facetRegistry = facetRegistry
$0.bytecode = bytecode
$0.owner = BarzContractOwner.with {
$0.publicKey = "0xB5547FBdC56DCE45e1B8ef75569916D438e09c46"
}
$0.publicKey = "0xB5547FBdC56DCE45e1B8ef75569916D438e09c46"
}

XCTAssertEqual(Barz.getCounterfactualAddress(input: try! input.serializedData()), "0xb16Db98B365B1f89191996942612B14F1Da4Bd5f");
}

func testCounterfactualAddressFromAttestationObject() {
let verificationFacet = "0x5034534Efe9902779eD6eA6983F435c00f3bc510"
let input = BarzContractAddressInput.with {
$0.factory = factory
$0.diamondCutFacet = diamondCutFacet
$0.accountFacet = accountFacet
$0.verificationFacet = verificationFacet
$0.entryPoint = entryPoint
$0.diamondLoupeFacet = diamondLoupeFacet
$0.diamondInit = diamondInit
$0.facetRegistry = facetRegistry
$0.bytecode = bytecode
$0.owner = BarzContractOwner.with {
$0.attestationObject = "0xa363666d74646e6f6e656761747453746d74a068617574684461746158981a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e075d000000000000000000000000000000000000000000147d0d9cf0634ebd79b5df0c91c7de42c567aac588a50102032620012158207868c62a834763bae747bd9db14d9d159ccd1052a8f81287e3f039c5c9c0f91e225820000e4fc74a22560d3bd22866c6b9fe88c10c170be073d2a838c8019586a7a4eb"
}
}

XCTAssertEqual(Barz.getCounterfactualAddress(input: try! input.serializedData()), "0x85a6290917d1DC2C507Ff2D545Ba5aF13e964Ba1");
}

func testFormatSignature() {
let signature = Data(hexString: "0x3044022012d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf0220256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca276")!
let challenge = Data(hexString: "0xcf267a78c5adaf96f341a696eb576824284c572f3e61be619694d539db1925f9")!
Expand Down Expand Up @@ -109,6 +79,9 @@ class BarzTests: XCTestCase {

// https://testnet.bscscan.com/tx/0xea1f5cddc0653e116327cbcb3bc770360a642891176eff2ec69c227e46791c31
func testSignR1TransferAccountNotDeployed() {
let attestationObject = Data(hexString: "0xa363666d74646e6f6e656761747453746d74a068617574684461746158981a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e075d00000000000000000000000000000000000000000014c14f8a2dfd8f451581fad6e4e1c11821abcaacd6a5010203262001215820b173a6a812025c40c38bac46343646bd0a8137c807aae6e04aac238cc24d2ad2225820116ca14d23d357588ff2aabd7db29d5976f4ecc8037775db86f67e873a306b1f")!
let publicKey = WebAuthn.getPublicKey(attestationObject: attestationObject)!

let input = EthereumSigningInput.with {
$0.chainID = Data(hexString: "61")!
$0.nonce = Data(hexString: "00")!
Expand All @@ -124,9 +97,9 @@ class BarzTests: XCTestCase {
$0.preVerificationGas = Data(hexString: "b708")!
$0.entryPoint = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
$0.sender = "0x1392Ae041BfBdBAA0cFF9234a0C8F64df97B7218"
$0.initCode = Barz.getInitCodeFromAttestationObject(
$0.initCode = Barz.getInitCode(
factory: factory,
attestationObject: "0xa363666d74646e6f6e656761747453746d74a068617574684461746158981a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e075d00000000000000000000000000000000000000000014c14f8a2dfd8f451581fad6e4e1c11821abcaacd6a5010203262001215820b173a6a812025c40c38bac46343646bd0a8137c807aae6e04aac238cc24d2ad2225820116ca14d23d357588ff2aabd7db29d5976f4ecc8037775db86f67e873a306b1f",
publicKey: publicKey,
verificationFacet: "0x5034534Efe9902779eD6eA6983F435c00f3bc510"
)
}
Expand Down
17 changes: 17 additions & 0 deletions swift/Tests/WebAuthnTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright © 2017-2022 Trust Wallet.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

import XCTest
import WalletCore

class WebAuthnTests: XCTestCase {

func testGetPubicKey() {
let attestationObject = Data(hexString: "0xa363666d74646e6f6e656761747453746d74a068617574684461746158a4f95bc73828ee210f9fd3bbe72d97908013b0a3759e9aea3d0ae318766cd2e1ad4500000000adce000235bcc60a648b0b25f1f055030020c720eb493e167ce93183dd91f5661e1004ed8cc1be23d3340d92381da5c0c80ca5010203262001215820a620a8cfc88fd062b11eab31663e56cad95278bef612959be214d98779f645b82258204e7b905b42917570148b0432f99ba21f2e7eebe018cbf837247e38150a89f771")!
let result = WebAuthn.getPublicKey(attestationObject: attestationObject)!.data
XCTAssertEqual(result.hexString, "04a620a8cfc88fd062b11eab31663e56cad95278bef612959be214d98779f645b84e7b905b42917570148b0432f99ba21f2e7eebe018cbf837247e38150a89f771")
}
}
Loading

0 comments on commit ffe8755

Please sign in to comment.