Created
November 29, 2019 23:18
-
-
Save sleepdefic1t/61219a3cec777178cd1e359aa0d0cc71 to your computer and use it in GitHub Desktop.
Radians C++ Scooter Registration Implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.2) | |
project(ark_cpp_crypto C CXX) | |
# ------------------------------------------------------------------------------ | |
# External Libraries | |
# ------------------------------------------------------------------------------ | |
include(${CMAKE_SOURCE_DIR}/cmake/External.cmake) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Internal Libraries | |
# ------------------------------------------------------------------------------ | |
set(INTERNAL_LIBRARY_SOURCE_DIRS | |
${PROJECT_SOURCE_DIR}/lib/bcl | |
${PROJECT_SOURCE_DIR}/lib/rfc6979 | |
) | |
include_directories(${INTERNAL_LIBRARY_SOURCE_DIRS}) | |
# ------------------------------------------------------------------------------ | |
# Nayuki's Bitcoin Cryptography Library | |
set(BCL_SOURCE | |
lib/bcl/Base58Check.cpp | |
lib/bcl/CurvePoint.cpp | |
lib/bcl/Ecdsa.cpp | |
lib/bcl/FieldInt.cpp | |
lib/bcl/Ripemd160.cpp | |
lib/bcl/Sha256Hash.cpp | |
lib/bcl/Sha256.cpp | |
lib/bcl/Sha512.cpp | |
lib/bcl/Uint256.cpp | |
lib/bcl/Utils.cpp | |
) | |
set(INTERNAL_LIBRARY_SOURCE ${BCL_SOURCE}) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# ARK C++ Crypto Source | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Common | |
set(COMMON_SOURCE | |
common/configuration.cpp | |
common/network.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Crypto | |
set(CRYPTO_SOURCE | |
crypto/curve.cpp | |
crypto/hash.cpp | |
crypto/message.cpp | |
crypto/slot.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Identities | |
set(IDENTITIES_SOURCE | |
identities/address.cpp | |
identities/keys.cpp | |
identities/privatekey.cpp | |
identities/publickey.cpp | |
identities/wif.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Transactions | |
# Types | |
set(TRANSACTIONS_TYPES_SOURCE | |
transactions/types/transfer.cpp | |
transactions/types/second_signature.cpp | |
transactions/types/delegate_registration.cpp | |
transactions/types/vote.cpp | |
# transactions/types/multi_signature.cpp | |
transactions/types/ipfs.cpp | |
transactions/types/multi_payment.cpp | |
transactions/types/htlc_lock.cpp | |
transactions/types/htlc_claim.cpp | |
transactions/types/htlc_refund.cpp | |
transactions/types/scooter_registration.cpp | |
) | |
# Serialization/Deserialization | |
set(TRANSACTIONS_SERDE_SOURCE | |
transactions/deserializer.cpp | |
transactions/serializer.cpp | |
) | |
# Transaction Source Files | |
set(TRANSACTIONS_SOURCE | |
${TRANSACTIONS_TYPES_SOURCE} | |
${TRANSACTIONS_SERDE_SOURCE} | |
transactions/transaction.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Utils | |
set(UTILS_SOURCE utils/base58.cpp) | |
# ------------------------------------------------------------------------------ | |
# ARK C++ Crypto Library Source | |
set(ARK_LIBRARY_SOURCE | |
${COMMON_SOURCE} | |
${CRYPTO_SOURCE} | |
${IDENTITIES_SOURCE} | |
${TRANSACTIONS_SOURCE} | |
${UTILS_SOURCE} | |
) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Add the Source Files to the Library | |
# ------------------------------------------------------------------------------ | |
add_library(${PROJECT_NAME} STATIC | |
${EXTERNAL_LIBRARY_SOURCE} | |
${INTERNAL_LIBRARY_SOURCE} | |
${ARK_LIBRARY_SOURCE} | |
) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Set the Include Folders | |
# ------------------------------------------------------------------------------ | |
set(ARK_CPP_CRYPTO_INCLUDE_DIRS | |
${PROJECT_SOURCE_DIR} | |
${PROJECT_SOURCE_DIR}/include/cpp-crypto | |
${PROJECT_SOURCE_DIR}/lib/ | |
) | |
include_directories(${ARK_CPP_CRYPTO_INCLUDE_DIRS}) | |
target_include_directories(${PROJECT_NAME} PUBLIC ${ARK_CPP_CRYPTO_INCLUDE_DIRS}) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Windows: Link to `crypt32` | |
# ------------------------------------------------------------------------------ | |
if (MSVC) | |
target_link_libraries(${PROJECT_NAME} PUBLIC crypt32) | |
endif() | |
# ------------------------------------------------------------------------------ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of Ark Cpp Crypto. | |
* | |
* (c) Ark Ecosystem <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
**/ | |
#ifndef ARK_TRANSACTIONS_BUILDERS_SCOOTER_REGISTRATION_HPP | |
#define ARK_TRANSACTIONS_BUILDERS_SCOOTER_REGISTRATION_HPP | |
#include <string> | |
#include "transactions/builders/common.hpp" | |
namespace Ark { | |
namespace Crypto { | |
namespace transactions { | |
namespace builder { | |
//////////////////////////////////////////////////////////////////////////////// | |
// Forward Declaration | |
class ScooterRegistration; | |
//////////////////////////////////////////////////////////////////////////////// | |
class ScooterRegistration : public Common<ScooterRegistration> { | |
public: | |
//////////////////////////////////////////////////////////////////////////// | |
// Amount | |
ScooterRegistration &scooterId(const std::string &scooterId) { | |
this->transaction.data.asset.scooterRegistration.scooterId = scooterId; | |
return *this; | |
} | |
}; | |
} // namespace builder | |
} // namespace transactions | |
} // namespace Crypto | |
} // namespace Ark | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of Ark Cpp Crypto. | |
* | |
* (c) Ark Ecosystem <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
**/ | |
#include "transactions/deserializer.hpp" | |
#include <cstdbool> | |
#include <cstdint> | |
#include <utility> | |
#include <vector> | |
#include "interfaces/constants.h" | |
#include "transactions/defaults/offsets.hpp" | |
#include "transactions/transaction_data.hpp" | |
#include "utils/unpack.h" | |
namespace Ark { | |
namespace Crypto { | |
namespace transactions { | |
//////////////////////////////////////////////////////////////////////////////// | |
// Deserialize Common | |
// | |
// @param TransactionData *data: The Transaction Data destination. | |
// @param const std::vector<uint8_t> &buffer | |
// | |
// --- | |
// Internals: | |
// | |
// Header - 1 Byte: | |
// - data->header = buffer.at(0); | |
// | |
// Transaction Version - 1 Byte: | |
// - data->version = buffer.at(1); | |
// | |
// Network Version - 1 Byte: | |
// - data->network = buffer.at(2); | |
// | |
// TypeGroup - 4 Bytes: | |
// - data->typeGroup = unpack4LE(&buffer, 3); | |
// | |
// Transaction Type - 2 Bytes: | |
// - data->type = unpack2LE(&buffer, 7); | |
// | |
// Nonce - 8 Bytes: | |
// - data->nonce = unpack8LE(&buffer, 9); | |
// | |
// SenderPublicKey - 33 Bytes: | |
// - std::move(&buffer.at(17), &buffer.at(50), data->senderPublicKey.begin()); | |
// | |
// Fee - 8 bytes | |
// - data->fee = unpack8LE(&buffer, 50); | |
// | |
// VendorField Length - 1 Byte: | |
// - buffer.at(58); | |
// | |
// VendorField - 0 - 255 Bytes: | |
// - data->vendorField.insert(data->vendorField.begin(), &buffer.at(59), &buffer.at(59 + data->vendorField.size())); | |
// | |
// --- | |
static void deserializeCommon(TransactionData *data, | |
const std::vector<uint8_t> &buffer) { | |
data->header = buffer.at(HEADER_OFFSET); // 1 Byte | |
data->version = buffer.at(VERSION_OFFSET); // 1 Byte | |
data->network = buffer.at(NETWORK_OFFSET); // 1 Byte | |
data->typeGroup = unpack4LE(buffer, TYPEGROUP_OFFSET); // 4 Bytes | |
data->type = unpack2LE(buffer, TYPE_OFFSET); // 2 Bytes | |
data->nonce = unpack8LE(buffer, NONCE_OFFSET); // 8 Bytes | |
std::move(&buffer.at(SENDER_PUBLICKEY_OFFSET), // 21 Bytes | |
&buffer.at(SENDER_PUBLICKEY_OFFSET + PUBLICKEY_COMPRESSED_LEN), | |
data->senderPublicKey.begin()); | |
data->fee = unpack8LE(buffer, FEE_OFFSET); // 8 Bytes | |
if (buffer.at(VF_LEN_OFFSET) != 0U) { | |
data->vendorField.insert( // 0 <=> 255 Bytes | |
data->vendorField.begin(), | |
&buffer.at(VF_OFFSET), | |
&buffer.at(VF_OFFSET + buffer.at(VF_LEN_OFFSET))); | |
}; | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Deserialize Common v1 | |
// | |
// @param TransactionData *data: The Transaction Data destination. | |
// @param const std::vector<uint8_t> &buffer | |
// | |
// --- | |
// Internals: | |
// | |
// Header - 1 Byte: | |
// - data->header = buffer.at(0); | |
// | |
// Transaction Version - 1 Byte: | |
// - data->version = buffer.at(1); | |
// | |
// Network Version - 1 Byte: | |
// - data->network = buffer.at(2); | |
// | |
// Transaction Type - 1 Byte: | |
// - data->type = buffer.at(3); | |
// | |
// Timestamp - 4 Bytes | |
// - data->timestamp = unpack4LE(buffer, 4); | |
// | |
// SenderPublicKey - 33 Bytes: | |
// - std::move(&buffer.at(8), &buffer.at(41) data->senderPublicKey.begin()); | |
// | |
// Fee - 8 bytes | |
// - data->fee = unpack8LE(buffer, 41); | |
// | |
// VendorField Length - 1 Byte: | |
// - buffer.at(49) | |
// | |
// VendorField - 0 - 255 Bytes: | |
// - data->vendorField.insert(data->vendorField.begin(), &buffer.at(50), &buffer.at(50 + buffer.at(49))); | |
// | |
// --- | |
static void deserializeCommonV1(TransactionData *data, | |
const std::vector<uint8_t> &buffer) { | |
data->header = buffer.at(HEADER_OFFSET); // 1 Byte | |
data->version = buffer.at(VERSION_OFFSET); // 1 Byte | |
data->network = buffer.at(NETWORK_OFFSET); // 1 Byte | |
data->type = buffer.at(v1::TYPE_OFFSET); // 1 Bytes | |
data->timestamp = unpack4LE(buffer, v1::TIMESTAMP_OFFSET); // 4 Bytes | |
std::move(&buffer.at(v1::SENDER_PUBLICKEY_OFFSET), // 33 Bytes | |
&buffer.at(v1::SENDER_PUBLICKEY_OFFSET + PUBLICKEY_COMPRESSED_LEN), | |
data->senderPublicKey.begin()); | |
data->fee = unpack8LE(buffer, v1::FEE_OFFSET); // 8 Bytes | |
if (buffer.at(v1::VF_LEN_OFFSET) != 0U) { | |
data->vendorField.insert( // 0 <=> 255 Bytes | |
data->vendorField.begin(), | |
&buffer.at(v1::VF_OFFSET), | |
&buffer.at(v1::VF_OFFSET + buffer.at(v1::VF_LEN_OFFSET))); | |
}; | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
static auto deserializeAsset(TransactionData *transaction, | |
const std::vector<uint8_t> &buffer, | |
const size_t offset) -> size_t { | |
switch (transaction->type) { | |
case TRANSFER_TYPE: | |
return Transfer::Deserialize( | |
&transaction->asset.transfer, | |
&buffer.at(offset)); | |
case SECOND_SIGNATURE_TYPE: | |
return SecondSignature::Deserialize( | |
&transaction->asset.secondSignature, | |
&buffer.at(offset)); | |
case DELEGATE_REGISTRATION_TYPE: | |
return DelegateRegistration::Deserialize( | |
&transaction->asset.delegateRegistration, | |
&buffer.at(offset)); | |
case VOTE_TYPE: | |
return Vote::Deserialize( | |
&transaction->asset.vote, | |
&buffer.at(offset)); | |
// case MULTI_SIGNATURE_TYPE: // TODO | |
case IPFS_TYPE: | |
return Ipfs::Deserialize( | |
&transaction->asset.ipfs, | |
&buffer.at(offset)); | |
case MULTI_PAYMENT_TYPE: | |
return MultiPayment::Deserialize( | |
&transaction->asset.multiPayment, | |
&buffer.at(offset)); | |
case DELEGATE_RESIGNATION_TYPE: return 0UL; | |
case HTLC_LOCK_TYPE: | |
return HtlcLock::Deserialize( | |
&transaction->asset.htlcLock, | |
&buffer.at(offset)); | |
case HTLC_CLAIM_TYPE: | |
return HtlcClaim::Deserialize( | |
&transaction->asset.htlcClaim, | |
&buffer.at(offset)); | |
case HTLC_REFUND_TYPE: | |
return HtlcRefund::Deserialize( | |
&transaction->asset.htlcRefund, | |
&buffer.at(offset)); | |
case SCOOTER_TYPE: | |
if (transaction->typeGroup == SCOOTER_TYPEGROUP) { | |
return ScooterRegistration::Deserialize( | |
&transaction->asset.scooterRegistration, | |
&buffer.at(offset)); | |
} | |
default: return 0UL; | |
}; | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
static void deserializeSignatures(TransactionData *transaction, | |
const uint8_t *buffer) { | |
uint8_t signatureLength = buffer[1] + 2U; | |
if (signatureLength >= SIGNATURE_ECDSA_MIN && | |
signatureLength <= SIGNATURE_ECDSA_MAX) { | |
transaction->signature.reserve(SIGNATURE_ECDSA_MAX); | |
transaction->signature.insert(transaction->signature.begin(), | |
buffer, | |
buffer + signatureLength); | |
} | |
uint8_t secondSignatureLength = buffer[signatureLength + 1U] + 2U; | |
if (secondSignatureLength >= SIGNATURE_ECDSA_MIN && | |
secondSignatureLength <= SIGNATURE_ECDSA_MAX) { | |
transaction->secondSignature.reserve(SIGNATURE_ECDSA_MAX); | |
transaction->secondSignature.insert( | |
transaction->secondSignature.begin(), | |
buffer + signatureLength, | |
buffer + signatureLength + secondSignatureLength); | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Deserialize Transaction Data | |
// | |
// @param TransactionData *data | |
// @param const std::vector<uint8_t> &buffer | |
// | |
// --- | |
auto Deserializer::deserialize(TransactionData *data, | |
const std::vector<uint8_t> &buffer) -> bool { | |
size_t assetOffset = 0UL; | |
// Use v2 or v1, otherwise return with no changes to the Tx Data. | |
if (buffer.at(VERSION_OFFSET) == 0x02) { | |
deserializeCommon(data, buffer); | |
assetOffset = VF_OFFSET + data->vendorField.size(); | |
} | |
else if(buffer.at(VERSION_OFFSET) == 0x01) { | |
deserializeCommonV1(data, buffer); | |
assetOffset = v1::VF_OFFSET + data->vendorField.size(); | |
} | |
else { return false; } | |
size_t assetSize = deserializeAsset(data, buffer, assetOffset); | |
deserializeSignatures(data, &buffer[assetOffset + assetSize]); | |
return true; | |
} | |
} // namespace transactions | |
} // namespace Crypto | |
} // namespace Ark |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of Ark Cpp Crypto. | |
* | |
* (c) Ark Ecosystem <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
**/ | |
#include "transactions/serializer.hpp" | |
#include <cstdint> | |
#include <cstring> | |
#include <vector> | |
#include "interfaces/constants.h" | |
#include "crypto/hash.hpp" | |
#include "transactions/defaults/offsets.hpp" | |
#include "transactions/transaction_data.hpp" | |
namespace Ark { | |
namespace Crypto { | |
namespace transactions { | |
//////////////////////////////////////////////////////////////////////////////// | |
// Serialize Common | |
// | |
// @param const TransactionData &data | |
// @param std::vector<uint8_t> &buffer: The serialized transactions buffer. | |
// | |
// --- | |
// Internals: | |
// | |
// Header - 1 Byte: | |
// - buffer.at(0) = transaction.header; | |
// | |
// Transaction Version - 1 Byte: | |
// - buffer.at(1) = transaction.version; | |
// | |
// Network Version - 1 Byte: | |
// - buffer.at(2) = transaction.network; | |
// | |
// TypeGroup - 4 Bytes: | |
// - memmove(&buffer.at(3), &transaction.typeGroup, sizeof(uint32_t)); | |
// | |
// Transaction Type - 2 Bytes: | |
// - memmove(&buffer.at(7), &transaction.type, sizeof(uint16_t)); | |
// | |
// Nonce - 8 Bytes: | |
// - memmove(&buffer.at(9), &transaction.nonce, sizeof(uint64_t)); | |
// | |
// SenderPublicKey - 33 Bytes: | |
// - buffer.insert(buffer.begin() + 17, transaction.senderPublicKey.begin(), transaction.senderPublicKey.end()); | |
// | |
// Fee - 8 bytes | |
// - memmove(&buffer.at(50), &transaction.fee, sizeof(uint64_t)); | |
// | |
// VendorField Length - 1 Byte: | |
// - buffer.at(58) = transaction.vendorField.size(); | |
// | |
// VendorField - 0 <=> 255 Bytes: | |
// - buffer.insert(buffer.begin() + 59, transaction.vendorField.begin(), transaction.vendorField.end()); | |
// | |
// --- | |
static void serializeCommon(const TransactionData &transaction, | |
std::vector<uint8_t> &buffer) { | |
buffer.at(HEADER_OFFSET) = transaction.header; // 1 Byte | |
buffer.at(VERSION_OFFSET) = transaction.version; // 1 Byte | |
buffer.at(NETWORK_OFFSET) = transaction.network; // 1 Byte | |
memmove(&buffer.at(TYPEGROUP_OFFSET), // 4 Bytes | |
&transaction.typeGroup, | |
sizeof(uint32_t)); | |
memmove(&buffer.at(TYPE_OFFSET), // 2 Bytes | |
&transaction.type, | |
sizeof(uint16_t)); | |
memmove(&buffer.at(NONCE_OFFSET), // 4 Bytes | |
&transaction.nonce, | |
sizeof(uint64_t)); | |
buffer.insert(buffer.begin() + SENDER_PUBLICKEY_OFFSET, // 21 Bytes | |
transaction.senderPublicKey.begin(), | |
transaction.senderPublicKey.end()); | |
memmove(&buffer.at(FEE_OFFSET), // 8 Bytes | |
&transaction.fee, | |
sizeof(uint64_t)); | |
buffer.at(VF_LEN_OFFSET) = // 1 Byte | |
static_cast<uint8_t>(transaction.vendorField.size()); | |
if (!transaction.vendorField.empty()) { | |
buffer.insert(buffer.begin() + VF_OFFSET, // 0 <=> 255 Bytes | |
transaction.vendorField.begin(), | |
transaction.vendorField.end()); | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Serialize Common V1 | |
// | |
// @param const TransactionData &data | |
// @param std::vector<uint8_t> &buffer: The serialized transactions buffer. | |
// | |
// --- | |
// Internals: | |
// | |
// Header - 1 Byte: | |
// - buffer.at(0) = transaction.header; | |
// | |
// Transaction Version - 1 Byte: | |
// - buffer.at(1) = transaction.version; | |
// | |
// Network Version - 1 Byte: | |
// - buffer.at(2) = transaction.network; | |
// | |
// Transaction Type - 1 Byte: | |
// - buffer.at(3) = transaction.type; | |
// | |
// Timestamp - 4 Bytes | |
// - memmove(&buffer.at(4), &transaction.timestamp,sizeof(uint32_t)); | |
// | |
// SenderPublicKey - 33 Bytes: | |
// - buffer.insert(buffer.begin() + 8, transaction.senderPublicKey.begin(), transaction.senderPublicKey.end()); | |
// | |
// Fee - 8 bytes | |
// - memmove(&buffer.at(41), &transaction.fee, sizeof(uint64_t)); | |
// | |
// VendorField Length - 1 Byte: | |
// - buffer.at(49) = transaction.vendorField.size(); | |
// | |
// VendorField - 0 <=> 255 Bytes: | |
// - buffer.insert(buffer.begin() + 50, transaction.vendorField.begin(), transaction.vendorField.end()); | |
// | |
// --- | |
static void serializeCommonV1(const TransactionData &transaction, | |
std::vector<uint8_t> &buffer) { | |
buffer.at(v1::HEADER_OFFSET) = transaction.header; // 1 Byte | |
buffer.at(v1::VERSION_OFFSET) = transaction.version; // 1 Byte | |
buffer.at(v1::NETWORK_OFFSET) = transaction.network; // 1 Byte | |
buffer.at(v1::TYPE_OFFSET) = // 1 Byte | |
static_cast<uint8_t>(transaction.type); | |
memmove(&buffer.at(v1::TIMESTAMP_OFFSET), // 4 Bytes | |
&transaction.timestamp, | |
sizeof(uint32_t)); | |
buffer.insert(buffer.begin() + v1::SENDER_PUBLICKEY_OFFSET, // 21 Bytes | |
transaction.senderPublicKey.begin(), | |
transaction.senderPublicKey.end()); | |
memmove(&buffer.at(v1::FEE_OFFSET), // 8 Bytes | |
&transaction.fee, | |
sizeof(uint64_t)); | |
buffer.at(v1::VF_LEN_OFFSET) = // 1 Byte | |
static_cast<uint8_t>(transaction.vendorField.size()); | |
if (!transaction.vendorField.empty()) { | |
buffer.insert(buffer.begin() + v1::VF_OFFSET, // 0 <=> 255 Bytes | |
transaction.vendorField.begin(), | |
transaction.vendorField.end()); | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
static auto serializeAsset(const TransactionData &transaction, | |
std::vector<uint8_t> &buffer, | |
const size_t offset) -> size_t { | |
switch (transaction.type) { | |
case TRANSFER_TYPE: | |
return Transfer::Serialize( | |
transaction.asset.transfer, | |
&buffer.at(offset)); | |
case SECOND_SIGNATURE_TYPE: | |
return SecondSignature::Serialize( | |
transaction.asset.secondSignature, | |
&buffer.at(offset)); | |
case DELEGATE_REGISTRATION_TYPE: | |
return DelegateRegistration::Serialize( | |
transaction.asset.delegateRegistration, | |
&buffer.at(offset)); | |
case VOTE_TYPE: | |
return Vote::Serialize( | |
transaction.asset.vote, | |
&buffer.at(offset)); | |
// case MULTI_SIGNATURE_TYPE: // TODO | |
case IPFS_TYPE: | |
return Ipfs::Serialize( | |
transaction.asset.ipfs, | |
&buffer.at(offset)); | |
case MULTI_PAYMENT_TYPE: | |
return MultiPayment::Serialize( | |
transaction.asset.multiPayment, | |
buffer, | |
offset); | |
case DELEGATE_RESIGNATION_TYPE: return 0UL; | |
case HTLC_LOCK_TYPE: | |
return HtlcLock::Serialize( | |
transaction.asset.htlcLock, | |
&buffer.at(offset)); | |
case HTLC_CLAIM_TYPE: | |
return HtlcClaim::Serialize( | |
transaction.asset.htlcClaim, | |
&buffer.at(offset)); | |
case HTLC_REFUND_TYPE: | |
return HtlcRefund::Serialize( | |
transaction.asset.htlcRefund, | |
&buffer.at(offset)); | |
case SCOOTER_TYPE: | |
if (transaction.typeGroup == SCOOTER_TYPEGROUP) { | |
return ScooterRegistration::Serialize( | |
transaction.asset.scooterRegistration, | |
&buffer.at(offset)); | |
} | |
default: return 0UL; | |
}; | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
static auto serializeSignatures(const TransactionData &data, | |
std::vector<uint8_t> &buffer, | |
const size_t offset, | |
const SerializerOptions &options) -> size_t { | |
if (!options.excludeSignature && | |
data.signature.size() >= SIGNATURE_ECDSA_MIN && | |
data.signature.size() <= SIGNATURE_ECDSA_MAX) { | |
buffer.insert(buffer.begin() + offset, | |
data.signature.begin(), | |
data.signature.end()); | |
} | |
else { return 0UL; } | |
if (!options.excludeSecondSignature && | |
data.secondSignature.size() >= SIGNATURE_ECDSA_MIN && | |
data.secondSignature.size() <= SIGNATURE_ECDSA_MAX) { | |
buffer.insert(buffer.begin() + offset + data.signature.size(), | |
data.secondSignature.begin(), | |
data.secondSignature.end()); | |
} | |
else { return data.signature.size(); } | |
return data.signature.size() + data.secondSignature.size(); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Serialize Transaction Data | |
// | |
// @param const TransactionData &data | |
// @param const SerializerOptions &options | |
// | |
// @return std::vector<uint8_t> | |
// | |
// --- | |
auto Serializer::serialize(const TransactionData &data, | |
const SerializerOptions &options) | |
-> std::vector<uint8_t>{ | |
std::vector<uint8_t> buffer; | |
buffer.resize(TX_DEFAULT_SIZE); | |
size_t assetOffset = 0UL; | |
// Use v2 or v1, otherwise return an empty object. | |
if (data.version == TRANSACTION_VERSION_TYPE_2) { | |
serializeCommon(data, buffer); | |
assetOffset = VF_OFFSET + data.vendorField.size(); | |
} | |
else if (data.version == TRANSACTION_VERSION_TYPE_1) { | |
serializeCommonV1(data, buffer); | |
assetOffset = v1::VF_OFFSET + data.vendorField.size(); | |
} | |
else { return {}; } | |
size_t assetSize = serializeAsset(data, buffer, assetOffset); | |
size_t signaturesSize = serializeSignatures(data, | |
buffer, | |
assetOffset + assetSize, | |
options); | |
buffer.resize(assetOffset + assetSize + signaturesSize); | |
return buffer; | |
} | |
} // namespace transactions | |
} // namespace Crypto | |
} // namespace Ark |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of Ark Cpp Crypto. | |
* | |
* (c) Ark Ecosystem <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
**/ | |
#include "transactions/transaction.hpp" | |
#include <cstddef> | |
#include <cstdint> | |
#include <map> | |
#include <string> | |
#include <utility> | |
#include <vector> | |
#include "crypto/curve.hpp" | |
#include "crypto/hash.hpp" | |
#include "identities/keys.hpp" | |
#include "transactions/deserializer.hpp" | |
#include "transactions/serializer.hpp" | |
#include "transactions/defaults/offsets.hpp" | |
#include "transactions/transaction_data.hpp" | |
#include "utils/base58.hpp" | |
#include "utils/hex.hpp" | |
#include "utils/json.h" | |
#include "utils/str.hpp" | |
namespace Ark { | |
namespace Crypto { | |
namespace transactions { | |
//////////////////////////////////////////////////////////////////////////////// | |
// Compute the unique transaction ID. | |
auto Transaction::getId() const -> Hash32 { | |
const auto serialized = this->toBytes(false, false); | |
return Hash::sha256(serialized.data(), serialized.size()); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Sign the transaction using a passphrase. | |
auto Transaction::sign(const std::string &passphrase) -> bool { | |
if (passphrase.empty()) { | |
return false; | |
} | |
const auto keys = identities::Keys::fromPassphrase(passphrase.c_str()); | |
std::move(keys.publicKey.begin(), | |
keys.publicKey.end(), | |
this->data.senderPublicKey.begin()); | |
const auto serialized = this->toBytes(true, true); | |
const auto hash32 = Hash::sha256(serialized.data(), serialized.size()); | |
this->data.signature.reserve(SIGNATURE_ECDSA_MAX); | |
return Curve::Ecdsa::sign(hash32.data(), | |
keys.privateKey.data(), | |
&this->data.signature); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Sign the Transaction using a Second Passphrase. | |
auto Transaction::secondSign(const std::string &secondPassphrase) -> bool { | |
if (this->data.signature.empty() || secondPassphrase.empty()) { | |
return false; | |
} | |
const auto keys = identities::Keys::fromPassphrase(secondPassphrase.c_str()); | |
const auto serialized = this->toBytes(false, true); | |
const auto hash32 = Hash::sha256(serialized.data(), serialized.size()); | |
this->data.secondSignature.reserve(SIGNATURE_ECDSA_MAX); | |
return Curve::Ecdsa::sign(hash32.data(), | |
keys.privateKey.data(), | |
&this->data.secondSignature); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Verify the Transaction. | |
auto Transaction::verify() const -> bool { | |
// skip both signatures, | |
// neither should be present in the signing hash. | |
const auto serialized = this->toBytes(true, true); | |
const auto hash32 = Hash::sha256(serialized.data(), serialized.size()); | |
return Curve::Ecdsa::verify(hash32.data(), | |
this->data.senderPublicKey.data(), | |
this->data.signature); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Verify the Transaction using a Second PublicKey. | |
auto Transaction::secondVerify(const uint8_t *secondPublicKey) const -> bool { | |
// include only the first signature, | |
// that should be present signing hash for a second signing. | |
const auto serialized = this->toBytes(false, true); | |
const auto hash32 = Hash::sha256(serialized.data(), serialized.size()); | |
return Curve::Ecdsa::verify(hash32.data(), | |
secondPublicKey, | |
this->data.secondSignature); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Deserialize the given Hex string via AIP11. | |
auto Transaction::deserialize(const std::vector<uint8_t> &serialized) -> bool { | |
return Deserializer::deserialize(&this->data, serialized); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Serialize the object via AIP11. | |
auto Transaction::serialize() -> std::vector<uint8_t> { | |
return Serializer::serialize(this->data); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Turn the Transaction into its byte representation. | |
auto Transaction::toBytes(bool excludeSignature, | |
bool excludeSecondSignature) const | |
-> std::vector<uint8_t> { | |
return Serializer::serialize(this->data, | |
{ excludeSignature, excludeSecondSignature }); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Turn the transaction into a standardized array. | |
// | |
// This concept of an array in is quite different compared to other ARK SDKs. | |
// C++11 doesn't have an 'Any' type, so we'll need to use a string map here. | |
// | |
// Json Sizes are approximated using 'https://arduinojson.org/v6/assistant/' | |
// | |
// -- | |
auto Transaction::toMap() const -> std::map<std::string, std::string> { | |
std::map<std::string, std::string> map; | |
size_t jsonSize = 0UL; | |
size_t extraBytes = | |
static_cast<size_t>(this->data.vendorField.empty()) + | |
this->data.vendorField.size() + sizeof("vendorField") - 1 + | |
static_cast<size_t>(this->data.signature.empty()) + | |
this->data.signature.size() + sizeof("signature") - 1 + | |
static_cast<size_t>(this->data.secondSignature.empty()) + | |
this->data.secondSignature.size() + sizeof("secondSignature") - 1; | |
// Start with the Transaction's Asset. | |
// Tranfer | |
if (this->data.type == TRANSFER_TYPE) { | |
map = Transfer::getMap(this->data.asset.transfer); | |
jsonSize = JSON_OBJECT_SIZE(11) + | |
TRANSACTION_TYPE_TRANSFER_SIZE + | |
extraBytes + | |
289; | |
} | |
// Second Signature Registration | |
if (this->data.type == SECOND_SIGNATURE_TYPE) { | |
map = SecondSignature::getMap(this->data.asset.secondSignature); | |
jsonSize = 2 * JSON_OBJECT_SIZE(1) + | |
JSON_OBJECT_SIZE(9) + | |
PUBLICKEY_COMPRESSED_LEN + | |
extraBytes + | |
297; | |
} | |
// Delegate Registration | |
if (this->data.type == DELEGATE_REGISTRATION_TYPE) { | |
map = DelegateRegistration::getMap( | |
this->data.asset.delegateRegistration); | |
jsonSize = | |
2 * JSON_OBJECT_SIZE(1) + | |
JSON_OBJECT_SIZE(9) + | |
sizeof("username") - 1 + | |
strtol(map["usernameLen"].c_str(), nullptr, BASE_10) + | |
extraBytes + | |
251; | |
} | |
// Vote | |
if (this->data.type == VOTE_TYPE) { | |
map = Vote::getMap(this->data.asset.vote); | |
jsonSize = JSON_ARRAY_SIZE(1) + | |
JSON_OBJECT_SIZE(1) + | |
JSON_OBJECT_SIZE(9) + | |
VOTES_LEN + | |
extraBytes + | |
284; | |
} | |
// MultiSignature Registration | |
// if (this->data.type == MULTI_SIGNATURE_TYPE) {} // TODO | |
// Ipfs | |
if (this->data.type == IPFS_TYPE) { | |
map = Ipfs::getMap(this->data.asset.ipfs); | |
jsonSize = 2 * JSON_OBJECT_SIZE(1) + | |
JSON_OBJECT_SIZE(11) + | |
strtol(map["ipfsLen"].c_str(), nullptr, BASE_10) + | |
sizeof("ipfs") - 1U + | |
extraBytes + | |
218; | |
} | |
// MultiPayment | |
if (this->data.type == MULTI_PAYMENT_TYPE) { | |
map = MultiPayment::getMap(this->data.asset.multiPayment); | |
// Get the number of payments. | |
const auto n_payments = strtol(map["n_payments"].c_str(), | |
nullptr, | |
BASE_10); | |
const auto uint64StrSize = 20; | |
jsonSize = | |
JSON_ARRAY_SIZE(n_payments) + | |
JSON_OBJECT_SIZE(1) + | |
(n_payments * JSON_OBJECT_SIZE(2)) + | |
JSON_OBJECT_SIZE(10) + | |
(n_payments * (sizeof("amount") - 1 + uint64StrSize + | |
sizeof("recipientId") - 1 + ADDRESS_STR_LEN)) + | |
483; | |
} | |
// Delegate Resignation | |
if (this->data.type == DELEGATE_RESIGNATION_TYPE) { | |
jsonSize = JSON_OBJECT_SIZE(10) + extraBytes * 205; | |
} | |
// Htlc Lock | |
if (this->data.type == HTLC_LOCK_TYPE) { | |
map = HtlcLock::getMap(this->data.asset.htlcLock); | |
jsonSize = JSON_OBJECT_SIZE(1) + | |
(2 * JSON_OBJECT_SIZE(2)) + | |
JSON_OBJECT_SIZE(11) + | |
HTLC_LOCK_SIZE + | |
extraBytes + | |
368; | |
} | |
// Htlc Claim | |
if (this->data.type == HTLC_CLAIM_TYPE) { | |
map = HtlcClaim::getMap(this->data.asset.htlcClaim); | |
jsonSize = JSON_OBJECT_SIZE(1) + | |
JSON_OBJECT_SIZE(2) + | |
JSON_OBJECT_SIZE(9) + | |
HASH_32_LEN + HASH_32_LEN + | |
extraBytes + | |
337; | |
} | |
// Htlc Refund | |
if (this->data.type == HTLC_REFUND_TYPE) { | |
map = HtlcRefund::getMap(this->data.asset.htlcRefund); | |
jsonSize = 2 * JSON_OBJECT_SIZE(1) + | |
JSON_OBJECT_SIZE(11) + | |
HASH_32_LEN + | |
extraBytes + | |
445; | |
} | |
// Scooter Registration | |
if (this->data.typeGroup == SCOOTER_TYPEGROUP && this->data.type == SCOOTER_TYPE) { | |
map = ScooterRegistration::getMap(this->data.asset.scooterRegistration); | |
jsonSize = 2 * JSON_OBJECT_SIZE(1) + | |
JSON_OBJECT_SIZE(9) + | |
sizeof("scooterId") - 1 + SCOOTER_ID_LEN + | |
extraBytes + | |
233; | |
} | |
// Continue with the Common variables | |
// Version | |
map.emplace("version", UintToString(this->data.version)); | |
// Network | |
map.emplace("network", UintToString(this->data.network)); | |
// v2 | |
if (this->data.version == TRANSACTION_VERSION_TYPE_2) { | |
// TypeGroup | |
map.emplace("typeGroup", UintToString(this->data.typeGroup)); | |
} | |
// Type | |
map.emplace("type", UintToString(this->data.type)); | |
// v2 | |
if (this->data.version == TRANSACTION_VERSION_TYPE_2) { | |
// Nonce | |
map.emplace("nonce", UintToString(this->data.nonce)); | |
} | |
// v1 | |
else if (this->data.version == TRANSACTION_VERSION_TYPE_1) { | |
// Timestamp | |
map.emplace("timestamp", UintToString(this->data.timestamp)); | |
} | |
// Sender PublicKey | |
map.emplace("senderPublicKey", BytesToHex(this->data.senderPublicKey)); | |
// Fee | |
map.emplace("fee", UintToString(this->data.fee)); | |
// VendorField | |
if (!this->data.vendorField.empty()) { | |
const auto vf = reinterpret_cast<const char *>( | |
this->data.vendorField.data()); | |
map.emplace("vendorField", | |
std::string(vf, vf + this->data.vendorField.size())); | |
} | |
// Signature | |
if (!this->data.signature.empty()) { | |
map.emplace("signature", BytesToHex(this->data.signature)); | |
} | |
// Second Signature | |
if (!this->data.secondSignature.empty()) { | |
map.emplace("secondSignature", BytesToHex(this->data.secondSignature)); | |
} | |
// Transaction Id | |
map.emplace("id", BytesToHex(this->getId())); | |
// v2 | |
if (this->data.version == TRANSACTION_VERSION_TYPE_2) { | |
jsonSize += VF_OFFSET; | |
} | |
// v1 | |
else if (this->data.version == TRANSACTION_VERSION_TYPE_1) { | |
jsonSize += v1::VF_OFFSET; | |
} | |
map.emplace("jsonSize", UintToString(jsonSize)); | |
return map; | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Turn the Transaction into a JSON string using `toMap` as the source. | |
auto Transaction::toJson() const -> std::string { | |
auto txArray = this->toMap(); | |
const auto jsonSize = strtol(txArray["jsonSize"].c_str(), nullptr, BASE_10); | |
const auto docCapacity = jsonSize; | |
DynamicJsonDocument doc(docCapacity); | |
// Version | |
doc["version"] = strtol(txArray["version"].c_str(), nullptr, BASE_10); | |
// Network | |
doc["network"] = strtol(txArray["network"].c_str(), nullptr, BASE_10); | |
// v2 | |
if (this->data.version == TRANSACTION_VERSION_TYPE_2) { | |
// TypeGroup | |
doc["typeGroup"] = strtol(txArray["typeGroup"].c_str(), | |
nullptr, | |
BASE_10); | |
} | |
// Type | |
doc["type"] = strtol(txArray["type"].c_str(), nullptr, BASE_10); | |
// v2 | |
if (this->data.version == TRANSACTION_VERSION_TYPE_2) { | |
// Nonce | |
doc["nonce"] = txArray["nonce"]; | |
} | |
// v1 | |
else if (this->data.version == TRANSACTION_VERSION_TYPE_1) { | |
// Timestamp | |
doc["timestamp"] = txArray["timestamp"]; | |
} | |
// Sender PublicKey | |
doc["senderPublicKey"] = txArray["senderPublicKey"]; | |
// Fee | |
doc["fee"] = txArray["fee"]; | |
// VendorField | |
if (!this->data.vendorField.empty()) { | |
doc["vendorField"] = txArray["vendorField"]; | |
} | |
// Assets | |
// Transfer | |
if (this->data.type == TRANSFER_TYPE) { | |
// Amount | |
doc["amount"] = txArray["amount"]; | |
// Expiration | |
doc["expiration"] = strtol(txArray["expiration"].c_str(), | |
nullptr, | |
BASE_10); | |
// RecipientId | |
doc["recipientId"] = txArray["recipientId"]; | |
} | |
// Second Signature Registration | |
if (this->data.type == SECOND_SIGNATURE_TYPE) { | |
JsonObject asset = doc.createNestedObject("asset"); | |
JsonObject secondSignature = asset.createNestedObject("signature"); | |
// Second PublicKey | |
secondSignature["publicKey"] = txArray["publicKey"]; | |
} | |
// Delegate Registration | |
if (this->data.type == DELEGATE_REGISTRATION_TYPE) { | |
JsonObject asset = doc.createNestedObject("asset"); | |
JsonObject registration = asset.createNestedObject("delegate"); | |
// Username | |
registration["username"] = txArray["username"]; | |
} | |
// Vote | |
if (this->data.type == VOTE_TYPE) { | |
JsonObject asset = doc.createNestedObject("asset"); | |
JsonArray votes = asset.createNestedArray("votes"); | |
// Votes | |
votes.add(txArray["votes"]); | |
} | |
// MultiSignature Registration | |
// if (this->data.type == MULTI_SIGNATURE_TYPE) {} // TODO | |
// Ipfs | |
if (this->data.type == IPFS_TYPE) { | |
JsonObject asset = doc.createNestedObject("asset"); | |
// Ipfs DAG | |
asset["ipfs"] = txArray["ipfs"]; | |
} | |
// MultiPayment | |
if (this->data.type == MULTI_PAYMENT_TYPE) { | |
JsonObject asset = doc.createNestedObject("asset"); | |
JsonArray payments = asset.createNestedArray("payments"); | |
const auto paymentsStr = txArray["amounts"]; | |
const auto addressesStr = txArray["addresses"]; | |
const auto n_payments = strtol(txArray["n_payments"].c_str(), | |
nullptr, | |
BASE_10); | |
for (uint8_t i = 0U; i < n_payments; ++i) { | |
JsonObject payment_n = payments.createNestedObject(); | |
// Ammount(N) | |
payment_n["amount"] = paymentsStr | |
.substr(0, paymentsStr.find(',', 0)); | |
// RecipientId(N) | |
payment_n["recipientId"] = addressesStr | |
.substr(i + (i * ADDRESS_STR_LEN), ADDRESS_STR_LEN); | |
} | |
} | |
// Delegate Resignation | |
// No Asset Needed. | |
// HTLC Lock | |
if (this->data.type == HTLC_LOCK_TYPE) { | |
// Amount | |
doc["amount"] = txArray["amount"]; | |
// RecipientId | |
doc["recipientId"] = txArray["recipientId"]; | |
JsonObject asset = doc.createNestedObject("asset"); | |
JsonObject lock = asset.createNestedObject("lock"); | |
// Secret Hash | |
lock["secretHash"] = txArray["secretHash"]; | |
JsonObject expiration = lock.createNestedObject("expiration"); | |
// Expiration Type | |
expiration["type"] = strtol(txArray["expirationType"].c_str(), | |
nullptr, | |
BASE_10); | |
// Expiration Value | |
expiration["value"] = strtol(txArray["expiration"].c_str(), | |
nullptr, | |
BASE_10); | |
} | |
// HTLC Claim | |
if (this->data.type == HTLC_CLAIM_TYPE) { | |
JsonObject asset = doc.createNestedObject("asset"); | |
JsonObject claim = asset.createNestedObject("claim"); | |
// Lock Transaction Id | |
claim["lockTransactionId"] = txArray["lockTransactionId"]; | |
// Unlock Secret | |
claim["unlockSecret"] = txArray["unlockSecret"]; | |
} | |
// HTLC Refund | |
if (this->data.type == HTLC_REFUND_TYPE) { | |
JsonObject asset = doc.createNestedObject("asset"); | |
JsonObject refund = asset.createNestedObject("refund"); | |
// Lock Transaction Id | |
refund["lockTransactionId"] = txArray["lockTransactionId"]; | |
} | |
// Scooter Registration | |
if (this->data.typeGroup == SCOOTER_TYPEGROUP && this->data.type == SCOOTER_TYPE) { | |
doc["amount"] = "0"; | |
JsonObject asset = doc.createNestedObject("asset"); | |
// ScooterId | |
asset["scooterId"] = txArray["scooterId"]; | |
} | |
// Signature | |
if (!this->data.signature.empty()) { | |
doc["signature"] = txArray["signature"]; | |
} | |
// Second Signature | |
if (!this->data.secondSignature.empty()) { | |
doc["secondSignature"] = txArray["secondSignature"]; | |
} | |
// Transaction Id | |
doc["id"] = txArray["id"]; | |
std::string jsonStr; | |
jsonStr.reserve(docCapacity); | |
serializeJson(doc, jsonStr); | |
return jsonStr; | |
} | |
} // namespace transactions | |
} // namespace Crypto | |
} // namespace Ark |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of Ark Cpp Crypto. | |
* | |
* (c) Ark Ecosystem <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
**/ | |
#ifndef ARK_TRANSACTIONS_TYPES_ASSETS_HPP | |
#define ARK_TRANSACTIONS_TYPES_ASSETS_HPP | |
#include "transactions/defaults/types.hpp" | |
#include "transactions/types/transfer.hpp" | |
#include "transactions/types/second_signature.hpp" | |
#include "transactions/types/delegate_registration.hpp" | |
#include "transactions/types/vote.hpp" | |
// #include "transactions/types/multi_signature.hpp" | |
#include "transactions/types/ipfs.hpp" | |
#include "transactions/types/multi_payment.hpp" | |
#include "transactions/types/delegate_resignation.hpp" | |
#include "transactions/types/htlc_lock.hpp" | |
#include "transactions/types/htlc_claim.hpp" | |
#include "transactions/types/htlc_refund.hpp" | |
#include "transactions/types/scooter_registration.hpp" | |
namespace Ark { | |
namespace Crypto { | |
namespace transactions { | |
//////////////////////////////////////////////////////////////////////////////// | |
// AIP-11 Transaction Assets | |
typedef struct tx_asset_t { | |
Transfer transfer; // Type 0 | |
SecondSignature secondSignature; // Type 1 | |
DelegateRegistration delegateRegistration; // Type 2 | |
Vote vote; // Type 3 | |
// MultiSignature multiSignature; // Type 4 | |
Ipfs ipfs; // Type 5 | |
MultiPayment multiPayment; // Type 6 | |
DelegateResignation delegateResignation; // Type 7 | |
HtlcLock htlcLock; // Type 8 | |
HtlcClaim htlcClaim; // Type 9 | |
HtlcRefund htlcRefund; // Type 10 | |
ScooterRegistration scooterRegistration; // TypeGroup 4000, type 400 | |
} Asset; | |
} // namespace transactions | |
} // namespace Crypto | |
} // namespace Ark | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of Ark Cpp Crypto. | |
* | |
* (c) Ark Ecosystem <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
**/ | |
#include "transactions/types/scooter_registration.hpp" | |
#include <cstdint> | |
#include <map> | |
#include <string> | |
#include <utility> | |
namespace Ark { | |
namespace Crypto { | |
namespace transactions { | |
//////////////////////////////////////////////////////////////////////////////// | |
// Deserialize Scooter Registration (TypeGroup 4000, Type 400) - 11 bytes | |
// | |
// @param ScooterRegistration *registration | |
// @param uint8_t *buffer: The serialized buffer beginning at the Assets offset. | |
// | |
// @return Asset Length | |
// | |
// --- | |
// Internals: | |
// | |
// ScooterId Len - 1 Byte | |
// - registration->scooterId.resize(buffer[0]); | |
// | |
// ScooterId - 10 Bytes: | |
// - std::move(&buffer[1], &buffer[1 + 10], registration->scooterId.data()); | |
// | |
// --- | |
auto ScooterRegistration::Deserialize(ScooterRegistration *registration, | |
const uint8_t *buffer) | |
-> size_t { | |
registration->scooterId.resize(buffer[0]); // 1 Byte | |
std::move(&buffer[sizeof(uint8_t)], // 10 Bytes | |
&buffer[sizeof(uint8_t) + SCOOTER_ID_LEN], | |
registration->scooterId.begin()); | |
return sizeof(uint8_t) + SCOOTER_ID_LEN; // 11 Bytes | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Serialize Scooter Registration (TypeGroup 4000, Type 400) - 11 bytes | |
// | |
// @param const ScooterRegistration ®istration | |
// @param uint8_t *buffer: The serialized buffer at the Assets offset. | |
// | |
// @return Asset Length | |
// | |
// --- | |
// Internals: | |
// | |
// ScooterId Length - 1 Byte | |
// - buffer[0] = static_cast<uint8_t>(10); | |
// | |
// ScooterId - 10 Bytes: | |
// - std::move(registration.scooterId.begin(), registration.scooterId.end(), &buffer[1]); | |
// | |
// --- | |
auto ScooterRegistration::Serialize(const ScooterRegistration ®istration, | |
uint8_t *buffer) -> size_t { | |
buffer[0] = // 1 Byte | |
static_cast<uint8_t>(registration.scooterId.length()); | |
std::move(registration.scooterId.begin(), // 10 Bytes | |
registration.scooterId.end(), | |
&buffer[sizeof(uint8_t)]); | |
return sizeof(uint8_t) + SCOOTER_ID_LEN; // 11 Bytes | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Return a Map of the Transfer asset. | |
auto ScooterRegistration::getMap(const ScooterRegistration ®istration) | |
-> std::map<std::string, std::string> { | |
std::map<std::string, std::string> map; | |
// ScooterId | |
map.emplace("scooterId", registration.scooterId); | |
return map; | |
} | |
} // namespace transactions | |
} // namespace Crypto | |
} // namespace Ark |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of Ark Cpp Crypto. | |
* | |
* (c) Ark Ecosystem <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
**/ | |
#ifndef ARK_TRANSACTIONS_TYPES_SCOOTER_REGISTRATION_HPP | |
#define ARK_TRANSACTIONS_TYPES_SCOOTER_REGISTRATION_HPP | |
#include <array> | |
#include <cstdint> | |
#include <cstring> | |
#include <map> | |
#include <string> | |
#include "interfaces/constants.h" | |
#include "utils/json.h" | |
namespace Ark { | |
namespace Crypto { | |
namespace transactions { | |
const uint32_t SCOOTER_TYPEGROUP = 4000UL; | |
const uint16_t SCOOTER_TYPE = 400UL; | |
const size_t SCOOTER_ID_LEN = 10UL; | |
//////////////////////////////////////////////////////////////////////////////// | |
// TypeGroup 4000, Type 400 - Scooter Registration | |
struct ScooterRegistration { | |
//////////////////////////////////////////////////////////////////////////// | |
std::string scooterId; | |
//////////////////////////////////////////////////////////////////////////// | |
static size_t Deserialize(ScooterRegistration *registration, | |
const uint8_t *buffer); | |
//////////////////////////////////////////////////////////////////////////// | |
static size_t Serialize(const ScooterRegistration ®istration, | |
uint8_t *buffer); | |
//////////////////////////////////////////////////////////////////////////// | |
static std::map<std::string, std::string> getMap( | |
const ScooterRegistration ®istration); | |
//////////////////////////////////////////////////////////////////////////// | |
ScooterRegistration() : scooterId() {} | |
}; | |
} // namespace transactions | |
} // namespace Crypto | |
} // namespace Ark | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.2) | |
project(${PROJECT_NAME}_tests C CXX) | |
set (PROJECT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) | |
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../lib") | |
# ------------------------------------------------------------------------------ | |
# External Libraries | |
# ------------------------------------------------------------------------------ | |
include(${CMAKE_SOURCE_DIR}/cmake/GTest.cmake) | |
include_directories(${ARDUINO_JSON_SOURCE_DIR}) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Link the directories to be included | |
# ------------------------------------------------------------------------------ | |
include_directories(${PROJECT_SOURCE_DIR}) | |
include_directories(${PROJECT_SOURCE_DIR}/../src) | |
include_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# ARK C++ Crypto Test Source | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Common | |
set(COMMON_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/common/configuration.cpp | |
${PROJECT_SOURCE_DIR}/common/fee_policy.cpp | |
${PROJECT_SOURCE_DIR}/common/network.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Crypto | |
set(CRYPTO_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/crypto/curve_ecdsa_sign_null_hash.cpp | |
${PROJECT_SOURCE_DIR}/crypto/curve_ecdsa_sign_null_privatekey.cpp | |
${PROJECT_SOURCE_DIR}/crypto/curve_ecdsa_sign.cpp | |
${PROJECT_SOURCE_DIR}/crypto/curve_publickey.cpp | |
${PROJECT_SOURCE_DIR}/crypto/curve_verify_invalid.cpp | |
${PROJECT_SOURCE_DIR}/crypto/curve_verify_valid.cpp | |
${PROJECT_SOURCE_DIR}/crypto/hash.cpp | |
${PROJECT_SOURCE_DIR}/crypto/message_sign.cpp | |
${PROJECT_SOURCE_DIR}/crypto/message_verify.cpp | |
${PROJECT_SOURCE_DIR}/crypto/message.cpp | |
${PROJECT_SOURCE_DIR}/crypto/slot.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Identities | |
set(IDENTITIES_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/identities/address.cpp | |
${PROJECT_SOURCE_DIR}/identities/keys.cpp | |
${PROJECT_SOURCE_DIR}/identities/keys_publickey.cpp | |
${PROJECT_SOURCE_DIR}/identities/privatekey.cpp | |
${PROJECT_SOURCE_DIR}/identities/publickey.cpp | |
${PROJECT_SOURCE_DIR}/identities/wif.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Managers | |
set(MANAGERS_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/managers/fee_manager.cpp | |
${PROJECT_SOURCE_DIR}/managers/network_manager.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Networks | |
set(NETWORKS_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/networks/devnet.cpp | |
${PROJECT_SOURCE_DIR}/networks/mainnet.cpp | |
${PROJECT_SOURCE_DIR}/networks/testnet.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Transactions Test Sources | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Builders | |
set(TRANSACTIONS_BUILDERS_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/transactions/builders/transfer.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/second_signature.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/delegate_registration.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/vote.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/ipfs.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/multi_payment.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/htlc_lock.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/htlc_claim.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/htlc_refund.cpp | |
${PROJECT_SOURCE_DIR}/transactions/builders/scooter_registration.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Defaults | |
set(TRANSACTIONS_DEFAULTS_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/transactions/defaults/fees_types.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Serialization/Deserialization | |
set(TRANSACTIONS_SERDE_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/transactions/deserializer.cpp | |
${PROJECT_SOURCE_DIR}/transactions/serializer.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# v1 Types | |
set(TRANSACTIONS_TYPES_V1_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/transactions/types/transfer_v1.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/second_signature_v1.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/delegate_registration_v1.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/vote_v1.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Types | |
set(TRANSACTIONS_TYPES_TEST_SOURCE | |
${TRANSACTIONS_TYPES_V1_SOURCE} | |
${PROJECT_SOURCE_DIR}/transactions/types/transfer.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/second_signature.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/delegate_registration.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/vote.cpp | |
# ${PROJECT_SOURCE_DIR}/transactions/types/multi_signature.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/ipfs.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/multi_payment.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/delegate_resignation.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/htlc_lock.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/htlc_claim.cpp | |
${PROJECT_SOURCE_DIR}/transactions/types/htlc_refund.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Transactions Test Source Files | |
set(TRANSACTIONS_TEST_SOURCE | |
${TRANSACTIONS_BUILDERS_TEST_SOURCE} | |
${TRANSACTIONS_DEFAULTS_TEST_SOURCE} | |
${TRANSACTIONS_SERDE_TEST_SOURCE} | |
${TRANSACTIONS_TYPES_V1_TEST_SOURCE} | |
${TRANSACTIONS_TYPES_TEST_SOURCE} | |
${TRANSACTIONS_TRANSACTION_TEST_SOURCE} | |
${PROJECT_SOURCE_DIR}/transactions/transaction.cpp | |
${PROJECT_SOURCE_DIR}/transactions/transaction_v1.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# Utils | |
set(UTILS_TEST_SOURCE | |
${PROJECT_SOURCE_DIR}/utils/base58.cpp | |
${PROJECT_SOURCE_DIR}/utils/crypto_helpers.cpp | |
${PROJECT_SOURCE_DIR}/utils/hex.cpp | |
${PROJECT_SOURCE_DIR}/utils/str.cpp | |
${PROJECT_SOURCE_DIR}/utils/unpack.cpp | |
) | |
# ------------------------------------------------------------------------------ | |
# ARK C++ Library Test Source | |
set(ARK_TEST_SOURCE | |
${COMMON_TEST_SOURCE} | |
${CRYPTO_TEST_SOURCE} | |
${IDENTITIES_TEST_SOURCE} | |
${MANAGERS_TEST_SOURCE} | |
${NETWORKS_TEST_SOURCE} | |
${TRANSACTIONS_TEST_SOURCE} | |
${UTILS_TEST_SOURCE} | |
) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Link ARK C++ Crypto to the Test Libraries | |
# ------------------------------------------------------------------------------ | |
find_library(${PROJECT_NAME} PUBLIC) | |
add_executable(${PROJECT_NAME} ${ARK_TEST_SOURCE}) | |
target_link_libraries(${PROJECT_NAME} ark_cpp_crypto gtest gtest_main) | |
add_test(NAME test COMMAND ${PROJECT_NAME}) | |
# ------------------------------------------------------------------------------ | |
# ------------------------------------------------------------------------------ | |
# Coverage | |
# ------------------------------------------------------------------------------ | |
if (CMAKE_BUILD_TYPE STREQUAL "Coverage") | |
include("${CMAKE_SOURCE_DIR}/cmake/CodeCoverage.cmake") | |
setup_target_for_coverage(${PROJECT_NAME}_coverage ${PROJECT_NAME}_tests coverage) | |
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") | |
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") | |
endif() #CMAKE_BUILD_TYPE STREQUAL "Coverage" | |
# ------------------------------------------------------------------------------ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This file is part of Ark Cpp Crypto. | |
* | |
* (c) Ark Ecosystem <[email protected]> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
**/ | |
#include "gtest/gtest.h" | |
#include "transactions/builders/scooter_registration.hpp" | |
#include "common/configuration.hpp" | |
#include "identities/keys.hpp" | |
#include "test_helpers.h" | |
using namespace Ark::Crypto; | |
using namespace Ark::Crypto::transactions; | |
//////////////////////////////////////////////////////////////////////////////// | |
TEST(transactions_builder, scooter_registration) { // NOLINT | |
const Network Radians = { | |
"f39a61f04d6136a690a0b675ef6eedbd053665bd343b4e4f03311f12065fb875", | |
1, 0xCE, 0x41, | |
"2019-10-25T09:05:40.856Z" | |
}; | |
const Configuration radiansCfg(Radians); | |
const uint8_t radiansRecipient[] = { | |
65, 29, 252, 105, 181, 76, 127, 233, 1, 233, 29, | |
90, 154, 183, 131, 136, 100, 94, 36, 39, 234 }; | |
const auto passphrase = "vehicle smile daughter torch often ask rare crucial best cargo half lady"; | |
const auto publicKey = identities::Keys::fromPassphrase(passphrase).publicKey; | |
auto transaction = builder::ScooterRegistration() | |
.typeGroup(SCOOTER_TYPEGROUP) | |
.type(SCOOTER_TYPE) | |
.nonce(3) | |
.senderPublicKey(publicKey.data()) | |
.fee(3000000000ULL) | |
.scooterId("1234567890") | |
.build(radiansCfg); | |
transaction.sign(passphrase); | |
ASSERT_TRUE(transaction.verify()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment