Skip to content

Commit

Permalink
[Barz] Allow deriving multiple addresses from a single public key
Browse files Browse the repository at this point in the history
  • Loading branch information
rsrbk committed Jul 28, 2023
1 parent 45c0ff5 commit 1239b6e
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 13 deletions.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion include/TrustWalletCore/TWBarz.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ TWString *_Nonnull TWBarzGetCounterfactualAddress(TWData *_Nonnull input);
/// \param verificationFacet Verification facet address
/// \return The address.
TW_EXPORT_STATIC_METHOD
TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKey* _Nonnull publicKey, TWString* _Nonnull verificationFacet);
TWData *_Nonnull TWBarzGetInitCode(TWString* _Nonnull factory, struct TWPublicKey* _Nonnull publicKey, TWString* _Nonnull verificationFacet, uint32_t salt);

/// Converts the original ASN-encoded signature from webauthn to the format accepted by Barz
///
Expand Down
7 changes: 3 additions & 4 deletions src/Ethereum/Barz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include "EIP1014.h"
#include "Hash.h"
#include "HexCoding.h"
#include <WebAuthn.h>
#include "../proto/Barz.pb.h"
#include "AsnParser.h"
#include "Base64.h"
Expand All @@ -35,15 +34,15 @@ std::string getCounterfactualAddress(const Proto::ContractAddressInput input) {
append(initCode, encoded);

const Data initCodeHash = Hash::keccak256(initCode);
const Data salt(32, 0);
Data salt = store(input.salt(), 32);
return Ethereum::checksumed(Ethereum::Address(hexEncoded(Ethereum::create2Address(input.factory(), salt, initCodeHash))));
}

Data getInitCode(const std::string& factoryAddress, const PublicKey& publicKey, const std::string& verificationFacet) {
Data getInitCode(const std::string& factoryAddress, const PublicKey& publicKey, const std::string& verificationFacet, const uint32_t salt) {
auto createAccountFunc = Ethereum::ABI::Function("createAccount", ParamCollection{
std::make_shared<Ethereum::ABI::ParamAddress>(parse_hex(verificationFacet)),
std::make_shared<Ethereum::ABI::ParamByteArray>(publicKey.bytes),
std::make_shared<Ethereum::ABI::ParamUInt256>(0)});
std::make_shared<Ethereum::ABI::ParamUInt256>(salt)});
Data createAccountFuncEncoded;
createAccountFunc.encode(createAccountFuncEncoded);

Expand Down
2 changes: 1 addition & 1 deletion src/Ethereum/Barz.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace TW::Barz {

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

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

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

const auto initCode = TW::Barz::getInitCode(factoryStr, publicKeyConverted, verificationFacetStr);
const auto initCode = TW::Barz::getInitCode(factoryStr, publicKeyConverted, verificationFacetStr, salt);
return TWDataCreateWithData(&initCode);
}

Expand Down
3 changes: 3 additions & 0 deletions src/proto/Barz.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ message ContractAddressInput {
string bytecode = 7;
// PublicKey of the wallet
string public_key = 8;

// Salt is used to derive multiple account from the same public key
uint32 salt = 9;
}
28 changes: 27 additions & 1 deletion swift/Tests/BarzTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,19 @@ class BarzTests: XCTestCase {
let publicKeyData = Data(hexString: "0x04e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02")!
let publicKey = PublicKey(data: publicKeyData, type: .nist256p1Extended)!
let verificationFacet = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf"
let result = Barz.getInitCode(factory: factoryAddress, publicKey: publicKey, verificationFacet: verificationFacet)
let result = Barz.getInitCode(factory: factoryAddress, publicKey: publicKey, verificationFacet: verificationFacet, salt: 0)
XCTAssertEqual(result.hexString, "3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000")
}

func testInitCodeNoneZeroSalt() {
let factoryAddress = "0x3fC708630d85A3B5ec217E53100eC2b735d4f800"
let publicKeyData = Data(hexString: "0x04e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b02")!
let publicKey = PublicKey(data: publicKeyData, type: .nist256p1Extended)!
let verificationFacet = "0x6BF22ff186CC97D88ECfbA47d1473a234CEBEFDf"
let result = Barz.getInitCode(factory: factoryAddress, publicKey: publicKey, verificationFacet: verificationFacet, salt: 1)
XCTAssertEqual(result.hexString, "3fc708630d85a3b5ec217e53100ec2b735d4f800296601cd0000000000000000000000006bf22ff186cc97d88ecfba47d1473a234cebefdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004104e6f4e0351e2f556fd7284a9a033832bae046ac31fd529ad02ab6220870624b79eb760e718fdaed7a037dd1d77a561759cee9f2706eb55a729dc953e0d5719b0200000000000000000000000000000000000000000000000000000000000000")
}

func testCounterfactualAddress() {
let input = BarzContractAddressInput.with {
$0.factory = "0x2c97f4a366Dd5D91178ec9E36c5C1fcA393A538C"
Expand All @@ -29,6 +38,23 @@ class BarzTests: XCTestCase {
$0.defaultFallback = "0x22eB0720d9Fc4bC90BB812B309e939880B71c20d"
$0.bytecode = bytecode
$0.publicKey = "0xB5547FBdC56DCE45e1B8ef75569916D438e09c46"
$0.salt = 123456
}

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

func testCounterfactualAddressNonZeroSalt() {
let input = BarzContractAddressInput.with {
$0.factory = "0x2c97f4a366Dd5D91178ec9E36c5C1fcA393A538C"
$0.accountFacet = "0x3322C04EAe11B9b14c6c289f2668b6f07071b591"
$0.verificationFacet = "0x90A6fE0A938B0d4188e9013C99A0d7D9ca6bFB63"
$0.entryPoint = entryPoint
$0.facetRegistry = "0xFd1A8170c12747060324D9079a386BD4290e6f93"
$0.defaultFallback = "0x22eB0720d9Fc4bC90BB812B309e939880B71c20d"
$0.bytecode = bytecode
$0.publicKey = "0xB5547FBdC56DCE45e1B8ef75569916D438e09c46"
$0.salt = 0
}

XCTAssertEqual(Barz.getCounterfactualAddress(input: try! input.serializedData()), "0x77F62bb3E43190253D4E198199356CD2b25063cA");
Expand Down
58 changes: 54 additions & 4 deletions tests/chains/Ethereum/BarzTests.cpp

Large diffs are not rendered by default.

0 comments on commit 1239b6e

Please sign in to comment.