diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/nebulas/TestNebulasSigner.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/nebulas/TestNebulasSigner.kt index eaef41a986f..eea779b247a 100644 --- a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/nebulas/TestNebulasSigner.kt +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/nebulas/TestNebulasSigner.kt @@ -26,8 +26,8 @@ class TestNebulasSigner { gasPrice = ByteString.copyFrom("0x0f4240".toHexByteArray()) //1000000 gasLimit = ByteString.copyFrom("0x030d40".toHexByteArray()) //200000 amount = ByteString.copyFrom("0x98a7d9b8314c0000".toHexByteArray()) //11000000000000000000 + payload = "" timestamp = ByteString.copyFrom("0x5cfc84ca".toHexByteArray()) //1560052938 - payload = ByteString.copyFrom("\n\u0006binary".toByteArray()) //{10, 6, 98, 105, 110, 97, 114, 121} privateKey = ByteString.copyFrom(PrivateKey("d2fd0ec9f6268fc8d1f563e3e976436936708bdf0dc60c66f35890f5967a8d2b".toHexByteArray()).data()) } @@ -36,5 +36,7 @@ class TestNebulasSigner { assertEquals(output.algorithm, 1) assertEquals(output.signature.toByteArray().toHex(), "0xf53f4a9141ff8e462b094138eccd8c3a5d7865f9e9ab509626c78460a9e0b0fc35f7ed5ba1795ceb81a5e46b7580a6f7fb431d44fdba92515399cf6a8e47e71500") + assertEquals(output.raw, + "CiBQXdR2neMqnEu21q/U+OHqZHSBX9Q0hNiRfL2eCZO4hRIaGVefwtw23wEobqA40/7aIwQHghETxH4r+50aGhlXf89CeLWgHFjKu9/6tn4KNbelsMDAIIi2IhAAAAAAAAAAAJin2bgxTAAAKAcwyony5wU6CAoGYmluYXJ5QAFKEAAAAAAAAAAAAAAAAAAPQkBSEAAAAAAAAAAAAAAAAAADDUBYAWJB9T9KkUH/jkYrCUE47M2MOl14Zfnpq1CWJseEYKngsPw19+1boXlc64Gl5Gt1gKb3+0MdRP26klFTmc9qjkfnFQA=") } -} \ No newline at end of file +} diff --git a/include/TrustWalletCore/TWNebulasProto.h b/include/TrustWalletCore/TWNebulasProto.h index 31f226abe87..a151b904057 100644 --- a/include/TrustWalletCore/TWNebulasProto.h +++ b/include/TrustWalletCore/TWNebulasProto.h @@ -10,3 +10,5 @@ typedef TWData *_Nonnull TW_Nebulas_Proto_SigningInput; typedef TWData *_Nonnull TW_Nebulas_Proto_SigningOutput; +typedef TWData *_Nonnull TW_Nebulas_Proto_Data; +typedef TWData *_Nonnull TW_Nebulas_Proto_RawTransaction; diff --git a/js/tests/blockchain/nebulas/NebulasSigner.test.ts b/js/tests/blockchain/nebulas/NebulasSigner.test.ts index 34e17240d7f..c84f86901d7 100644 --- a/js/tests/blockchain/nebulas/NebulasSigner.test.ts +++ b/js/tests/blockchain/nebulas/NebulasSigner.test.ts @@ -13,7 +13,7 @@ describe('NebulasSigner', () => { gasLimit: fromHexString('0x030d40'), //200000 gasPrice: fromHexString('0x0f4240'), //1000000 nonce: fromHexString('0x7'), //7 - payload: new Uint8Array((('\n\x06binary').match(/[\s\S]/g)||[]).map(ch=>ch.charCodeAt(0))), //{10, 6, 98, 105, 110, 97, 114, 121} + payload: '', privateKey: PrivateKey.createWithData(fromHexString("0xd2fd0ec9f6268fc8d1f563e3e976436936708bdf0dc60c66f35890f5967a8d2b")).data(), timestamp: fromHexString("0x5cfc84ca"), //1560052938 toAddress: "n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17", @@ -22,6 +22,7 @@ describe('NebulasSigner', () => { expect(output.algorithm == 1); expect(bufToHex(output.signature)).to.equal('0xf53f4a9141ff8e462b094138eccd8c3a5d7865f9e9ab509626c78460a9e0b0fc35f7ed5ba1795ceb81a5e46b7580a6f7fb431d44fdba92515399cf6a8e47e71500'); + expect(output.raw == 'CiBQXdR2neMqnEu21q/U+OHqZHSBX9Q0hNiRfL2eCZO4hRIaGVefwtw23wEobqA40/7aIwQHghETxH4r+50aGhlXf89CeLWgHFjKu9/6tn4KNbelsMDAIIi2IhAAAAAAAAAAAJin2bgxTAAAKAcwyony5wU6CAoGYmluYXJ5QAFKEAAAAAAAAAAAAAAAAAAPQkBSEAAAAAAAAAAAAAAAAAADDUBYAWJB9T9KkUH/jkYrCUE47M2MOl14Zfnpq1CWJseEYKngsPw19+1boXlc64Gl5Gt1gKb3+0MdRP26klFTmc9qjkfnFQA='); }); }); diff --git a/src/Coin.cpp b/src/Coin.cpp index 27f06fd357c..4a030613f4b 100644 --- a/src/Coin.cpp +++ b/src/Coin.cpp @@ -300,7 +300,7 @@ std::string TW::deriveAddress(TWCoinType coin, const PublicKey& publicKey) { case TWCoinTypeWaves: return Waves::Address(publicKey).string(); - + case TWCoinTypeNebulas: return Nebulas::Address(publicKey).string(); } diff --git a/src/Nebulas/Signer.cpp b/src/Nebulas/Signer.cpp index af1e47ac1c8..fb798427d2f 100644 --- a/src/Nebulas/Signer.cpp +++ b/src/Nebulas/Signer.cpp @@ -5,15 +5,12 @@ // file LICENSE at the root of the source code distribution tree. #include "Signer.h" +#include "Base64.h" #include "../HexCoding.h" using namespace TW; using namespace TW::Nebulas; -const char *Signer::TxPayloadBinaryType = "binary"; -const char *Signer::TxPayloadDeployType = "deploy"; -const char *Signer::TxPayloadCallType = "call"; - Proto::SigningOutput Signer::sign(Proto::SigningInput &input) const noexcept { Transaction tx(Address(input.from_address()), load(input.nonce()), @@ -22,7 +19,7 @@ Proto::SigningOutput Signer::sign(Proto::SigningInput &input) const noexcept { Address(input.to_address()), load(input.amount()), load(input.timestamp()), - Data(input.payload().begin(), input.payload().end()) + input.payload() ); auto privateKey = PrivateKey(Data(input.private_key().begin(), input.private_key().end())); @@ -31,25 +28,34 @@ Proto::SigningOutput Signer::sign(Proto::SigningInput &input) const noexcept { auto protoOutput = Proto::SigningOutput(); protoOutput.set_algorithm(tx.algorithm); protoOutput.set_signature(reinterpret_cast(tx.signature.data()), tx.signature.size()); + protoOutput.set_raw(TW::Base64::encode(tx.raw)); return protoOutput; } void Signer::sign(const PrivateKey &privateKey, Transaction &transaction) const noexcept { - auto hash = this->hash(transaction); + transaction.hash = this->hash(transaction); + transaction.chainID = chainID; transaction.algorithm = 1; - transaction.signature = privateKey.sign(hash, TWCurveSECP256k1); + transaction.signature = privateKey.sign(transaction.hash, TWCurveSECP256k1); + transaction.serializeToRaw(); } Data Signer::hash(const Transaction &transaction) const noexcept { auto encoded = Data(); + auto payload = Data(); + auto data = Transaction::newPayloadData(transaction.payload); + payload.resize(data->ByteSize()); + data->SerializePartialToArray(payload.data(),(int)payload.size()); + delete data; + encoded.insert(encoded.end(), transaction.from.bytes.begin(), transaction.from.bytes.end()); encoded.insert(encoded.end(), transaction.to.bytes.begin(), transaction.to.bytes.end()); encode256BE(encoded, transaction.amount, 128); encode256BE(encoded, transaction.nonce, 64); encode256BE(encoded, transaction.timestamp, 64); - encoded.insert(encoded.end(), transaction.payload.begin(), transaction.payload.end()); + encoded.insert(encoded.end(), payload.begin(), payload.end()); encode256BE(encoded, chainID, 32); encode256BE(encoded, transaction.gasPrice, 128); encode256BE(encoded, transaction.gasLimit, 128); return Hash::sha3_256(encoded); -} +} \ No newline at end of file diff --git a/src/Nebulas/Signer.h b/src/Nebulas/Signer.h index 5be5e3af33f..1604f8f21d9 100644 --- a/src/Nebulas/Signer.h +++ b/src/Nebulas/Signer.h @@ -24,10 +24,6 @@ namespace TW::Nebulas { class Signer { public: uint256_t chainID; - - static const char* TxPayloadBinaryType; - static const char* TxPayloadDeployType; - static const char* TxPayloadCallType; /// Initializes a signer with a chain identifier. explicit Signer(uint256_t chainID) : chainID(std::move(chainID)) {} @@ -48,4 +44,4 @@ class Signer { /// Wrapper for C interface. struct TWNebulasSigner { TW::Nebulas::Signer impl; -}; +}; \ No newline at end of file diff --git a/src/Nebulas/Transaction.cpp b/src/Nebulas/Transaction.cpp new file mode 100644 index 00000000000..4923cf2b1bc --- /dev/null +++ b/src/Nebulas/Transaction.cpp @@ -0,0 +1,96 @@ +// Copyright © 2017-2019 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// Copyright © 2017-2019 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 +#include "Transaction.h" +#include "../HexCoding.h" + +using namespace TW; +using namespace TW::Nebulas; + +const char *Transaction::TxPayloadBinaryType = "binary"; +const char *Transaction::TxPayloadDeployType = "deploy"; +const char *Transaction::TxPayloadCallType = "call"; + +std::string htmlescape(const std::string& str) { + std::string result; + for(size_t i=0; i': result += "\\u003e"; break; + case '<': result += "\\u003c"; break; + case 0x20: + if(i+1 < str.size()) { + if(str[i+1]==0x28) { + result += "\\u2028"; + ++i; + break; + } + else if (str[i+1]==0x29) { + result += "\\u2029"; + ++i; + break; + } + } + default: result += str[i]; break; + } + } + return result; +} + +Proto::Data* Transaction::newPayloadData(const std::string& payload){ + auto data = new Proto::Data(); + data->set_type(Transaction::TxPayloadBinaryType); + + nlohmann::json payloadData; + if(!payload.empty()) { + auto json = nlohmann::json::parse(payload); + if(json.find("binary")!=json.end()) { + std::string binary_data = json["binary"]; + auto buff = Data(binary_data.begin(),binary_data.end()); + payloadData["Data"]["type"] = "Buffer"; + payloadData["Data"]["data"] = nlohmann::json(buff); + } + } + if(!payloadData.empty()) + data->set_payload(htmlescape(payloadData.dump())); + return data; +} + +void Transaction::serializeToRaw(){ + if(signature.empty()) { + throw std::logic_error("The transaction is unsigned!"); + } + + auto tx = Proto::RawTransaction(); + auto data = newPayloadData(payload); + + auto value = Data(); + auto gas_price = Data(); + auto gas_limit = Data(); + tx.set_hash(reinterpret_cast(hash.data()),hash.size()); + tx.set_from(from.bytes.data(),from.size); + tx.set_to(to.bytes.data(),to.size); + encode256BE(value, amount, 128); + tx.set_value(value.data(),value.size()); + tx.set_nonce((uint64_t)nonce); + tx.set_timestamp((int64_t)timestamp); + tx.set_allocated_data(data); + tx.set_chain_id((uint32_t)chainID); + encode256BE(gas_price, gasPrice, 128); + tx.set_gas_price(gas_price.data(),gas_price.size()); + encode256BE(gas_limit, gasLimit, 128); + tx.set_gas_limit(gas_limit.data(),gas_limit.size()); + + tx.set_alg((uint32_t)algorithm); + tx.set_sign(reinterpret_cast(signature.data()),signature.size()); + + raw.resize(tx.ByteSize()); + tx.SerializeToArray(raw.data(),(int)raw.size()); +} \ No newline at end of file diff --git a/src/Nebulas/Transaction.h b/src/Nebulas/Transaction.h index 6c148c88f40..176a622ba52 100644 --- a/src/Nebulas/Transaction.h +++ b/src/Nebulas/Transaction.h @@ -8,11 +8,16 @@ #include "Address.h" #include "../uint256.h" +#include "../proto/Nebulas.pb.h" namespace TW::Nebulas { class Transaction { public: + static const char* TxPayloadBinaryType; + static const char* TxPayloadDeployType; + static const char* TxPayloadCallType; + Address from; uint256_t nonce; uint256_t gasPrice; @@ -20,13 +25,18 @@ class Transaction { Address to; uint256_t amount; uint256_t timestamp; - std::vector payload; + std::string payload; // Signature values + uint256_t chainID; + Data hash; Data signature; uint32_t algorithm; - Transaction(Address from, uint256_t nonce, uint256_t gasPrice, uint256_t gasLimit, Address to, uint256_t amount, uint256_t timestamp, Data payload) + // serialize data + Data raw; + + Transaction(Address from, uint256_t nonce, uint256_t gasPrice, uint256_t gasLimit, Address to, uint256_t amount, uint256_t timestamp, const std::string& payload) : from(std::move(from)) , nonce(std::move(nonce)) , gasPrice(std::move(gasPrice)) @@ -34,7 +44,13 @@ class Transaction { , to(std::move(to)) , amount(std::move(amount)) , timestamp(std::move(timestamp)) - , payload(std::move(payload)){} + , payload(payload){} + + public: + static Proto::Data* newPayloadData(const std::string& payload); + + ///serialize the signed transaction. + void serializeToRaw(); }; -} // namespace TW::Nebulas +} // namespace TW::Nebulas \ No newline at end of file diff --git a/src/proto/Nebulas.proto b/src/proto/Nebulas.proto index 79c55c149ba..a76ca6bf83a 100644 --- a/src/proto/Nebulas.proto +++ b/src/proto/Nebulas.proto @@ -31,7 +31,7 @@ message SigningInput { bytes timestamp = 8; // Optional payload - bytes payload = 9; + string payload = 9; // Private key. bytes private_key = 10; @@ -41,4 +41,28 @@ message SigningInput { message SigningOutput { uint32 algorithm = 1; bytes signature = 2; + string raw = 3; } + +// +message Data { + string type = 1; + bytes payload = 2; +} + +// Raw transaction data +message RawTransaction { + bytes hash = 1; + bytes from = 2; + bytes to = 3; + bytes value = 4; + uint64 nonce = 5; + int64 timestamp = 6; + Data data = 7; + uint32 chain_id = 8; + bytes gas_price = 9; + bytes gas_limit = 10; + + uint32 alg = 11; + bytes sign = 12; +} \ No newline at end of file diff --git a/swift/Tests/Blockchains/NebulasTests.swift b/swift/Tests/Blockchains/NebulasTests.swift index 306a5311e37..7118fb7c310 100644 --- a/swift/Tests/Blockchains/NebulasTests.swift +++ b/swift/Tests/Blockchains/NebulasTests.swift @@ -26,13 +26,15 @@ class NebulasTests: XCTestCase { $0.gasLimit = Data(hexString: "030d40")! //200000 $0.toAddress = "n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17" $0.amount = Data(hexString: "98a7d9b8314c0000")! //11000000000000000000ULL + $0.payload = "" $0.timestamp = Data(hexString: "5cfc84ca")! //1560052938 - $0.payload = "\n\u{6}binary".data(using: String.Encoding.utf8)! //{10, 6, 98, 105, 110, 97, 114, 121} $0.privateKey = PrivateKey(data: Data(hexString: "d2fd0ec9f6268fc8d1f563e3e976436936708bdf0dc60c66f35890f5967a8d2b")!)!.data } let output = NebulasSigner.sign(input: input) XCTAssertEqual(output.algorithm, 1) - XCTAssertEqual(output.signature.hexString, - "f53f4a9141ff8e462b094138eccd8c3a5d7865f9e9ab509626c78460a9e0b0fc35f7ed5ba1795ceb81a5e46b7580a6f7fb431d44fdba92515399cf6a8e47e71500") + //swiftlint:disable:next line_length + XCTAssertEqual(output.signature.hexString, "f53f4a9141ff8e462b094138eccd8c3a5d7865f9e9ab509626c78460a9e0b0fc35f7ed5ba1795ceb81a5e46b7580a6f7fb431d44fdba92515399cf6a8e47e71500") + //swiftlint:disable:next line_length + XCTAssertEqual(output.raw, "CiBQXdR2neMqnEu21q/U+OHqZHSBX9Q0hNiRfL2eCZO4hRIaGVefwtw23wEobqA40/7aIwQHghETxH4r+50aGhlXf89CeLWgHFjKu9/6tn4KNbelsMDAIIi2IhAAAAAAAAAAAJin2bgxTAAAKAcwyony5wU6CAoGYmluYXJ5QAFKEAAAAAAAAAAAAAAAAAAPQkBSEAAAAAAAAAAAAAAAAAADDUBYAWJB9T9KkUH/jkYrCUE47M2MOl14Zfnpq1CWJseEYKngsPw19+1boXlc64Gl5Gt1gKb3+0MdRP26klFTmc9qjkfnFQA=") } } diff --git a/tests/Nebulas/SignerTests.cpp b/tests/Nebulas/SignerTests.cpp index 714e8f4dd06..e4110989309 100644 --- a/tests/Nebulas/SignerTests.cpp +++ b/tests/Nebulas/SignerTests.cpp @@ -28,7 +28,6 @@ TEST(NebulasSigner, EmptyData) { ASSERT_EQ(zero, uint256_t(0)); } -const char* payloadString = "\n\6binary"; //{10, 6, 98, 105, 110, 97, 114, 121} TEST(NebulasSigner, Hash) { auto from = Address("n1V5bB2tbaM3FUiL4eRwpBLgEredS5C2wLY"); auto to = Address("n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17"); @@ -40,7 +39,7 @@ TEST(NebulasSigner, Hash) { /* to: */ to, /* amount: */ 11000000000000000000ULL, /* timestamp: */ 1560052938, - /* payload: */ Data(payloadString,payloadString+8)); + /* payload: */ std::string()); auto signer = SignerExposed(1); auto hash = signer.hash(transaction); @@ -59,9 +58,9 @@ TEST(NebulasSigner, Sign) { input.set_gas_limit(value.data(),value.size()); value = store(uint256_t(11000000000000000000ULL)); input.set_amount(value.data(),value.size()); + input.set_payload(""); value = store(uint256_t(1560052938)); input.set_timestamp(value.data(),value.size()); - input.set_payload(payloadString); const auto privateKey = PrivateKey(parse_hex("d2fd0ec9f6268fc8d1f563e3e976436936708bdf0dc60c66f35890f5967a8d2b")); input.set_private_key(privateKey.bytes.data(), privateKey.bytes.size()); @@ -73,4 +72,4 @@ TEST(NebulasSigner, Sign) { ASSERT_EQ(hex(signature.begin(),signature.end()), "f53f4a9141ff8e462b094138eccd8c3a5d7865f9e9ab509626c78460a9e0b0fc35f7ed5ba1795ceb81a5e46b7580a6f7fb431d44fdba92515399cf6a8e47e71500"); } -} // namespace TW::Nebulas +} // namespace TW::Nebulas \ No newline at end of file diff --git a/tests/Nebulas/TransactionTests.cpp b/tests/Nebulas/TransactionTests.cpp new file mode 100644 index 00000000000..f6fbe316eec --- /dev/null +++ b/tests/Nebulas/TransactionTests.cpp @@ -0,0 +1,83 @@ +// Copyright © 2017-2019 Trust Wallet. +// +// Copyright © 2017-2019 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 "Nebulas/Signer.h" +#include "HexCoding.h" +#include "Base64.h" +#include "PrivateKey.h" + +#include + +using namespace std; +using namespace TW; +using namespace TW::Nebulas; + +extern std::string htmlescape(const std::string& str); + +TEST(NebulasTransaction, serialize) { + auto from = Address("n1V5bB2tbaM3FUiL4eRwpBLgEredS5C2wLY"); + auto to = Address("n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17"); + auto transaction = Transaction( + /* to: */ from, + /* nonce: */ 7, + /* gasPrice: */ 1000000, + /* gasLimit: */ 200000, + /* to: */ to, + /* amount: */ 11000000000000000000ULL, + /* timestamp: */ 1560052938, + /* payload: */ std::string()); + + const auto privateKey = PrivateKey(parse_hex("d2fd0ec9f6268fc8d1f563e3e976436936708bdf0dc60c66f35890f5967a8d2b")); + auto signer = Signer(1); + signer.sign(privateKey, transaction); + transaction.serializeToRaw(); + + ASSERT_EQ(TW::Base64::encode(transaction.raw), "CiBQXdR2neMqnEu21q/U+OHqZHSBX9Q0hNiRfL2eCZO4hRIaGVefwtw23wEobqA40/7aIwQHghETxH4r+50aGhlXf89CeLWgHFjKu9/6tn4KNbelsMDAIIi2IhAAAAAAAAAAAJin2bgxTAAAKAcwyony5wU6CAoGYmluYXJ5QAFKEAAAAAAAAAAAAAAAAAAPQkBSEAAAAAAAAAAAAAAAAAADDUBYAWJB9T9KkUH/jkYrCUE47M2MOl14Zfnpq1CWJseEYKngsPw19+1boXlc64Gl5Gt1gKb3+0MdRP26klFTmc9qjkfnFQA="); +} + +TEST(NebulasTransaction, binaryPayload) { + auto from = Address("n1V5bB2tbaM3FUiL4eRwpBLgEredS5C2wLY"); + auto to = Address("n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17"); + auto transaction = Transaction( + /* to: */ from, + /* nonce: */ 7, + /* gasPrice: */ 1000000, + /* gasLimit: */ 200000, + /* to: */ to, + /* amount: */ 11000000000000000000ULL, + /* timestamp: */ 1560052938, + /* payload: */ std::string("{\"binary\":\"test\"}")); + + const auto privateKey = PrivateKey(parse_hex("d2fd0ec9f6268fc8d1f563e3e976436936708bdf0dc60c66f35890f5967a8d2b")); + auto signer = Signer(1); + signer.sign(privateKey, transaction); + ASSERT_EQ(TW::Base64::encode(transaction.raw), "CiB1Oqj7bxLQMHEoNyg/vFHmsTrGdkpTf/5qFDkYPB3bkxIaGVefwtw23wEobqA40/7aIwQHghETxH4r+50aGhlXf89CeLWgHFjKu9/6tn4KNbelsMDAIIi2IhAAAAAAAAAAAJin2bgxTAAAKAcwyony5wU6PQoGYmluYXJ5EjN7IkRhdGEiOnsiZGF0YSI6WzExNiwxMDEsMTE1LDExNl0sInR5cGUiOiJCdWZmZXIifX1AAUoQAAAAAAAAAAAAAAAAAA9CQFIQAAAAAAAAAAAAAAAAAAMNQFgBYkGHXq+JWPaEyeB19bqL3QB5jyM961WLq7PMTpnGM4iLtBjCkngjS81kgPM2TE4qKDcpzqjum/NccrZtUPQLGk0MAQ=="); +} + +TEST(NebulasTransaction, htmlescape) { + // test for escaped label + auto test = ("test&<>\x20\x28\x20\x29"); + auto result = htmlescape(test); + ASSERT_EQ(result, "test\\u0026\\u003c\\u003e\\u2028\\u2029"); +} + +TEST(NebulasTransaction, serializeUnsigned) { + auto from = Address("n1V5bB2tbaM3FUiL4eRwpBLgEredS5C2wLY"); + auto to = Address("n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17"); + auto transaction = Transaction( + /* to: */ from, + /* nonce: */ 7, + /* gasPrice: */ 1000000, + /* gasLimit: */ 200000, + /* to: */ to, + /* amount: */ 11000000000000000000ULL, + /* timestamp: */ 1560052938, + /* payload: */ std::string()); + + ASSERT_THROW(transaction.serializeToRaw(),std::logic_error); +} \ No newline at end of file diff --git a/tests/interface/TWNebulasTests.cpp b/tests/interface/TWNebulasTests.cpp index 3c6c7a6b465..d0ae5196d93 100644 --- a/tests/interface/TWNebulasTests.cpp +++ b/tests/interface/TWNebulasTests.cpp @@ -54,4 +54,4 @@ TEST(Nebulas, AddressIsValidString) { EXPECT_FALSE(TWNebulasAddressIsValidString(STRING("a1V5bB2tbaM3FUiL4eRwpBLgEredS5C2wLY").get())); EXPECT_FALSE(TWNebulasAddressIsValidString(STRING("n2V5bB2tbaM3FUiL4eRwpBLgEredS5C2wLY").get())); EXPECT_FALSE(TWNebulasAddressIsValidString(STRING("n123").get())); -} \ No newline at end of file +}