Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/02_cleos/03_command-reference/convert/index.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
## Description
Pack and unpack transactions
Pack and unpack transactions or convert public key format

## subcommands
- [pack_transaction](pack_transaction.md) - From plain signed json to packed form
- [unpack_transaction](unpack_transaction.md) - From packed to plain signed json form
- [pack_action_data](pack_action_data.md) - From json action data to packed form
- [unpack_action_data](unpack_action_data.md) - From packed to json action data form
- [legacy_public_key](legacy_public_key.md) - From public key to legacy format (EOS, PUB_R1, PUB_WA)
- [public_key](public_key.md) - From public key to canonical format (PUB_K1, PUB_R1, PUB_WA)
27 changes: 27 additions & 0 deletions docs/02_cleos/03_command-reference/convert/legacy_public_key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Description
Converts a public key to the legacy key format (EOS prefix for k1 keys, PUB_R1 prefix for r1 keys, PUB_WA prefix for WebAuthn keys)

If the key is already in the legacy format it will be output unchanged.

Only the k1 key format differs between legacy format and canonical format.

## Positionals

- `public_key` _TEXT_ - The public key to output in legacy format

## Options

- `-h,--help` - Print this help message and exit

## Usage


```sh
cleos convert legacy_public_key PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63
```

## Output

```
EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
```
27 changes: 27 additions & 0 deletions docs/02_cleos/03_command-reference/convert/public_key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Description
Converts a public key to the canonical key format (PUB_K1 prefix for k1 keys, PUB_R1 prefix for r1 keys, PUB_WA prefix for WebAuthn keys)

If the key is already in the canonical format it will be output unchanged.

Only the k1 key format differs between legacy format and canonical format.

## Positionals

- `public_key` _TEXT_ - The public key to output in new format

## Options

- `-h,--help` - Print this help message and exit

## Usage


```sh
cleos convert public_key EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
```

## Output

