Skip to content
This repository was archived by the owner on Jun 12, 2018. It is now read-only.
Open
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
2 changes: 1 addition & 1 deletion multy_core/src/golos/golos_facade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ AccountPtr GolosFacade::make_account(const char* serialized_private_key)

TransactionPtr GolosFacade::make_transaction(const Account& account)
{
return TransactionPtr(new GolosTransaction(account.get_blockchain_type()));
return TransactionPtr(new GolosTransaction(account));
}

void GolosFacade::validate_address(
Expand Down
121 changes: 114 additions & 7 deletions multy_core/src/golos/golos_transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,28 @@

#include "multy_core/src/api/properties_impl.h"
#include "multy_core/src/blockchain_facade_base.h"
#include "multy_core/src/api/key_impl.h"
#include "multy_core/src/codec.h"
#include "multy_core/src/exception.h"
#include "multy_core/src/exception_stream.h"
#include "multy_core/src/utility.h"

#include "third-party/portable_endian.h"

#include <chrono>
#include <cstddef>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <iostream>

namespace multy_core
{
namespace internal
{

const BinaryDataPtr GOLOS_CHAIN_ID = decode("782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de12", CODEC_HEX);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't do that, you should make an array with bytes corresponding to this.

const char* ISO8601_TIME_FORMAT="%FT%T%z";

std::string format_iso8601_string(const std::time_t& time)
Expand Down Expand Up @@ -75,14 +80,15 @@ class GolosBinaryStream
: m_data()
{}

void write_data(const unsigned char* data, size_t len)
void write_data(const uint8_t* data, size_t len)
{
if (!data)
{
THROW_EXCEPTION("Attempt to write null data.");
}

m_data.insert(m_data.end(), data, data + len);

}

BinaryData get_content() const
Expand All @@ -91,7 +97,7 @@ class GolosBinaryStream
}

private:
std::vector<unsigned char> m_data;
std::vector<uint8_t> m_data;
};

class GolosJsonStream
Expand Down Expand Up @@ -174,6 +180,69 @@ GolosBinaryStream& operator<<(GolosBinaryStream& stream, const GolosTransactionO
return stream;
}

GolosBinaryStream& operator<<(GolosBinaryStream& stream, const BinaryData& data)
{
stream.write_data(
reinterpret_cast<const uint8_t*>(data.data), data.len);

return stream;
}

template <typename T>
GolosBinaryStream& write_as_binary(const T& data, GolosBinaryStream& stream)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stream should be passed by pointer here and other non-operator<< functions.

{
stream.write_data(
reinterpret_cast<const uint8_t*>(&data), sizeof(data));

return stream;
}

GolosBinaryStream& operator<<(GolosBinaryStream& stream, const uint8_t data)
{
write_as_binary(data, stream);

return stream;
}

GolosBinaryStream& operator<<(GolosBinaryStream& stream, const uint16_t data)
{
write_as_binary(htole16(data), stream);

return stream;
}

GolosBinaryStream& operator<<(GolosBinaryStream& stream, const uint32_t data)
{
write_as_binary(htole32(data), stream);

return stream;
}

GolosBinaryStream& operator<<(GolosBinaryStream& stream, const uint64_t data)
{
write_as_binary(htole64(data), stream);

return stream;
}

GolosBinaryStream& operator<<(GolosBinaryStream& stream, const std::time_t& time)
{
stream.write_data(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that intentional to omit explicit endianess of the time ?

reinterpret_cast<const uint8_t*>(time), sizeof(time));

return stream;
}

GolosBinaryStream& operator<<(GolosBinaryStream& stream, const std::string& str)
{
stream.write_data(
reinterpret_cast<const uint8_t*>(str.c_str()), str.length());

return stream;
}



class GolosTransactionTransferOperation : public GolosTransactionOperation
{
public:
Expand All @@ -195,8 +264,30 @@ class GolosTransactionTransferOperation : public GolosTransactionOperation
return TRANSFER;
}

void write_to_stream(GolosBinaryStream* /*stream*/) const override
void write_to_stream(GolosBinaryStream* stream) const override
{
*stream << (uint8_t)0x02; // transfer_operation id
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make a named const out of this 0x02

*stream << static_cast<uint8_t>(from.size());
*stream << from;
*stream << static_cast<uint8_t>(to.size());
*stream << to;

*stream << amount.get_value_as_uint64();
*stream << static_cast<uint8_t>(GOLOS_VALUE_DECIMAL_PLACES);

std::string temp (7, '\0');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks silly, could you please explain what 7 stands for? also, this could be done much easier:

std::string normalized_token_name(token_name);
normalized_token_name.resize(7);

temp.insert(0, token_name);
temp.resize(7);
*stream << temp;
*stream << static_cast<uint8_t>(memo.size());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we have a certain pattern of writing a string to a BinaryStream here, and it makes sense to move that to appropriate operator<<

if (memo.size() == 0)
{
*stream << (uint8_t)0;
} else
{
*stream << memo;
}

}

void write_to_stream(GolosJsonStream* stream) const override
Expand Down Expand Up @@ -303,8 +394,9 @@ class GolosTransactionDestination
PropertyT<BigInt> amount;
};

