Skip to content

Commit

Permalink
[Anysigner] Add support to IoTeX, Wanchain and Waves (#624)
Browse files Browse the repository at this point in the history
* Add IoTex and Wanchain

* Add waves support

* Add tron and nebulas support

* Added more ethereum based coins
  • Loading branch information
leoneparise authored Sep 5, 2019
1 parent 0edbfa1 commit 53843d9
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 0 deletions.
90 changes: 90 additions & 0 deletions src/Any/Signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
#include "Binance/Signer.h"
#include "Ethereum/Signer.h"
#include "Tezos/Signer.h"
#include "IoTeX/Signer.h"
#include "Wanchain/Signer.h"
#include "Waves/Signer.h"
#include "Nebulas/Signer.h"
#include "Tron/Signer.h"

#include <string>
#include <google/protobuf/util/json_util.h>
Expand Down Expand Up @@ -50,6 +55,11 @@ Any::Proto::SigningOutput Any::Signer::sign() const noexcept {
}
break;
}
case TWCoinTypeTomoChain:
case TWCoinTypeCallisto:
case TWCoinTypeThunderToken:
case TWCoinTypePOANetwork:
case TWCoinTypeEthereumClassic:
case TWCoinTypeEthereum: {
Ethereum::Proto::SigningInput message;
parse(transaction, &message, output);
Expand All @@ -74,6 +84,79 @@ Any::Proto::SigningOutput Any::Signer::sign() const noexcept {
}
break;
}
case TWCoinTypeIoTeX: {
IoTeX::Proto::SigningInput message;
parse(transaction, &message, output);
if (output.success()) {
message.set_privatekey(privateKey.bytes.data(), privateKey.bytes.size());
auto signerOutput = IoTeX::Signer(std::move(message)).build();
auto encoded = signerOutput.encoded();
output.set_output(hex(encoded.begin(), encoded.end()));
}
break;
}
case TWCoinTypeWanchain: {
Ethereum::Proto::SigningInput message;
parse(transaction, &message, output);
if (output.success()) {
auto ethTransaction = Ethereum::Transaction(
/* nonce: */ load(message.nonce()),
/* gasPrice: */ load(message.gas_price()),
/* gasLimit: */ load(message.gas_limit()),
/* to: */ Ethereum::Address(message.to_address()),
/* amount: */ load(message.amount()),
/* payload: */ Data(message.payload().begin(), message.payload().end())
);
auto signer = Wanchain::Signer(load(message.chain_id()));
signer.sign(privateKey, ethTransaction);
auto encoded = signer.encode(ethTransaction);
output.set_output(hex(encoded.begin(), encoded.end()));
}
break;
}
case TWCoinTypeWaves: {
Waves::Proto::SigningInput message;
parse(transaction, &message, output);
if (output.success()) {
auto publicKey = privateKey.getPublicKey(TWPublicKeyTypeCURVE25519);
auto wavesTransaction = Waves::Transaction(
/* amount */ message.amount(),
/* asset */ message.asset(),
/* fee */ message.fee(),
/* fee_asset */ message.fee_asset(),
/* to */ Waves::Address(message.to()),
/* attachment */ Data(message.attachment().begin(), message.attachment().end()),
/* timestamp */ message.timestamp(),
/* pub_key */ publicKey.bytes
);
auto signature = Waves::Signer::sign(privateKey, wavesTransaction);
auto jsonOutput = wavesTransaction.buildJson(signature).dump();
output.set_output(jsonOutput);
}
break;
}
case TWCoinTypeNebulas: {
Nebulas::Proto::SigningInput message;
parse(transaction, &message, output);
if (output.success()) {
message.set_private_key(privateKey.bytes.data(), privateKey.bytes.size());
auto signerOutput = Nebulas::Signer(load(message.chain_id())).sign(message);
auto signature = signerOutput.signature();
output.set_output(hex(signature.begin(), signature.end()));
}
break;
}
case TWCoinTypeTron: {
Tron::Proto::SigningInput message;
parse(transaction, &message, output);
if (output.success()) {
message.set_private_key(privateKey.bytes.data(), privateKey.bytes.size());
auto signerOutput = Tron::Signer::sign(message);
auto signature = signerOutput.signature();
output.set_output(hex(signature.begin(), signature.end()));
}
break;
}
default:
auto error = new Proto::SigningOutput_Error();
error->set_code(SignerErrorCodeNotSupported);
Expand Down Expand Up @@ -102,3 +185,10 @@ void Any::Signer::parse(const std::string& transaction, Message* message,
error->set_description(result.error_message());
output.set_allocated_error(error);
}

