2015-05-27 12:08:46 +00:00
|
|
|
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
2015-04-06 16:13:07 +00:00
|
|
|
//
|
|
|
|
// This file is part of Bytecoin.
|
|
|
|
//
|
|
|
|
// Bytecoin is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// Bytecoin is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
#include "CryptoNoteSerialization.h"
|
2015-04-06 16:13:07 +00:00
|
|
|
|
|
|
|
#include <algorithm>
|
2015-07-30 15:22:07 +00:00
|
|
|
#include <sstream>
|
|
|
|
#include <stdexcept>
|
2015-04-06 16:13:07 +00:00
|
|
|
|
|
|
|
#include <boost/variant/static_visitor.hpp>
|
|
|
|
#include <boost/variant/apply_visitor.hpp>
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
#include "Serialization/ISerializer.h"
|
|
|
|
#include "Serialization/SerializationOverloads.h"
|
|
|
|
#include "Serialization/BinaryInputStreamSerializer.h"
|
|
|
|
#include "Serialization/BinaryOutputStreamSerializer.h"
|
|
|
|
|
|
|
|
#include "Common/StringOutputStream.h"
|
|
|
|
#include "crypto/crypto.h"
|
|
|
|
|
|
|
|
#include "Account.h"
|
|
|
|
#include "CryptoNoteConfig.h"
|
|
|
|
#include "CryptoNoteFormatUtils.h"
|
|
|
|
#include "CryptoNoteTools.h"
|
|
|
|
#include "TransactionExtra.h"
|
|
|
|
|
|
|
|
using namespace Common;
|
|
|
|
|
2015-04-06 16:13:07 +00:00
|
|
|
namespace {
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
using namespace CryptoNote;
|
|
|
|
using namespace Common;
|
|
|
|
|
|
|
|
size_t getSignaturesCount(const TransactionInput& input) {
|
|
|
|
struct txin_signature_size_visitor : public boost::static_visitor < size_t > {
|
|
|
|
size_t operator()(const BaseInput& txin) const { return 0; }
|
|
|
|
size_t operator()(const KeyInput& txin) const { return txin.outputIndexes.size(); }
|
|
|
|
size_t operator()(const MultisignatureInput& txin) const { return txin.signatureCount; }
|
|
|
|
};
|
|
|
|
|
|
|
|
return boost::apply_visitor(txin_signature_size_visitor(), input);
|
|
|
|
}
|
|
|
|
|
2015-04-06 16:13:07 +00:00
|
|
|
struct BinaryVariantTagGetter: boost::static_visitor<uint8_t> {
|
2015-07-30 15:22:07 +00:00
|
|
|
uint8_t operator()(const CryptoNote::BaseInput) { return 0xff; }
|
|
|
|
uint8_t operator()(const CryptoNote::KeyInput) { return 0x2; }
|
|
|
|
uint8_t operator()(const CryptoNote::MultisignatureInput) { return 0x3; }
|
|
|
|
uint8_t operator()(const CryptoNote::KeyOutput) { return 0x2; }
|
|
|
|
uint8_t operator()(const CryptoNote::MultisignatureOutput) { return 0x3; }
|
2015-05-27 12:08:46 +00:00
|
|
|
uint8_t operator()(const CryptoNote::Transaction) { return 0xcc; }
|
|
|
|
uint8_t operator()(const CryptoNote::Block) { return 0xbb; }
|
2015-04-06 16:13:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct VariantSerializer : boost::static_visitor<> {
|
2015-05-27 12:08:46 +00:00
|
|
|
VariantSerializer(CryptoNote::ISerializer& serializer, const std::string& name) : s(serializer), name(name) {}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
template <typename T>
|
|
|
|
void operator() (T& param) { s(param, name); }
|
2015-05-27 12:08:46 +00:00
|
|
|
|
|
|
|
CryptoNote::ISerializer& s;
|
2015-07-30 15:22:07 +00:00
|
|
|
std::string name;
|
2015-04-06 16:13:07 +00:00
|
|
|
};
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNote::TransactionInput& in) {
|
2015-04-06 16:13:07 +00:00
|
|
|
switch(tag) {
|
|
|
|
case 0xff: {
|
2015-07-30 15:22:07 +00:00
|
|
|
CryptoNote::BaseInput v;
|
|
|
|
serializer(v, "value");
|
2015-04-06 16:13:07 +00:00
|
|
|
in = v;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x2: {
|
2015-07-30 15:22:07 +00:00
|
|
|
CryptoNote::KeyInput v;
|
|
|
|
serializer(v, "value");
|
2015-04-06 16:13:07 +00:00
|
|
|
in = v;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x3: {
|
2015-07-30 15:22:07 +00:00
|
|
|
CryptoNote::MultisignatureInput v;
|
|
|
|
serializer(v, "value");
|
2015-04-06 16:13:07 +00:00
|
|
|
in = v;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
throw std::runtime_error("Unknown variant tag");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNote::TransactionOutputTarget& out) {
|
2015-04-06 16:13:07 +00:00
|
|
|
switch(tag) {
|
|
|
|
case 0x2: {
|
2015-07-30 15:22:07 +00:00
|
|
|
CryptoNote::KeyOutput v;
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(v, "data");
|
|
|
|
out = v;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x3: {
|
2015-07-30 15:22:07 +00:00
|
|
|
CryptoNote::MultisignatureOutput v;
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(v, "data");
|
|
|
|
out = v;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
throw std::runtime_error("Unknown variant tag");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2015-07-15 12:23:00 +00:00
|
|
|
bool serializePod(T& v, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
|
|
|
return serializer.binary(&v, sizeof(v), name);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool serializeVarintVector(std::vector<uint32_t>& vector, CryptoNote::ISerializer& serializer, Common::StringView name) {
|
|
|
|
size_t size = vector.size();
|
2015-07-15 12:23:00 +00:00
|
|
|
|
|
|
|
if (!serializer.beginArray(size, name)) {
|
|
|
|
vector.clear();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-04-06 16:13:07 +00:00
|
|
|
vector.resize(size);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < size; ++i) {
|
|
|
|
serializer(vector[i], "");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer.endArray();
|
2015-07-15 12:23:00 +00:00
|
|
|
return true;
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
namespace Crypto {
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool serialize(PublicKey& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
2015-07-15 12:23:00 +00:00
|
|
|
return serializePod(pubKey, name, serializer);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool serialize(SecretKey& secKey, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
2015-07-15 12:23:00 +00:00
|
|
|
return serializePod(secKey, name, serializer);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool serialize(Hash& h, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
2015-07-15 12:23:00 +00:00
|
|
|
return serializePod(h, name, serializer);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool serialize(KeyImage& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
2015-07-15 12:23:00 +00:00
|
|
|
return serializePod(keyImage, name, serializer);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
bool serialize(chacha8_iv& chacha, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
|
|
|
return serializePod(chacha, name, serializer);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool serialize(Signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
2015-07-15 12:23:00 +00:00
|
|
|
return serializePod(sig, name, serializer);
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
bool serialize(EllipticCurveScalar& ecScalar, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
|
|
|
return serializePod(ecScalar, name, serializer);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool serialize(EllipticCurvePoint& ecPoint, Common::StringView name, CryptoNote::ISerializer& serializer) {
|
|
|
|
return serializePod(ecPoint, name, serializer);
|
|
|
|
}
|
2015-07-15 12:23:00 +00:00
|
|
|
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
namespace CryptoNote {
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(TransactionPrefix& txP, ISerializer& serializer) {
|
2015-05-27 12:08:46 +00:00
|
|
|
serializer(txP.version, "version");
|
2015-07-30 15:22:07 +00:00
|
|
|
|
|
|
|
if (CURRENT_TRANSACTION_VERSION < txP.version) {
|
|
|
|
throw std::runtime_error("Wrong transaction version");
|
|
|
|
}
|
|
|
|
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(txP.unlockTime, "unlock_time");
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(txP.inputs, "vin");
|
|
|
|
serializer(txP.outputs, "vout");
|
2015-04-06 16:13:07 +00:00
|
|
|
serializeAsBinary(txP.extra, "extra", serializer);
|
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(Transaction& tx, ISerializer& serializer) {
|
2015-07-30 15:22:07 +00:00
|
|
|
serialize(static_cast<TransactionPrefix&>(tx), serializer);
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
size_t sigSize = tx.inputs.size();
|
2015-04-06 16:13:07 +00:00
|
|
|
//TODO: make arrays without sizes
|
|
|
|
// serializer.beginArray(sigSize, "signatures");
|
2015-07-30 15:22:07 +00:00
|
|
|
|
|
|
|
if (serializer.type() == ISerializer::INPUT) {
|
|
|
|
tx.signatures.resize(sigSize);
|
|
|
|
}
|
2015-04-06 16:13:07 +00:00
|
|
|
|
|
|
|
bool signaturesNotExpected = tx.signatures.empty();
|
2015-07-30 15:22:07 +00:00
|
|
|
if (!signaturesNotExpected && tx.inputs.size() != tx.signatures.size()) {
|
2015-04-06 16:13:07 +00:00
|
|
|
throw std::runtime_error("Serialization error: unexpected signatures size");
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
for (size_t i = 0; i < tx.inputs.size(); ++i) {
|
|
|
|
size_t signatureSize = getSignaturesCount(tx.inputs[i]);
|
2015-04-06 16:13:07 +00:00
|
|
|
if (signaturesNotExpected) {
|
|
|
|
if (signatureSize == 0) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
throw std::runtime_error("Serialization error: signatures are not expected");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (serializer.type() == ISerializer::OUTPUT) {
|
|
|
|
if (signatureSize != tx.signatures[i].size()) {
|
|
|
|
throw std::runtime_error("Serialization error: unexpected signatures size");
|
|
|
|
}
|
2015-07-30 15:22:07 +00:00
|
|
|
|
|
|
|
for (Crypto::Signature& sig : tx.signatures[i]) {
|
|
|
|
serializePod(sig, "", serializer);
|
|
|
|
}
|
|
|
|
|
2015-04-06 16:13:07 +00:00
|
|
|
} else {
|
2015-07-30 15:22:07 +00:00
|
|
|
std::vector<Crypto::Signature> signatures(signatureSize);
|
|
|
|
for (Crypto::Signature& sig : signatures) {
|
|
|
|
serializePod(sig, "", serializer);
|
|
|
|
}
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
tx.signatures[i] = std::move(signatures);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// serializer.endArray();
|
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(TransactionInput& in, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
if (serializer.type() == ISerializer::OUTPUT) {
|
|
|
|
BinaryVariantTagGetter tagGetter;
|
|
|
|
uint8_t tag = boost::apply_visitor(tagGetter, in);
|
|
|
|
serializer.binary(&tag, sizeof(tag), "type");
|
|
|
|
|
|
|
|
VariantSerializer visitor(serializer, "value");
|
|
|
|
boost::apply_visitor(visitor, in);
|
|
|
|
} else {
|
|
|
|
uint8_t tag;
|
|
|
|
serializer.binary(&tag, sizeof(tag), "type");
|
|
|
|
|
|
|
|
getVariantValue(serializer, tag, in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void serialize(BaseInput& gen, ISerializer& serializer) {
|
|
|
|
serializer(gen.blockIndex, "height");
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void serialize(KeyInput& key, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(key.amount, "amount");
|
2015-07-30 15:22:07 +00:00
|
|
|
serializeVarintVector(key.outputIndexes, serializer, "key_offsets");
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(key.keyImage, "k_image");
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void serialize(MultisignatureInput& multisignature, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(multisignature.amount, "amount");
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(multisignature.signatureCount, "signatures");
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(multisignature.outputIndex, "outputIndex");
|
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(TransactionOutput& output, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(output.amount, "amount");
|
|
|
|
serializer(output.target, "target");
|
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(TransactionOutputTarget& output, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
if (serializer.type() == ISerializer::OUTPUT) {
|
|
|
|
BinaryVariantTagGetter tagGetter;
|
|
|
|
uint8_t tag = boost::apply_visitor(tagGetter, output);
|
|
|
|
serializer.binary(&tag, sizeof(tag), "type");
|
|
|
|
|
|
|
|
VariantSerializer visitor(serializer, "data");
|
|
|
|
boost::apply_visitor(visitor, output);
|
|
|
|
} else {
|
|
|
|
uint8_t tag;
|
|
|
|
serializer.binary(&tag, sizeof(tag), "type");
|
|
|
|
|
|
|
|
getVariantValue(serializer, tag, output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void serialize(KeyOutput& key, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(key.key, "key");
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void serialize(MultisignatureOutput& multisignature, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(multisignature.keys, "keys");
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(multisignature.requiredSignatureCount, "required_signatures");
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(pbs.m_parentBlock.majorVersion, "majorVersion");
|
|
|
|
|
|
|
|
if (BLOCK_MAJOR_VERSION_1 < pbs.m_parentBlock.majorVersion) {
|
|
|
|
throw std::runtime_error("Wrong parent block major version");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer(pbs.m_parentBlock.minorVersion, "minorVersion");
|
|
|
|
serializer(pbs.m_timestamp, "timestamp");
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(pbs.m_parentBlock.previousBlockHash, "prevId");
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer.binary(&pbs.m_nonce, sizeof(pbs.m_nonce), "nonce");
|
|
|
|
|
|
|
|
if (pbs.m_hashingSerialization) {
|
2015-07-30 15:22:07 +00:00
|
|
|
Crypto::Hash minerTxHash;
|
|
|
|
if (!getObjectHash(pbs.m_parentBlock.baseTransaction, minerTxHash)) {
|
2015-04-06 16:13:07 +00:00
|
|
|
throw std::runtime_error("Get transaction hash error");
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
Crypto::Hash merkleRoot;
|
|
|
|
Crypto::tree_hash_from_branch(pbs.m_parentBlock.baseTransactionBranch.data(), pbs.m_parentBlock.baseTransactionBranch.size(), minerTxHash, 0, merkleRoot);
|
2015-04-06 16:13:07 +00:00
|
|
|
|
|
|
|
serializer(merkleRoot, "merkleRoot");
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
uint64_t txNum = static_cast<uint64_t>(pbs.m_parentBlock.transactionCount);
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(txNum, "numberOfTransactions");
|
2015-07-30 15:22:07 +00:00
|
|
|
pbs.m_parentBlock.transactionCount = static_cast<uint16_t>(txNum);
|
|
|
|
if (pbs.m_parentBlock.transactionCount < 1) {
|
2015-04-06 16:13:07 +00:00
|
|
|
throw std::runtime_error("Wrong transactions number");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pbs.m_headerOnly) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
size_t branchSize = Crypto::tree_depth(pbs.m_parentBlock.transactionCount);
|
2015-04-06 16:13:07 +00:00
|
|
|
if (serializer.type() == ISerializer::OUTPUT) {
|
2015-07-30 15:22:07 +00:00
|
|
|
if (pbs.m_parentBlock.baseTransactionBranch.size() != branchSize) {
|
2015-04-06 16:13:07 +00:00
|
|
|
throw std::runtime_error("Wrong miner transaction branch size");
|
|
|
|
}
|
|
|
|
} else {
|
2015-07-30 15:22:07 +00:00
|
|
|
pbs.m_parentBlock.baseTransactionBranch.resize(branchSize);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
// serializer(m_parentBlock.baseTransactionBranch, "baseTransactionBranch");
|
2015-04-06 16:13:07 +00:00
|
|
|
//TODO: Make arrays with computable size! This code won't work with json serialization!
|
2015-07-30 15:22:07 +00:00
|
|
|
for (Crypto::Hash& hash: pbs.m_parentBlock.baseTransactionBranch) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(hash, "");
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(pbs.m_parentBlock.baseTransaction, "minerTx");
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
TransactionExtraMergeMiningTag mmTag;
|
|
|
|
if (!getMergeMiningTagFromExtra(pbs.m_parentBlock.baseTransaction.extra, mmTag)) {
|
2015-04-06 16:13:07 +00:00
|
|
|
throw std::runtime_error("Can't get extra merge mining tag");
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
if (mmTag.depth > 8 * sizeof(Crypto::Hash)) {
|
2015-04-06 16:13:07 +00:00
|
|
|
throw std::runtime_error("Wrong merge mining tag depth");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (serializer.type() == ISerializer::OUTPUT) {
|
|
|
|
if (mmTag.depth != pbs.m_parentBlock.blockchainBranch.size()) {
|
|
|
|
throw std::runtime_error("Blockchain branch size must be equal to merge mining tag depth");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pbs.m_parentBlock.blockchainBranch.resize(mmTag.depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
// serializer(m_parentBlock.blockchainBranch, "blockchainBranch");
|
|
|
|
//TODO: Make arrays with computable size! This code won't work with json serialization!
|
2015-07-30 15:22:07 +00:00
|
|
|
for (Crypto::Hash& hash: pbs.m_parentBlock.blockchainBranch) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(hash, "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void serializeBlockHeader(BlockHeader& header, ISerializer& serializer) {
|
|
|
|
serializer(header.majorVersion, "major_version");
|
|
|
|
if (header.majorVersion > BLOCK_MAJOR_VERSION_2) {
|
|
|
|
throw std::runtime_error("Wrong major version");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializer(header.minorVersion, "minor_version");
|
|
|
|
if (header.majorVersion == BLOCK_MAJOR_VERSION_1) {
|
|
|
|
serializer(header.timestamp, "timestamp");
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(header.previousBlockHash, "prev_id");
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer.binary(&header.nonce, sizeof(header.nonce), "nonce");
|
|
|
|
} else if (header.majorVersion == BLOCK_MAJOR_VERSION_2) {
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(header.previousBlockHash, "prev_id");
|
2015-04-06 16:13:07 +00:00
|
|
|
} else {
|
|
|
|
throw std::runtime_error("Wrong major version");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(BlockHeader& header, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializeBlockHeader(header, serializer);
|
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(Block& block, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
serializeBlockHeader(block, serializer);
|
|
|
|
|
|
|
|
if (block.majorVersion == BLOCK_MAJOR_VERSION_2) {
|
|
|
|
auto parentBlockSerializer = makeParentBlockSerializer(block, false, false);
|
|
|
|
serializer(parentBlockSerializer, "parent_block");
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(block.baseTransaction, "miner_tx");
|
|
|
|
serializer(block.transactionHashes, "tx_hashes");
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 12:23:00 +00:00
|
|
|
void serialize(AccountPublicAddress& address, ISerializer& serializer) {
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(address.spendPublicKey, "m_spend_public_key");
|
|
|
|
serializer(address.viewPublicKey, "m_view_public_key");
|
2015-07-15 12:23:00 +00:00
|
|
|
}
|
2015-04-06 16:13:07 +00:00
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void serialize(AccountKeys& keys, ISerializer& s) {
|
|
|
|
s(keys.address, "m_account_address");
|
|
|
|
s(keys.spendSecretKey, "m_spend_secret_key");
|
|
|
|
s(keys.viewSecretKey, "m_view_secret_key");
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void doSerialize(TransactionExtraMergeMiningTag& tag, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
uint64_t depth = static_cast<uint64_t>(tag.depth);
|
|
|
|
serializer(depth, "depth");
|
|
|
|
tag.depth = static_cast<size_t>(depth);
|
2015-07-30 15:22:07 +00:00
|
|
|
serializer(tag.merkleRoot, "merkle_root");
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void serialize(TransactionExtraMergeMiningTag& tag, ISerializer& serializer) {
|
2015-04-06 16:13:07 +00:00
|
|
|
if (serializer.type() == ISerializer::OUTPUT) {
|
2015-07-30 15:22:07 +00:00
|
|
|
std::string field;
|
|
|
|
StringOutputStream os(field);
|
|
|
|
BinaryOutputStreamSerializer output(os);
|
2015-07-15 12:23:00 +00:00
|
|
|
doSerialize(tag, output);
|
2015-04-06 16:13:07 +00:00
|
|
|
serializer(field, "");
|
|
|
|
} else {
|
|
|
|
std::string field;
|
|
|
|
serializer(field, "");
|
2015-07-30 15:22:07 +00:00
|
|
|
MemoryInputStream stream(field.data(), field.size());
|
2015-04-06 16:13:07 +00:00
|
|
|
BinaryInputStreamSerializer input(stream);
|
2015-07-15 12:23:00 +00:00
|
|
|
doSerialize(tag, input);
|
2015-04-06 16:13:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-30 15:22:07 +00:00
|
|
|
void serialize(KeyPair& keyPair, ISerializer& serializer) {
|
|
|
|
serializer(keyPair.secretKey, "secret_key");
|
|
|
|
serializer(keyPair.publicKey, "public_key");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-27 12:08:46 +00:00
|
|
|
} //namespace CryptoNote
|