Skip to content

Commit

Permalink
[Nimiq]: Add networkId parameter to SigningInput
Browse files Browse the repository at this point in the history
  • Loading branch information
satoshiotomakan committed Nov 18, 2024
1 parent 5cc17bb commit ebcfdfa
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 15 deletions.
3 changes: 2 additions & 1 deletion src/Nimiq/Signer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ Proto::SigningOutput Signer::sign(const Proto::SigningInput& input) noexcept {
/* destination */Address(input.destination()),
/* amount */input.value(),
/* fee */input.fee(),
/* vsh */input.validity_start_height()
/* vsh */input.validity_start_height(),
/* networkId */input.network_id()
);

auto signer = Signer();
Expand Down
38 changes: 33 additions & 5 deletions src/Nimiq/Transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,33 @@

namespace TW::Nimiq {

const uint8_t NETWORK_ID = 24;
const uint8_t EMPTY_FLAGS = 0;

std::vector<uint8_t> Transaction::serialize() const {
// Source code:
// https://github.com/nimiq/core-rs-albatross/blame/b8ed402c9096ffb54afea52347b91ab7831e75de/primitives/transaction/src/lib.rs#L699

std::vector<uint8_t> data;

data.push_back(0x00); // Basic TX type
data.push_back(0x00); // Signature Proof type and flags (Ed25519 type and no flags)
if (isAlbatross()) {
data.push_back(0x00); // Signature Proof type and flags (Ed25519 type and no flags)
}
data.insert(data.end(), sender_pub_key.begin(), sender_pub_key.end());
data.insert(data.end(), destination.bytes.begin(), destination.bytes.end());
encode64BE(amount, data);
encode64BE(fee, data);
encode32BE(vsh, data);
data.push_back(NETWORK_ID);
data.push_back(consensusNetworkId());
data.insert(data.end(), signature.begin(), signature.end());

return data;
}

std::vector<uint8_t> Transaction::getPreImage() const {
// Source code:
// https://github.com/nimiq/core-rs-albatross/blame/b8ed402c9096ffb54afea52347b91ab7831e75de/primitives/transaction/src/lib.rs#L582

std::vector<uint8_t> data;

// Build pre-image
Expand All @@ -41,11 +48,32 @@ std::vector<uint8_t> Transaction::getPreImage() const {
encode64BE(amount, data);
encode64BE(fee, data);
encode32BE(vsh, data);
data.push_back(NETWORK_ID);
data.push_back(consensusNetworkId());
data.push_back(EMPTY_FLAGS);
data.push_back(0x00); // Sender Data size (+ 0 bytes of data)
if (isAlbatross()) {
data.push_back(0x00); // Sender Data size (+ 0 bytes of data)
}

return data;
}

bool Transaction::isAlbatross() const {
if (networkId == Proto::NetworkId::MainnetAlbatross) {
return true;
}
return false;
}

uint32_t Transaction::consensusNetworkId() const {
switch (networkId) {
case Proto::NetworkId::UseDefault:
case Proto::NetworkId::Mainnet:
return static_cast<uint32_t>(Proto::NetworkId::Mainnet);
case Proto::NetworkId::MainnetAlbatross:
return static_cast<uint32_t>(Proto::NetworkId::MainnetAlbatross);
default:
throw std::invalid_argument("Invalid network ID");
}
}

} // namespace TW::Nimiq
11 changes: 9 additions & 2 deletions src/Nimiq/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma once

#include "Address.h"
#include "proto/Nimiq.pb.h"

namespace TW::Nimiq {

Expand All @@ -20,16 +21,22 @@ class Transaction {
uint64_t fee;
// Validity start (block) height
uint32_t vsh;
// Network ID
Proto::NetworkId networkId;
// Sender signature
std::array<uint8_t, 64> signature;

Transaction(const std::array<uint8_t, 32>& sender, const Address& dest, uint64_t amount,
uint64_t fee, uint32_t vsh)
: sender_pub_key(sender), destination(dest), amount(amount), fee(fee), vsh(vsh) {}
uint64_t fee, uint32_t vsh, Proto::NetworkId networkId)
: sender_pub_key(sender), destination(dest), amount(amount), fee(fee), vsh(vsh), networkId(networkId) {}

public:
std::vector<uint8_t> serialize() const;
std::vector<uint8_t> getPreImage() const;

private:
bool isAlbatross() const;
uint32_t consensusNetworkId() const;
};

} // namespace TW::Nimiq
11 changes: 11 additions & 0 deletions src/proto/Nimiq.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ syntax = "proto3";
package TW.Nimiq.Proto;
option java_package = "wallet.core.jni.proto";

enum NetworkId {
UseDefault = 0;
// Default PoW Mainnet.
Mainnet = 42;
// PoS Mainnet starting at the PoW block height 3’456’000.
MainnetAlbatross = 24;
}

