// unpack to strings to maintain protocol compatibility with older versions void serialize(RawBlock& rawBlock, ISerializer& serializer) { if (serializer.type() == ISerializer::INPUT) { uint64_t blockSize; serializer(blockSize, "block_size"); rawBlock.block.resize(static_cast<size_t>(blockSize)); } else { auto blockSize = rawBlock.block.size(); serializer(blockSize, "block_size"); } serializer.binary(rawBlock.block.data(), rawBlock.block.size(), "block"); if (serializer.type() == ISerializer::INPUT) { uint64_t txCount; serializer(txCount, "tx_count"); rawBlock.transactions.resize(static_cast<size_t>(txCount)); for (auto& txBlob : rawBlock.transactions) { uint64_t txSize; serializer(txSize, "tx_size"); txBlob.resize(txSize); serializer.binary(txBlob.data(), txBlob.size(), "transaction"); } } else { auto txCount = rawBlock.transactions.size(); serializer(txCount, "tx_count"); for (auto& txBlob : rawBlock.transactions) { auto txSize = txBlob.size(); serializer(txSize, "tx_size"); serializer.binary(txBlob.data(), txBlob.size(), "transaction"); } } }
bool WalletUnconfirmedTransactions::serialize(ISerializer& s) { s(m_unconfirmedTxs, "transactions"); if (s.type() == ISerializer::INPUT) { collectUsedOutputs(); } return true; }
void BlockIndex::serialize(ISerializer& s) { if (s.type() == ISerializer::INPUT) { readSequence<Crypto::Hash>(std::back_inserter(m_container), "index", s); } else { writeSequence<Crypto::Hash>(m_container.begin(), m_container.end(), "index", s); } }
void serialize(Transaction& tx, ISerializer& serializer) { serialize(static_cast<TransactionPrefix&>(tx), serializer); size_t sigSize = tx.inputs.size(); //TODO: make arrays without sizes // serializer.beginArray(sigSize, "signatures"); // ignore base transaction if (serializer.type() == ISerializer::INPUT && !(sigSize == 1 && tx.inputs[0].type() == typeid(BaseInput))) { tx.signatures.resize(sigSize); } bool signaturesNotExpected = tx.signatures.empty(); if (!signaturesNotExpected && tx.inputs.size() != tx.signatures.size()) { throw std::runtime_error("Serialization error: unexpected signatures size"); } for (size_t i = 0; i < tx.inputs.size(); ++i) { size_t signatureSize = getSignaturesCount(tx.inputs[i]); 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"); } for (Crypto::Signature& sig : tx.signatures[i]) { serializePod(sig, "", serializer); } } else { std::vector<Crypto::Signature> signatures(signatureSize); for (Crypto::Signature& sig : signatures) { serializePod(sig, "", serializer); } tx.signatures[i] = std::move(signatures); } } // serializer.endArray(); }
bool serialize(boost::multi_index_container<T, Indexes>& value, Common::StringView name, ISerializer& s) { if (s.type() == ISerializer::INPUT) { readSequence<T>(std::inserter(value, value.end()), name, s); } else { writeSequence<T>(value.begin(), value.end(), name, s); } return true; }
void serialize(TransactionPrefix& txP, ISerializer& serializer) { serializer(txP.version, "version"); if (CURRENT_TRANSACTION_VERSION < txP.version && serializer.type() == ISerializer::INPUT) { throw std::runtime_error("Wrong transaction version"); } serializer(txP.unlockTime, "unlock_time"); serializer(txP.inputs, "vin"); serializer(txP.outputs, "vout"); serializeAsBinary(txP.extra, "extra", serializer); }
void serialize(TransactionExtraMergeMiningTag& tag, ISerializer& serializer) { if (serializer.type() == ISerializer::OUTPUT) { std::string field; StringOutputStream os(field); BinaryOutputStreamSerializer output(os); doSerialize(tag, output); serializer(field, ""); } else { std::string field; serializer(field, ""); MemoryInputStream stream(field.data(), field.size()); BinaryInputStreamSerializer input(stream); doSerialize(tag, input); } }
void serialize(TransactionOutputTarget& output, ISerializer& serializer) { 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); } }
void serializeBlockHeight(ISerializer& s, uint32_t& blockHeight, Common::StringView name) { if (s.type() == ISerializer::INPUT) { uint64_t height; s(height, name); if (height == std::numeric_limits<uint64_t>::max()) { blockHeight = std::numeric_limits<uint32_t>::max(); } else if (height > std::numeric_limits<uint32_t>::max() && height < std::numeric_limits<uint64_t>::max()) { throw std::runtime_error("Deserialization error: wrong value"); } else { blockHeight = static_cast<uint32_t>(height); } } else { s(blockHeight, name); } }
void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) { serializer(pbs.m_parentBlock.majorVersion, "majorVersion"); serializer(pbs.m_parentBlock.minorVersion, "minorVersion"); serializer(pbs.m_timestamp, "timestamp"); serializer(pbs.m_parentBlock.previousBlockHash, "prevId"); serializer.binary(&pbs.m_nonce, sizeof(pbs.m_nonce), "nonce"); if (pbs.m_hashingSerialization) { Crypto::Hash minerTxHash; if (!getBaseTransactionHash(pbs.m_parentBlock.baseTransaction, minerTxHash)) { throw std::runtime_error("Get transaction hash error"); } Crypto::Hash merkleRoot; Crypto::tree_hash_from_branch(pbs.m_parentBlock.baseTransactionBranch.data(), pbs.m_parentBlock.baseTransactionBranch.size(), minerTxHash, 0, merkleRoot); serializer(merkleRoot, "merkleRoot"); } uint64_t txNum = static_cast<uint64_t>(pbs.m_parentBlock.transactionCount); serializer(txNum, "numberOfTransactions"); pbs.m_parentBlock.transactionCount = static_cast<uint16_t>(txNum); if (pbs.m_parentBlock.transactionCount < 1) { throw std::runtime_error("Wrong transactions number"); } if (pbs.m_headerOnly) { return; } size_t branchSize = Crypto::tree_depth(pbs.m_parentBlock.transactionCount); if (serializer.type() == ISerializer::OUTPUT) { if (pbs.m_parentBlock.baseTransactionBranch.size() != branchSize) { throw std::runtime_error("Wrong miner transaction branch size"); } } else { pbs.m_parentBlock.baseTransactionBranch.resize(branchSize); } // serializer(m_parentBlock.baseTransactionBranch, "baseTransactionBranch"); //TODO: Make arrays with computable size! This code won't work with json serialization! for (Crypto::Hash& hash: pbs.m_parentBlock.baseTransactionBranch) { serializer(hash, ""); } serializer(pbs.m_parentBlock.baseTransaction, "minerTx"); TransactionExtraMergeMiningTag mmTag; if (!getMergeMiningTagFromExtra(pbs.m_parentBlock.baseTransaction.extra, mmTag)) { throw std::runtime_error("Can't get extra merge mining tag"); } if (mmTag.depth > 8 * sizeof(Crypto::Hash)) { 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! for (Crypto::Hash& hash: pbs.m_parentBlock.blockchainBranch) { serializer(hash, ""); } }