void Any::Signer::toJson(const google::protobuf::Message &message, std::string *json_string) const noexcept {
util::JsonPrintOptions options;
options.preserve_proto_field_names = true;

MessageToJsonString(message, json_string, options);
}
1 change: 1 addition & 0 deletions src/Any/Signer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Signer {
const Proto::SigningInput& input;

void parse(const std::string &transaction, google::protobuf::Message *message, Proto::SigningOutput &output) const noexcept;
void toJson(const google::protobuf::Message &message, std::string *json_string) const noexcept;
};

}
Expand Down
75 changes: 75 additions & 0 deletions tests/Any/SignerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,81 @@ TEST(Signer, TezosTransactionSign) {
output.output());
}

TEST(Signer, IoTeXTransactionSign) {
auto transaction = R"({"version": 1,"nonce": 123,"gasLimit": 888,"gasPrice": "999","transfer": {"amount": "456","recipient": "io187wzp08vnhjjpkydnr97qlh8kh0dpkkytfam8j","payload": "aGVsbG8gd29ybGQh"}})";
auto input = Proto::SigningInput();
input.set_private_key("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f");
input.set_transaction(transaction);
input.set_coin_type(TWCoinTypeIoTeX);

auto signer = Signer(input);
auto output = signer.sign();

ASSERT_TRUE(output.success());;
ASSERT_EQ("0a4c0801107b18f8062203393939523e0a033435361229696f313837777a703038766e686a6a706b79646e723937716c68386b683064706b6b797466616d386a1a0c68656c6c6f20776f726c64211241044e18306ae9ef4ec9d07bf6e705442d4d1a75e6cdf750330ca2d880f2cc54607c9c33deb9eae9c06e06e04fe9ce3d43962cc67d5aa34fbeb71270d4bad3d648d91a41555cc8af4181bf85c044c3201462eeeb95374f78aa48c67b87510ee63d5e502372e53082f03e9a11c1e351de539cedf85d8dff87de9d003cb9f92243541541a000",
output.output());
}

TEST(Signer, WanchainTransactionSign) {
auto transaction = R"({"chainId": "MQ==","toAddress": "0x3535353535353535353535353535353535353535","nonce": "OQ==","gasPrice": "MjAwMDAwMDAwMDA=","gasLimit": "MjEwMDA=","amount": "MTAwMDAwMDAwMDAwMDAwMDAwMA=="})";
auto input = Proto::SigningInput();
input.set_private_key("4646464646464646464646464646464646464646464646464646464646464646");
input.set_transaction(transaction);
input.set_coin_type(TWCoinTypeWanchain);

auto signer = Signer(input);
auto output = signer.sign();

ASSERT_TRUE(output.success());;
ASSERT_EQ("f88201398b32303030303030303030308532313030309435353535353535353535353535353535353535359331303030303030303030303030303030303030808185a0f7bca5c00884bcba5c068f507a33559df775e09785fc55956c9bbe4276259a4ca06679fc4f853b7f224ac8096d15005a3d1070c81a0a13aee8e60a72654273fe5e",
output.output());
}

TEST(Signer, WavesTransactionSign) {
auto transaction = R"({"amount": 100000000,"asset": "WAVES","fee": 100000000,"fee_asset": "WAVES","to": "3P2uzAzX9XTu1t32GkWw68YFFLwtapWvDds","attachment": "ZmFsYWZlbA==","timestamp": 1526641218066})";
auto input = Proto::SigningInput();
input.set_private_key("9864a747e1b97f131fabb6b447296c9b6f0201e79fb3c5356e6c77e89b6a806a");
input.set_transaction(transaction);
input.set_coin_type(TWCoinTypeWaves);

auto signer = Signer(input);
auto output = signer.sign();

ASSERT_TRUE(output.success());;
ASSERT_EQ(R"({"amount":100000000,"attachment":"4t2Xazb2SX","fee":100000000,"proofs":["4WUvsbgA2EsyCd5C7jHS57SgvPNczXYnxyKSvAzm18vtRhvbjjH9Dq2vUDgqm8h4GcDzzueQnHg3WH4xTyxDJ1Hg"],"recipient":"3P2uzAzX9XTu1t32GkWw68YFFLwtapWvDds","senderPublicKey":"6mA8eQjie53kd4jbZrwL3ZhMBqCX6nzit1k55tR2X7zU","timestamp":1526641218066,"type":4,"version":2})",
output.output());
}