// Input data necessary to create a signed transaction.
message SigningInput {
// The secret private key used for signing (32 bytes).
Expand All @@ -19,6 +27,9 @@ message SigningInput {

// Validity start, in block height
uint32 validity_start_height = 5;

// Network ID.
NetworkId network_id = 6;
}

// Result containing the signed and encoded transaction.
Expand Down
5 changes: 3 additions & 2 deletions tests/chains/Nimiq/SignerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ TEST(NimiqSigner, Sign) {
Address("NQ86 2H8F YGU5 RM77 QSN9 LYLH C56A CYYR 0MLA"),
42042042,
1000,
314159
314159,
Proto::NetworkId::Mainnet
);

Signer signer;
signer.sign(privateKey, tx);

ASSERT_EQ(hex(tx.signature),
"0ba678744be3bf9cd44fbcdabfb5be209f21739934836e26055610ab02720fa99489219d9f3581664473a1b40b30ad1f6e13150d59f8234a42c3f0de3d505405");
"74dc7f6e0ab58a0bf52cc6e8801b0cca132dd4229d9a3e3a3d2f90e4d8f045d981b771bf5fc3851a98f3c617b1a943228f963e910e061808a721cfa0e3cad50b");
}

} // namespace TW::Nimiq
18 changes: 18 additions & 0 deletions tests/chains/Nimiq/TWAnySignerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ TEST(TWAnySignerNimiq, Sign) {
Proto::SigningOutput output;
ANY_SIGN(input, TWCoinTypeNimiq);

EXPECT_EQ(hex(output.encoded()), "0070c7492aaa9c9ac7a05bc0d9c5db2dae9372029654f71f0c7f95deed5099b7021450ffc385cd4e7c6ac9a7e91614ca67ff90568a00000000028182ba00000000000003e80004cb2f2a74dc7f6e0ab58a0bf52cc6e8801b0cca132dd4229d9a3e3a3d2f90e4d8f045d981b771bf5fc3851a98f3c617b1a943228f963e910e061808a721cfa0e3cad50b");
}

TEST(TWAnySignerNimiq, SignPoS) {
auto privateKey = parse_hex("e3cc33575834add098f8487123cd4bca543ee859b3e8cfe624e7e6a97202b756");

Proto::SigningInput input;

input.set_destination("NQ86 2H8F YGU5 RM77 QSN9 LYLH C56A CYYR 0MLA");
input.set_fee(1000);
input.set_value(42042042);
input.set_validity_start_height(314159);
input.set_private_key(privateKey.data(), privateKey.size());
input.set_network_id(Proto::NetworkId::MainnetAlbatross);

Proto::SigningOutput output;
ANY_SIGN(input, TWCoinTypeNimiq);

EXPECT_EQ(hex(output.encoded()), "000070c7492aaa9c9ac7a05bc0d9c5db2dae9372029654f71f0c7f95deed5099b7021450ffc385cd4e7c6ac9a7e91614ca67ff90568a00000000028182ba00000000000003e80004cb2f180ba678744be3bf9cd44fbcdabfb5be209f21739934836e26055610ab02720fa99489219d9f3581664473a1b40b30ad1f6e13150d59f8234a42c3f0de3d505405");
}

Expand Down
12 changes: 7 additions & 5 deletions tests/chains/Nimiq/TransactionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ TEST(NimiqTransaction, PreImage) {
Address("NQ86 2H8F YGU5 RM77 QSN9 LYLH C56A CYYR 0MLA"),
42042042,
1000,
314159
314159,
Proto::NetworkId::UseDefault
);
ASSERT_EQ(hex(tx.getPreImage()),
"000082d5f776378ccbe34a3d941f22d4715bc9f81e0d001450ffc385cd4e7c6ac9a7e91614ca67ff90568a0000000000028182ba00000000000003e80004cb2f180000");
"000082d5f776378ccbe34a3d941f22d4715bc9f81e0d001450ffc385cd4e7c6ac9a7e91614ca67ff90568a0000000000028182ba00000000000003e80004cb2f2a00");
}

TEST(NimiqTransaction, Serialize) {
Expand All @@ -39,14 +40,15 @@ TEST(NimiqTransaction, Serialize) {
Address("NQ86 2H8F YGU5 RM77 QSN9 LYLH C56A CYYR 0MLA"),
42042042,
1000,
314159
314159,
Proto::NetworkId::Mainnet
);

const auto signature = parse_hex("0ba678744be3bf9cd44fbcdabfb5be209f21739934836e26055610ab02720fa99489219d9f3581664473a1b40b30ad1f6e13150d59f8234a42c3f0de3d505405");
const auto signature = parse_hex("74dc7f6e0ab58a0bf52cc6e8801b0cca132dd4229d9a3e3a3d2f90e4d8f045d981b771bf5fc3851a98f3c617b1a943228f963e910e061808a721cfa0e3cad50b");
std::copy(signature.begin(), signature.end(), tx.signature.begin());

ASSERT_EQ(hex(tx.serialize()),
"000070c7492aaa9c9ac7a05bc0d9c5db2dae9372029654f71f0c7f95deed5099b7021450ffc385cd4e7c6ac9a7e91614ca67ff90568a00000000028182ba00000000000003e80004cb2f180ba678744be3bf9cd44fbcdabfb5be209f21739934836e26055610ab02720fa99489219d9f3581664473a1b40b30ad1f6e13150d59f8234a42c3f0de3d505405");
"0070c7492aaa9c9ac7a05bc0d9c5db2dae9372029654f71f0c7f95deed5099b7021450ffc385cd4e7c6ac9a7e91614ca67ff90568a00000000028182ba00000000000003e80004cb2f2a74dc7f6e0ab58a0bf52cc6e8801b0cca132dd4229d9a3e3a3d2f90e4d8f045d981b771bf5fc3851a98f3c617b1a943228f963e910e061808a721cfa0e3cad50b");
}

} // namespace TW::Nimiq

0 comments on commit ebcfdfa

Please sign in to comment.