GolosTransaction::GolosTransaction(BlockchainType blockchain_type)
: TransactionBase(blockchain_type),
GolosTransaction::GolosTransaction(const Account& account)
: TransactionBase(account.get_blockchain_type()),
m_account(account),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Account instance should not be locked for lifetime of transaction, please store the private key instead or add a transaction-level PropertyT for private key.

m_message(),
m_source(),
m_destination(),
Expand Down Expand Up @@ -408,9 +500,23 @@ void GolosTransaction::update()
m_signature = make_clone(as_binary_data("FAKE GOLOS TX SIGNATURE"));
}

void GolosTransaction::sign()
{
GolosBinaryStream transaction_stream;
transaction_stream << *GOLOS_CHAIN_ID;
transaction_stream << static_cast<uint16_t>(static_cast<uint32_t>(*m_ref_block_num));
transaction_stream << reinterpret_cast<const uint32_t*>(m_ref_block_hash.get_value()->data)[1];
transaction_stream << static_cast<uint32_t>(m_expiration);
transaction_stream << (uint8_t)0x01; // count operaions
transaction_stream << *m_operation;

m_signature = m_account.get_private_key()->sign(transaction_stream.get_content());
}

BinaryDataPtr GolosTransaction::serialize()
{
update();
sign();

const uint16_t ref_block_num = static_cast<uint16_t>(
static_cast<uint32_t>(*m_ref_block_num));
Expand All @@ -427,8 +533,8 @@ BinaryDataPtr GolosTransaction::serialize()
char buffer[1024] = {'\0'};
snprintf(buffer, sizeof(buffer), R"json(
{
"ref_block_num": %ud,
"ref_block_prefix": %ud,
"ref_block_num": %u,
"ref_block_prefix": %u,
"expiration": "%s",
"operations": [%s],
"extensions": [],
Expand All @@ -442,6 +548,7 @@ BinaryDataPtr GolosTransaction::serialize()
encode(*m_signature, CODEC_HEX).c_str()
);

std::cerr << buffer;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this.

return make_clone(as_binary_data(buffer));
}

Expand Down
4 changes: 3 additions & 1 deletion multy_core/src/golos/golos_transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ typedef std::unique_ptr<GolosTransactionOperation> GolosTransactionOperationPtr;
class GolosTransaction : public TransactionBase
{
public:
GolosTransaction(BlockchainType blockchain_type);
GolosTransaction(const Account& account);
~GolosTransaction();

void update() override;
Expand All @@ -52,8 +52,10 @@ class GolosTransaction : public TransactionBase
private:
void verify();
void set_expiration(const std::string&);
void sign();

private:
const Account& m_account;
BinaryDataPtr m_message;
GolosTransactionSourcePtr m_source;
GolosTransactionDestinationPtr m_destination;
Expand Down
4 changes: 2 additions & 2 deletions multy_test/test_golos_account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ GTEST_TEST(GolosTest, private_key_sign)
make_account(BLOCKCHAIN_GOLOS, "5Hq2ZdSGZokcgLoNxNGL5kHKi4e3kUUCqorgFK6T6ka7KtSvYLj", reset_sp(account));
PrivateKeyPtr prv_key = account->get_private_key();
// binary serialize TX to sign golos private key
BinaryDataPtr signature = prv_key->sign(as_binary_data(from_hex("782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de1269466c1944189"
"fb3bb5a0102096d756c7479746573740b70617368616b6c7962696b010000000000000003474f4c4f5300000000")));
BinaryDataPtr signature = prv_key->sign(as_binary_data(from_hex("782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de1269466c194418"
"9fb3bb5a0102096d756c7479746573740b70617368616b6c7962696b010000000000000003474f4c4f5300000000")));
// signature generated form golos-core
ASSERT_EQ(as_binary_data(from_hex(
"1f2e6bb028760bacddd31dc9772e63240fd297ee2f9fcd29f3605aeb79f774fa4b7d1b4e6dc4a1cd6fd2d4e08b2ea2758680d6a5b1e49664522f391ff949b70018")),
Expand Down