TEST(Signer, NebulasTransactionSign) {
auto transaction = R"({"fromAddress": "n1V5bB2tbaM3FUiL4eRwpBLgEredS5C2wLY","chainId": "MQ==","nonce": "Nw==","gasPrice": "MTAwMDAwMA==","gasLimit": "MjAwMDAw","toAddress": "n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17","amount": "MTEwMDAwMDAwMDAwMDAwMDAwMDA=","timestamp": "MTU2MDA1MjkzOA==","payload": ""})";
auto input = Proto::SigningInput();
input.set_private_key("d2fd0ec9f6268fc8d1f563e3e976436936708bdf0dc60c66f35890f5967a8d2b");
input.set_transaction(transaction);
input.set_coin_type(TWCoinTypeNebulas);

auto signer = Signer(input);
auto output = signer.sign();

ASSERT_TRUE(output.success());;
ASSERT_EQ("17aca84f1c31f2065123ff14d53f10e2c2a8cd6e99f75fb9b11a2bc7bacb14e05c29f2267c700f9f1c5b9df26bddc5972993c71be651c5c7872683e23cdd80c301",
output.output());
}

TEST(Signer, TronTransactionSign) {
auto transaction = R"({"transaction": {"timestamp": 1539295479000,"expiration": 1539331479000,"blockHeader": {"timestamp": 1539295479000,"txTrieRoot": "ZCiMLbBkExZ2KpnbsC73yQ+Wi2D58uQQg1mAYUMy+G0=","parentHash": "AAAAAAAvezr09fi54jowxTD3GfFlt0LnNYU2soDurS0=","number": 3111739,"witnessAddress": "QVhj9gkbjnF2bagIsd0xWXkPYd59","version": 3},"transfer": {"ownerAddress": "TJRyWwFs9wTFGZg3JbrVriFbNfCug5tDeC","toAddress": "THTR75o8xXAgCTQqpiot2AFRAjvW1tSbVV","amount": 2000000}}})";
auto input = Proto::SigningInput();
input.set_private_key("2d8f68944bdbfbc0769542fba8fc2d2a3de67393334471624364c7006da2aa54");
input.set_transaction(transaction);
input.set_coin_type(TWCoinTypeTron);

auto signer = Signer(input);
auto output = signer.sign();

ASSERT_TRUE(output.success());;
ASSERT_EQ("ede769f6df28aefe6a846be169958c155e23e7e5c9621d2e8dce1719b4d952b63e8a8bf9f00e41204ac1bf69b1a663dacdf764367e48e4a5afcd6b055a747fb200",
output.output());
}

TEST(Signer, NetworkNotSupported) {
auto transaction = R"({"accountNumber":"8733","chainId":"cosmoshub-2","fee":{"amounts":[{"denom":"uatom","amount":"5000"}],"gas":"200000"},"memo":"Testing","sendCoinsMessage":{"fromAddress":"cosmos1ufwv9ymhqaal6xz47n0jhzm2wf4empfqvjy575","toAddress":"cosmos135qla4294zxarqhhgxsx0sw56yssa3z0f78pm0","amounts":[{"denom":"uatom","amount":"995000"}]}})";
auto input = Proto::SigningInput();
Expand Down
2 changes: 2 additions & 0 deletions tests/Wanchain/SignerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ TEST(Signer, Sign) {
auto key = PrivateKey(parse_hex("0x4646464646464646464646464646464646464646464646464646464646464646"));
auto signer = SignerExposed(1);
signer.sign(key, transaction);
auto encoded = signer.encode(transaction);

ASSERT_EQ(hex(encoded.begin(), encoded.end()), "f86d01098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a0b3efa52659bb3dfcc1356942a5024ca55d742d8a2b551a142c5a0427c11c6272a07f616e839104c8c9c8f83254afc4e5c7010293cd5e471f6756629d17c8392467");
ASSERT_EQ(transaction.v, 37);
ASSERT_EQ(transaction.r, uint256_t("81387416166961732074688826827458851755389597777750181844865627349674117325426"));
ASSERT_EQ(transaction.s, uint256_t("57615878674481745412864351256912693004505281517367788339541976444424345429095"));
Expand Down

0 comments on commit 53843d9

Please sign in to comment.