```
PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63
```
1 change: 1 addition & 0 deletions libraries/libfc/include/fc/crypto/public_key.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ namespace fc { namespace crypto {

// serialize to/from string
explicit public_key(const std::string& base58str);
std::string to_legacy_string(const fc::yield_function_t& yield) const;
std::string to_string(const fc::yield_function_t& yield) const;

storage_type _storage;
Expand Down
11 changes: 10 additions & 1 deletion libraries/libfc/src/crypto/public_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ namespace fc { namespace crypto {
return std::visit(is_valid_visitor(), _storage);
}

std::string public_key::to_string(const fc::yield_function_t& yield) const
// output in pre Spring-2.0 format: EOS, PUB_R1, PUB_WA
std::string public_key::to_legacy_string(const fc::yield_function_t& yield) const
{
auto data_str = std::visit(base58str_visitor<storage_type, config::public_key_prefix, 0>(yield), _storage);

Expand All @@ -84,6 +85,14 @@ namespace fc { namespace crypto {
}
}

//output for Spring 2.0+: PUB_K1, PUB_R1, PUB_WA
std::string public_key::to_string(const fc::yield_function_t& yield) const
{
auto data_str = std::visit(base58str_visitor<storage_type, config::public_key_prefix>(yield), _storage);

return std::string(config::public_key_base_prefix) + "_" + data_str;
}

std::ostream& operator<<(std::ostream& s, const public_key& k) {
s << "public_key(" << k.to_string({}) << ')';
return s;
Expand Down
13 changes: 12 additions & 1 deletion libraries/libfc/test/crypto/test_cypher_suites.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,20 @@ using namespace fc::crypto;
using namespace fc;

BOOST_AUTO_TEST_SUITE(cypher_suites)
BOOST_AUTO_TEST_CASE(test_k1_legacy_to_new) try {
BOOST_CHECK_EQUAL(public_key("EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV").to_string({}), "PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63");
} FC_LOG_AND_RETHROW();

BOOST_AUTO_TEST_CASE(test_k1_legacy_and_new_underlying_match) try {
public_key from_legacy("EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV");
public_key from_new(from_legacy.to_string({}));

BOOST_CHECK(std::get<ecc::public_key_shim>(from_legacy._storage)._data == std::get<ecc::public_key_shim>(from_new._storage)._data);
} FC_LOG_AND_RETHROW();

BOOST_AUTO_TEST_CASE(test_k1) try {
auto private_key_string = std::string("5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3");
auto expected_public_key = std::string("EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV");
auto expected_public_key = std::string("PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63");
auto test_private_key = private_key(private_key_string);
auto test_public_key = test_private_key.get_public_key();

Expand Down
2 changes: 1 addition & 1 deletion programs/cleos/help_text.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ auto smatch_to_variant(const std::smatch& smatch) {
};

const char* error_advice_name_type_exception = R"=====(Name should be less than 13 characters and only contains the following symbol .12345abcdefghijklmnopqrstuvwxyz)=====";
const char* error_advice_public_key_type_exception = R"=====(Public key should be encoded in base58 and starts with EOS prefix)=====";
const char* error_advice_public_key_type_exception = R"=====(Public key should be encoded in base58 and starts with PUB_ or EOS prefix)=====";
const char* error_advice_private_key_type_exception = R"=====(Private key should be encoded in base58 WIF)=====";
const char* error_advice_authority_type_exception = R"=====(Ensure that your authority JSON is valid follows the following format!
{
Expand Down
20 changes: 19 additions & 1 deletion programs/cleos/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2876,7 +2876,7 @@ int main( int argc, char** argv ) {
auto createAccount = create_account_subcommand( create, true /*simple*/ );

// convert subcommand
auto convert = app.add_subcommand("convert", localized("Pack and unpack transactions")); // TODO also add converting action args based on abi from here ?
auto convert = app.add_subcommand("convert", localized("Pack and unpack transactions or convert public key format")); // TODO also add converting action args based on abi from here ?
convert->require_subcommand();

// pack transaction
Expand Down Expand Up @@ -2958,6 +2958,24 @@ int main( int argc, char** argv ) {
std::cout << fc::json::to_pretty_string(unpacked_action_data_json) << std::endl;
});

string public_key_to_convert;
// output public key in legacy format
auto legacy_public_key = convert->add_subcommand("legacy_public_key", localized("From public key to legacy format (EOS, PUB_R1, PUB_WA)"));
legacy_public_key->add_option("public_key", public_key_to_convert, localized("Public key to output in legacy format"))->required();
legacy_public_key->callback([&] {
try {
std::cout << crypto::public_key(public_key_to_convert).to_legacy_string({}) << std::endl;
} EOS_RETHROW_EXCEPTIONS(public_key_type_exception, "Failed to parse public key");
});
// output public key in canonical format
auto public_key = convert->add_subcommand("public_key", localized("From public key to canonical format (PUB_K1, PUB_R1, PUB_WA)"));
public_key->add_option("public_key", public_key_to_convert, localized("Public key to output in canonical format"))->required();
public_key->callback([&] {
try {
std::cout << crypto::public_key(public_key_to_convert).to_string({}) << std::endl;
} EOS_RETHROW_EXCEPTIONS(public_key_type_exception, "Failed to parse public key");
});

// validate subcommand
auto validate = app.add_subcommand("validate", localized("Validate transactions"));
validate->require_subcommand();
Expand Down
12 changes: 12 additions & 0 deletions tests/cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,17 @@ def abi_file_with_nodeos_test():

walletMgr.testFailed = not testSuccessful

def public_key_convert_test():
assert(processCleosCommand(['./programs/cleos/cleos', 'convert', 'legacy_public_key', 'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV'])[0] == b'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV\n')
assert(processCleosCommand(['./programs/cleos/cleos', 'convert', 'legacy_public_key', 'PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63'])[0] == b'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV\n')
assert(processCleosCommand(['./programs/cleos/cleos', 'convert', 'public_key', 'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV'])[0] == b'PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63\n')
assert(processCleosCommand(['./programs/cleos/cleos', 'convert', 'public_key', 'PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63'])[0] == b'PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63\n')

assert(processCleosCommand(['./programs/cleos/cleos', 'convert', 'legacy_public_key', 'PUB_R1_6p9aKPd9zweERtaPwp2vEyVgQcdmyYBstH3vYocLiwuETfJm7r'])[0] == b'PUB_R1_6p9aKPd9zweERtaPwp2vEyVgQcdmyYBstH3vYocLiwuETfJm7r\n')

_, errs = processCleosCommand(['./programs/cleos/cleos', 'convert', 'legacy_public_key', 'BANANA6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV'])
assert(b'Invalid public key' in errs)

nodeos_help_test()

cleos_help_test(['--help'])
Expand All @@ -427,6 +438,7 @@ def abi_file_with_nodeos_test():

cleos_abi_file_test()
abi_file_with_nodeos_test()
public_key_convert_test()

errorCode = 0 if testSuccessful else 1
exit(errorCode)
12 changes: 6 additions & 6 deletions unittests/abi_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -939,9 +939,9 @@ BOOST_AUTO_TEST_CASE(updateauth_test)
BOOST_TEST(2147483145u == updauth.auth.threshold);

BOOST_TEST_REQUIRE(2u == updauth.auth.keys.size());
BOOST_TEST("EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im" == updauth.auth.keys[0].key.to_string({}));
BOOST_TEST("PUB_K1_65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6ZoHPHw" == updauth.auth.keys[0].key.to_string({}));
BOOST_TEST(57005u == updauth.auth.keys[0].weight);
BOOST_TEST("EOS5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWRzbJf" == updauth.auth.keys[1].key.to_string({}));
BOOST_TEST("PUB_K1_5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWpj3BS" == updauth.auth.keys[1].key.to_string({}));
BOOST_TEST(57605u == updauth.auth.keys[1].weight);

BOOST_TEST_REQUIRE(2u == updauth.auth.accounts.size());
Expand Down Expand Up @@ -1043,9 +1043,9 @@ BOOST_AUTO_TEST_CASE(newaccount_test)
BOOST_TEST(2147483145u == newacct.owner.threshold);

BOOST_TEST_REQUIRE(2u == newacct.owner.keys.size());
BOOST_TEST("EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im" == newacct.owner.keys[0].key.to_string({}));
BOOST_TEST("PUB_K1_65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6ZoHPHw" == newacct.owner.keys[0].key.to_string({}));
BOOST_TEST(57005u == newacct.owner.keys[0].weight);
BOOST_TEST("EOS5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWRzbJf" == newacct.owner.keys[1].key.to_string({}));
BOOST_TEST("PUB_K1_5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWpj3BS" == newacct.owner.keys[1].key.to_string({}));
BOOST_TEST(57605u == newacct.owner.keys[1].weight);

BOOST_TEST_REQUIRE(2u == newacct.owner.accounts.size());
Expand All @@ -1059,9 +1059,9 @@ BOOST_AUTO_TEST_CASE(newaccount_test)
BOOST_TEST(2146483145u == newacct.active.threshold);

BOOST_TEST_REQUIRE(2u == newacct.active.keys.size());
BOOST_TEST("EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im" == newacct.active.keys[0].key.to_string({}));
BOOST_TEST("PUB_K1_65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6ZoHPHw" == newacct.active.keys[0].key.to_string({}));
BOOST_TEST(57005u == newacct.active.keys[0].weight);
BOOST_TEST("EOS5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWRzbJf" == newacct.active.keys[1].key.to_string({}));
BOOST_TEST("PUB_K1_5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWpj3BS" == newacct.active.keys[1].key.to_string({}));
BOOST_TEST(57605u == newacct.active.keys[1].weight);

BOOST_TEST_REQUIRE(2u == newacct.active.accounts.size());
Expand Down
Loading
Loading