mirror of
https://github.com/MAGICGrants/flutter_libsparkmobile.git
synced 2026-01-09 13:08:00 -05:00
WIP spark spend ffi binding
This commit is contained in:
@@ -223,18 +223,140 @@ abstract final class LibSpark {
|
||||
}
|
||||
|
||||
///
|
||||
/// Attempt to create and sign a spark spend transaction.
|
||||
/// Attempt to create a spark spend.
|
||||
///
|
||||
/// Returns the raw transaction hex if successful, otherwise null.
|
||||
/// Returns the serialized spark spend.
|
||||
///
|
||||
static String? createSparkSendTransaction({
|
||||
static ({
|
||||
String serializedSpendPayload,
|
||||
List<Uint8List> outputScripts,
|
||||
int fee,
|
||||
}) createSparkSendTransaction({
|
||||
required String privateKeyHex,
|
||||
// TODO what do we need?
|
||||
int index = 1,
|
||||
required List<({String address, int amount, bool subtractFeeFromAmount})>
|
||||
recipients,
|
||||
required List<
|
||||
({
|
||||
String sparkAddress,
|
||||
int amount,
|
||||
bool subtractFeeFromAmount,
|
||||
String memo
|
||||
})>
|
||||
privateRecipients,
|
||||
required List<Uint8List> serializedMintMetas,
|
||||
required List<
|
||||
({
|
||||
int setId,
|
||||
String setHash,
|
||||
List<({String serializedCoin, String txHash})> set
|
||||
})>
|
||||
allAnonymitySets,
|
||||
}) {
|
||||
// TODO allocate/create data structures required by the generated bindings
|
||||
final privateKeyPtr =
|
||||
privateKeyHex.to32BytesFromHex().unsignedCharPointer();
|
||||
|
||||
// some kind of failure
|
||||
return null;
|
||||
final recipientsPtr =
|
||||
malloc.allocate<CRecip>(sizeOf<CRecip>() * recipients.length);
|
||||
for (int i = 0; i < recipients.length; i++) {
|
||||
recipientsPtr[i].amount = recipients[i].amount;
|
||||
recipientsPtr[i].subtractFee =
|
||||
recipients[i].subtractFeeFromAmount ? 1 : 0;
|
||||
}
|
||||
|
||||
final privateRecipientsPtr = malloc.allocate<COutputRecipient>(
|
||||
sizeOf<COutputRecipient>() * recipients.length);
|
||||
for (int i = 0; i < recipients.length; i++) {
|
||||
privateRecipientsPtr[i].subtractFee =
|
||||
recipients[i].subtractFeeFromAmount ? 1 : 0;
|
||||
|
||||
privateRecipientsPtr[i].output =
|
||||
malloc.allocate<COutputCoinData>(sizeOf<COutputCoinData>());
|
||||
privateRecipientsPtr[i].output.ref.value = privateRecipients[i].amount;
|
||||
privateRecipientsPtr[i].output.ref.memo =
|
||||
privateRecipients[i].memo.toNativeUtf8().cast<Char>();
|
||||
privateRecipientsPtr[i].output.ref.address =
|
||||
privateRecipients[i].sparkAddress.toNativeUtf8().cast<Char>();
|
||||
}
|
||||
|
||||
final serializedMintMetasPtr = malloc.allocate<CCDataStream>(
|
||||
sizeOf<CCDataStream>() * serializedMintMetas.length);
|
||||
for (int i = 0; i < serializedMintMetas.length; i++) {
|
||||
serializedMintMetasPtr[i].data =
|
||||
serializedMintMetas[i].unsignedCharPointer();
|
||||
serializedMintMetasPtr[i].length = serializedMintMetas[i].length;
|
||||
}
|
||||
|
||||
final coverSetDataAllPtr = malloc.allocate<CCoverSetData>(
|
||||
sizeOf<CCoverSetData>() * allAnonymitySets.length);
|
||||
for (int i = 0; i < allAnonymitySets.length; i++) {
|
||||
coverSetDataAllPtr[i].setId = allAnonymitySets[i].setId;
|
||||
|
||||
coverSetDataAllPtr[i].cover_set = malloc.allocate<CCDataStream>(
|
||||
sizeOf<CCDataStream>() * allAnonymitySets[i].set.length);
|
||||
coverSetDataAllPtr[i].cover_setLength = allAnonymitySets[i].set.length;
|
||||
|
||||
for (int j = 0; j < allAnonymitySets[i].set.length; j++) {
|
||||
final b64CoinDecoded =
|
||||
base64Decode(allAnonymitySets[i].set[j].serializedCoin);
|
||||
coverSetDataAllPtr[i].cover_set[j].length = b64CoinDecoded.length;
|
||||
coverSetDataAllPtr[i].cover_set[j].data =
|
||||
b64CoinDecoded.unsignedCharPointer();
|
||||
}
|
||||
|
||||
final setHash = base64Decode(allAnonymitySets[i].setHash);
|
||||
coverSetDataAllPtr[i].cover_set_representation =
|
||||
setHash.unsignedCharPointer();
|
||||
coverSetDataAllPtr[i].cover_set_representationLength = setHash.length;
|
||||
}
|
||||
|
||||
final result = _bindings.cCreateSparkSpendTransaction(
|
||||
privateKeyPtr,
|
||||
index,
|
||||
recipientsPtr,
|
||||
recipients.length,
|
||||
privateRecipientsPtr,
|
||||
privateRecipients.length,
|
||||
serializedMintMetasPtr,
|
||||
serializedMintMetas.length,
|
||||
coverSetDataAllPtr,
|
||||
allAnonymitySets.length,
|
||||
);
|
||||
|
||||
// todo: more comprehensive frees
|
||||
malloc.free(privateKeyPtr);
|
||||
malloc.free(recipientsPtr);
|
||||
malloc.free(privateRecipientsPtr);
|
||||
malloc.free(serializedMintMetasPtr);
|
||||
malloc.free(coverSetDataAllPtr);
|
||||
|
||||
if (result.address == nullptr.address) {
|
||||
throw Exception(
|
||||
"createSparkSendTransaction() failed for an unknown reason",
|
||||
);
|
||||
}
|
||||
|
||||
final messageBytes = result.ref.data.toUint8List(result.ref.dataLength);
|
||||
final message = utf8.decode(messageBytes);
|
||||
malloc.free(result.ref.data);
|
||||
|
||||
if (result.ref.isError > 0) {
|
||||
throw Exception(message);
|
||||
}
|
||||
|
||||
final fee = result.ref.fee;
|
||||
|
||||
final List<Uint8List> scripts = [];
|
||||
for (int i = 0; i < result.ref.outputScriptsLength; i++) {
|
||||
final script = result.ref.outputScripts[i].bytes
|
||||
.toUint8List(result.ref.outputScripts[i].length);
|
||||
malloc.free(result.ref.outputScripts[i].bytes);
|
||||
scripts.add(script);
|
||||
}
|
||||
|
||||
malloc.free(result.ref.outputScripts);
|
||||
|
||||
return (serializedSpendPayload: message, fee: fee, outputScripts: scripts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,22 +136,17 @@ class FlutterLibsparkmobileBindings {
|
||||
/// FFI-friendly wrapper for spark::createSparkSpendTransaction.
|
||||
///
|
||||
/// createSparkSpendTransaction: https://github.com/firoorg/sparkmobile/blob/23099b0d9010a970ad75b9cfe05d568d634088f3/src/spark.cpp#L190
|
||||
ffi.Pointer<ffi.UnsignedChar> cCreateSparkSpendTransaction(
|
||||
ffi.Pointer<SparkSpendTransactionResult> cCreateSparkSpendTransaction(
|
||||
ffi.Pointer<ffi.UnsignedChar> keyData,
|
||||
int index,
|
||||
ffi.Pointer<CRecip> recipients,
|
||||
int recipientsLength,
|
||||
ffi.Pointer<COutputRecipient> privateRecipients,
|
||||
int privateRecipientsLength,
|
||||
ffi.Pointer<CCSparkMintMeta> coins,
|
||||
int coinsLength,
|
||||
ffi.Pointer<CCoverSets> cover_set_data_all,
|
||||
ffi.Pointer<CCDataStream> serializedMintMetas,
|
||||
int serializedMintMetasLength,
|
||||
ffi.Pointer<CCoverSetData> cover_set_data_all,
|
||||
int cover_set_data_allLength,
|
||||
ffi.Pointer<ffi.Char> txHashSig,
|
||||
int txHashSigLength,
|
||||
int fee,
|
||||
ffi.Pointer<OutputScript> outputScripts,
|
||||
int outputScriptsLength,
|
||||
) {
|
||||
return _cCreateSparkSpendTransaction(
|
||||
keyData,
|
||||
@@ -160,53 +155,38 @@ class FlutterLibsparkmobileBindings {
|
||||
recipientsLength,
|
||||
privateRecipients,
|
||||
privateRecipientsLength,
|
||||
coins,
|
||||
coinsLength,
|
||||
serializedMintMetas,
|
||||
serializedMintMetasLength,
|
||||
cover_set_data_all,
|
||||
cover_set_data_allLength,
|
||||
txHashSig,
|
||||
txHashSigLength,
|
||||
fee,
|
||||
outputScripts,
|
||||
outputScriptsLength,
|
||||
);
|
||||
}
|
||||
|
||||
late final _cCreateSparkSpendTransactionPtr = _lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<ffi.UnsignedChar> Function(
|
||||
ffi.Pointer<SparkSpendTransactionResult> Function(
|
||||
ffi.Pointer<ffi.UnsignedChar>,
|
||||
ffi.Int,
|
||||
ffi.Pointer<CRecip>,
|
||||
ffi.Int,
|
||||
ffi.Pointer<COutputRecipient>,
|
||||
ffi.Int,
|
||||
ffi.Pointer<CCSparkMintMeta>,
|
||||
ffi.Pointer<CCDataStream>,
|
||||
ffi.Int,
|
||||
ffi.Pointer<CCoverSets>,
|
||||
ffi.Int,
|
||||
ffi.Pointer<ffi.Char>,
|
||||
ffi.Int,
|
||||
ffi.Uint64,
|
||||
ffi.Pointer<OutputScript>,
|
||||
ffi.Pointer<CCoverSetData>,
|
||||
ffi.Int)>>('cCreateSparkSpendTransaction');
|
||||
late final _cCreateSparkSpendTransaction =
|
||||
_cCreateSparkSpendTransactionPtr.asFunction<
|
||||
ffi.Pointer<ffi.UnsignedChar> Function(
|
||||
ffi.Pointer<SparkSpendTransactionResult> Function(
|
||||
ffi.Pointer<ffi.UnsignedChar>,
|
||||
int,
|
||||
ffi.Pointer<CRecip>,
|
||||
int,
|
||||
ffi.Pointer<COutputRecipient>,
|
||||
int,
|
||||
ffi.Pointer<CCSparkMintMeta>,
|
||||
ffi.Pointer<CCDataStream>,
|
||||
int,
|
||||
ffi.Pointer<CCoverSets>,
|
||||
int,
|
||||
ffi.Pointer<ffi.Char>,
|
||||
int,
|
||||
int,
|
||||
ffi.Pointer<OutputScript>,
|
||||
ffi.Pointer<CCoverSetData>,
|
||||
int)>();
|
||||
}
|
||||
|
||||
@@ -337,75 +317,25 @@ final class COutputCoinData extends ffi.Struct {
|
||||
///
|
||||
/// See https://github.com/firoorg/sparkmobile/blob/23099b0d9010a970ad75b9cfe05d568d634088f3/src/spark.cpp#L195
|
||||
final class COutputRecipient extends ffi.Struct {
|
||||
external COutputCoinData output;
|
||||
external ffi.Pointer<COutputCoinData> output;
|
||||
|
||||
@ffi.Int()
|
||||
external int subtractFee;
|
||||
}
|
||||
|
||||
final class CCDataStream extends ffi.Struct {
|
||||
external ffi.Pointer<ffi.Char> data;
|
||||
external ffi.Pointer<ffi.UnsignedChar> data;
|
||||
|
||||
@ffi.Int()
|
||||
external int length;
|
||||
}
|
||||
|
||||
/// FFI-friendly wrapper for a spark::CSparkMintMeta.
|
||||
///
|
||||
/// CSparkMintMeta: https://github.com/firoorg/sparkmobile/blob/8bf17cd3deba6c3b0d10e89282e02936d7e71cdd/src/primitives.h#L9
|
||||
final class CCSparkMintMeta extends ffi.Struct {
|
||||
@ffi.Uint64()
|
||||
external int height;
|
||||
|
||||
external ffi.Pointer<ffi.Char> id;
|
||||
|
||||
@ffi.Int()
|
||||
external int isUsed;
|
||||
|
||||
external ffi.Pointer<ffi.Char> txid;
|
||||
|
||||
/// Diversifier.
|
||||
@ffi.Uint64()
|
||||
external int i;
|
||||
|
||||
/// Encrypted diversifier.
|
||||
external ffi.Pointer<ffi.UnsignedChar> d;
|
||||
|
||||
@ffi.Int()
|
||||
external int dLength;
|
||||
|
||||
/// Value.
|
||||
@ffi.Uint64()
|
||||
external int v;
|
||||
|
||||
/// Nonce.
|
||||
external ffi.Pointer<ffi.UnsignedChar> k;
|
||||
|
||||
@ffi.Int()
|
||||
external int kLength;
|
||||
|
||||
external ffi.Pointer<ffi.Char> memo;
|
||||
|
||||
@ffi.Int()
|
||||
external int memoLength;
|
||||
|
||||
external ffi.Pointer<ffi.UnsignedChar> serial_context;
|
||||
|
||||
@ffi.Int()
|
||||
external int serial_contextLength;
|
||||
|
||||
@ffi.Char()
|
||||
external int type;
|
||||
|
||||
external CCDataStream coin;
|
||||
}
|
||||
|
||||
/// FFI-friendly wrapper for a spark::CoverSetData.
|
||||
///
|
||||
/// CoverSetData: https://github.com/firoorg/sparkmobile/blob/8bf17cd3deba6c3b0d10e89282e02936d7e71cdd/src/spend_transaction.h#L28
|
||||
final class CCoverSetData extends ffi.Struct {
|
||||
/// vs. struct CCoin* cover_set;
|
||||
external ffi.Pointer<ffi.Pointer<CCDataStream>> cover_set;
|
||||
external ffi.Pointer<CCDataStream> cover_set;
|
||||
|
||||
@ffi.Int()
|
||||
external int cover_setLength;
|
||||
@@ -414,16 +344,9 @@ final class CCoverSetData extends ffi.Struct {
|
||||
|
||||
@ffi.Int()
|
||||
external int cover_set_representationLength;
|
||||
}
|
||||
|
||||
/// FFI-friendly wrapper for a std::unordered_map<uint64_t, spark::CoverSetData>.
|
||||
///
|
||||
/// See https://github.com/firoorg/sparkmobile/blob/23099b0d9010a970ad75b9cfe05d568d634088f3/src/spark.cpp#L197
|
||||
final class CCoverSets extends ffi.Struct {
|
||||
external ffi.Pointer<CCoverSetData> cover_sets;
|
||||
|
||||
@ffi.Int()
|
||||
external int cover_setsLength;
|
||||
external int setId;
|
||||
}
|
||||
|
||||
final class OutputScript extends ffi.Struct {
|
||||
@@ -465,3 +388,24 @@ final class AggregateCoinData extends ffi.Struct {
|
||||
@ffi.Int()
|
||||
external int nonceLength;
|
||||
}
|
||||
|
||||
/// Aggregate data structure to handle passing spark spend data across FFI.
|
||||
///
|
||||
/// Contains the serialized transaction or the error message if isError is true.
|
||||
final class SparkSpendTransactionResult extends ffi.Struct {
|
||||
external ffi.Pointer<ffi.UnsignedChar> data;
|
||||
|
||||
@ffi.Int()
|
||||
external int dataLength;
|
||||
|
||||
external ffi.Pointer<OutputScript> outputScripts;
|
||||
|
||||
@ffi.Int()
|
||||
external int outputScriptsLength;
|
||||
|
||||
@ffi.Int()
|
||||
external int fee;
|
||||
|
||||
@ffi.Int()
|
||||
external int isError;
|
||||
}
|
||||
|
||||
@@ -174,25 +174,17 @@ CCRecipientList* cCreateSparkMintRecipients(
|
||||
* createSparkSpendTransaction: https://github.com/firoorg/sparkmobile/blob/23099b0d9010a970ad75b9cfe05d568d634088f3/src/spark.cpp#L190
|
||||
*/
|
||||
FFI_PLUGIN_EXPORT
|
||||
unsigned char* cCreateSparkSpendTransaction(
|
||||
SparkSpendTransactionResult* cCreateSparkSpendTransaction(
|
||||
unsigned char* keyData,
|
||||
int index,
|
||||
struct CRecip* recipients, // This CRecip(ient) is not the same as a CRecipient.
|
||||
int recipientsLength,
|
||||
struct COutputRecipient* privateRecipients,
|
||||
int privateRecipientsLength,
|
||||
struct CCSparkMintMeta* coins,
|
||||
int coinsLength,
|
||||
struct CCoverSets* cover_set_data_all,
|
||||
int cover_set_data_allLength,
|
||||
// idAndBlockHashes_all is unused in spark::createSparkSpendTransaction so we ignore it here.
|
||||
const char* txHashSig, // A hex string.
|
||||
int txHashSigLength,
|
||||
uint64_t fee,
|
||||
// spark's createSparkSpendTransaction returns void, writing to the serializedSpend parameter.
|
||||
// We return it instead.
|
||||
const OutputScript* outputScripts,
|
||||
int outputScriptsLength
|
||||
struct CCDataStream* serializedMintMetas,
|
||||
int serializedMintMetasLength,
|
||||
struct CCoverSetData* cover_set_data_all,
|
||||
int cover_set_data_allLength
|
||||
) {
|
||||
try {
|
||||
// Derive the keys from the key data and index.
|
||||
@@ -209,66 +201,50 @@ unsigned char* cCreateSparkSpendTransaction(
|
||||
// Convert COutputRecipient* privateRecipients to std::vector<std::pair<spark::OutputCoinData, bool>> cppPrivateRecipients.
|
||||
std::vector<std::pair<spark::OutputCoinData, bool>> cppPrivateRecipients;
|
||||
for (int i = 0; i < privateRecipientsLength; i++) {
|
||||
cppPrivateRecipients.push_back(std::make_pair(fromFFI(privateRecipients[i].output), privateRecipients[i].subtractFee));
|
||||
spark::OutputCoinData outputCoinData;
|
||||
outputCoinData.memo = std::string(privateRecipients[i].output->memo);
|
||||
outputCoinData.v = (uint64_t)privateRecipients[i].output->value;
|
||||
std::string addrString = privateRecipients[i].output->address;
|
||||
outputCoinData.address = decodeAddress(addrString);
|
||||
cppPrivateRecipients.push_back(std::make_pair(outputCoinData, privateRecipients[i].subtractFee));
|
||||
}
|
||||
|
||||
// Convert CCSparkMintMeta* coins to std::list<CSparkMintMeta> cppCoins.
|
||||
// Convert CCSparkMintMeta* serializedMintMetas to std::list<CSparkMintMeta> cppCoins.
|
||||
std::list<CSparkMintMeta> cppCoins;
|
||||
for (int i = 0; i < coinsLength; i++) {
|
||||
cppCoins.push_back(fromFFI(coins[i]));
|
||||
for (int i = 0; i < serializedMintMetasLength; i++) {
|
||||
std::vector<unsigned char> vec(serializedMintMetas[i].data, serializedMintMetas[i].data + serializedMintMetas[i].length);
|
||||
CDataStream stream(vec, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CSparkMintMeta meta;
|
||||
stream >> meta;
|
||||
cppCoins.push_back(meta);
|
||||
}
|
||||
|
||||
// Convert CCoverSets* cover_set_data_all to a std::unordered_map<uint64_t, spark::CoverSetData> cppCoverSetDataAll
|
||||
// TODO verify correctness.
|
||||
std::unordered_map<uint64_t, spark::CoverSetData> cppCoverSetDataAll;
|
||||
for (int i = 0; i < cover_set_data_allLength; i++) {
|
||||
for (int j = 0; j < cover_set_data_all[i].cover_setsLength; j++) {
|
||||
// Convert CCoverSetData to vector of Coins.
|
||||
for (int j = 0; j < cover_set_data_all[i].cover_setLength; j++) {
|
||||
std::vector<spark::Coin> cppCoverSetCoins;
|
||||
spark::Coin coin = fromFFI(*cover_set_data_all[i].cover_sets[j].cover_set[0]);
|
||||
spark::Coin coin = fromFFI(cover_set_data_all[i].cover_set[j]);
|
||||
cppCoverSetCoins.push_back(coin);
|
||||
|
||||
// Convert CCoverSetData to vector of vector of unsigned chars.
|
||||
std::vector<CCoverSetData> coverSets(cover_set_data_all[i].cover_sets, cover_set_data_all[i].cover_sets + cover_set_data_all[i].cover_setsLength);
|
||||
|
||||
// Combine all the cover set representations into one vector.
|
||||
std::vector<unsigned char> coverSetReps;
|
||||
for (int k = 0; k < cover_set_data_all[i].cover_setsLength; k++) {
|
||||
for (int l = 0; l < cover_set_data_all[i].cover_sets[k].cover_set_representationLength; l++) {
|
||||
coverSetReps.push_back(cover_set_data_all[i].cover_sets[k].cover_set_representation[l]);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct spark::CoverSetData.
|
||||
spark::CoverSetData cppCoverSetData;
|
||||
cppCoverSetData.cover_set = cppCoverSetCoins;
|
||||
cppCoverSetData.cover_set_representation = coverSetReps;
|
||||
cppCoverSetData.cover_set_representation = std::vector<unsigned char>(cover_set_data_all[i].cover_set_representation, cover_set_data_all[i].cover_set_representation + cover_set_data_all[i].cover_set_representationLength);
|
||||
|
||||
cppCoverSetDataAll[cover_set_data_all[i].cover_sets[j].cover_setLength] = cppCoverSetData;
|
||||
cppCoverSetDataAll[cover_set_data_all[i].setId] = cppCoverSetData;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert const char * txHashSig to a uint256 cppTxHashSig.
|
||||
// uint256 cppTxHashSig(txHashSig); // This throws `error: no matching function for call to ‘uint256::uint256(const char*&)’`, we need to:
|
||||
uint256 cppTxHashSig;
|
||||
cppTxHashSig.SetHex(txHashSig);
|
||||
|
||||
// Make a CAmount cppFee from fee.
|
||||
CAmount cppFee = fee;
|
||||
|
||||
// Make a dummy for idAndBlockHashes_all.
|
||||
// Required but unused params.
|
||||
std::map<uint64_t, uint256> cppIdAndBlockHashesAll;
|
||||
uint256 cppTxHashSig;
|
||||
|
||||
// Make a placeholder for serializedSpend.
|
||||
// Output data
|
||||
std::vector<uint8_t> cppSerializedSpend;
|
||||
|
||||
// Convert outputScripts to std::vector<std::vector<unsigned char>> cppOutputScripts.
|
||||
CAmount cppFee;
|
||||
std::vector<std::vector<unsigned char>> cppOutputScripts;
|
||||
for (int i = 0; i < outputScriptsLength; i++) {
|
||||
for (int j = 0; j < outputScripts[i].length; j++) {
|
||||
cppOutputScripts[i].push_back(outputScripts[i].bytes[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// Call spark::createSparkSpendTransaction.
|
||||
createSparkSpendTransaction(
|
||||
@@ -286,18 +262,32 @@ unsigned char* cCreateSparkSpendTransaction(
|
||||
cppOutputScripts
|
||||
);
|
||||
|
||||
// Allocate memory for the C-style string.
|
||||
unsigned char* cstr = new unsigned char[cppSerializedSpend.size()];
|
||||
SparkSpendTransactionResult *result = (SparkSpendTransactionResult*)malloc(sizeof(SparkSpendTransactionResult));
|
||||
result->isError = false;
|
||||
result->fee = cppFee;
|
||||
|
||||
// Copy the data from the vector to the array.
|
||||
for (int i = 0; i < cppSerializedSpend.size(); i++) {
|
||||
cstr[i] = cppSerializedSpend[i];
|
||||
result->outputScriptsLength = cppOutputScripts.size();
|
||||
result->outputScripts = (OutputScript*)malloc(sizeof(OutputScript) * result->outputScriptsLength);
|
||||
for (int i = 0; i < result->outputScriptsLength; i++) {
|
||||
result->outputScripts[i].length = cppOutputScripts[i].size();
|
||||
result->outputScripts[i].bytes = (unsigned char*)malloc(result->outputScripts[i].length);
|
||||
memcpy(result->outputScripts[i].bytes, cppOutputScripts[i].data(), result->outputScripts[i].length);
|
||||
}
|
||||
|
||||
// Return the array.
|
||||
return cstr;
|
||||
result->dataLength = cppSerializedSpend.size();
|
||||
result->data = (unsigned char*)malloc(result->dataLength);
|
||||
memcpy(result->data, cppSerializedSpend.data(), result->dataLength);
|
||||
|
||||
return result;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return nullptr;
|
||||
|
||||
SparkSpendTransactionResult *result = (SparkSpendTransactionResult*)malloc(sizeof(SparkSpendTransactionResult));
|
||||
result->isError = true;
|
||||
result->dataLength = strlen(e.what());
|
||||
result->data = (unsigned char*)malloc(sizeof(unsigned char) * result->dataLength);
|
||||
memcpy(result->data, e.what(), result->dataLength);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,22 +62,17 @@ struct CCRecipientList* cCreateSparkMintRecipients(
|
||||
* createSparkSpendTransaction: https://github.com/firoorg/sparkmobile/blob/23099b0d9010a970ad75b9cfe05d568d634088f3/src/spark.cpp#L190
|
||||
*/
|
||||
FFI_PLUGIN_EXPORT
|
||||
unsigned char* cCreateSparkSpendTransaction(
|
||||
struct SparkSpendTransactionResult* cCreateSparkSpendTransaction(
|
||||
unsigned char* keyData,
|
||||
int index,
|
||||
struct CRecip* recipients,
|
||||
struct CRecip* recipients, // This CRecip(ient) is not the same as a CRecipient.
|
||||
int recipientsLength,
|
||||
struct COutputRecipient* privateRecipients,
|
||||
int privateRecipientsLength,
|
||||
struct CCSparkMintMeta* coins,
|
||||
int coinsLength,
|
||||
struct CCoverSets* cover_set_data_all,
|
||||
int cover_set_data_allLength,
|
||||
const char* txHashSig,
|
||||
int txHashSigLength,
|
||||
uint64_t fee,
|
||||
const struct OutputScript* outputScripts,
|
||||
int outputScriptsLength
|
||||
struct CCDataStream* serializedMintMetas,
|
||||
int serializedMintMetasLength,
|
||||
struct CCoverSetData* cover_set_data_all,
|
||||
int cover_set_data_allLength
|
||||
);
|
||||
|
||||
#endif //ORG_FIRO_SPARK_DART_INTERFACE_H
|
||||
|
||||
@@ -105,12 +105,12 @@ struct COutputCoinData {
|
||||
* See https://github.com/firoorg/sparkmobile/blob/23099b0d9010a970ad75b9cfe05d568d634088f3/src/spark.cpp#L195
|
||||
*/
|
||||
struct COutputRecipient {
|
||||
struct COutputCoinData output;
|
||||
struct COutputCoinData* output;
|
||||
int subtractFee;
|
||||
};
|
||||
|
||||
struct CCDataStream {
|
||||
const char *data;
|
||||
unsigned char *data;
|
||||
int length;
|
||||
};
|
||||
|
||||
@@ -119,24 +119,24 @@ struct CCDataStream {
|
||||
*
|
||||
* CSparkMintMeta: https://github.com/firoorg/sparkmobile/blob/8bf17cd3deba6c3b0d10e89282e02936d7e71cdd/src/primitives.h#L9
|
||||
*/
|
||||
struct CCSparkMintMeta {
|
||||
uint64_t height;
|
||||
const char *id;
|
||||
int isUsed;
|
||||
const char *txid;
|
||||
uint64_t i; // Diversifier.
|
||||
const unsigned char *d; // Encrypted diversifier.
|
||||
int dLength;
|
||||
uint64_t v; // Value.
|
||||
const unsigned char *k; // Nonce.
|
||||
int kLength;
|
||||
const char *memo;
|
||||
int memoLength;
|
||||
unsigned char *serial_context;
|
||||
int serial_contextLength;
|
||||
char type;
|
||||
struct CCDataStream coin;
|
||||
|
||||
//struct CCSparkMintMeta {
|
||||
// uint64_t height;
|
||||
// const char *id;
|
||||
// int isUsed;
|
||||
// const char *txid;
|
||||
// uint64_t i; // Diversifier.
|
||||
// const unsigned char *d; // Encrypted diversifier.
|
||||
// int dLength;
|
||||
// uint64_t v; // Value.
|
||||
// const unsigned char *k; // Nonce.
|
||||
// int kLength;
|
||||
// const char *memo;
|
||||
// int memoLength;
|
||||
// unsigned char *serial_context;
|
||||
// int serial_contextLength;
|
||||
// char type;
|
||||
// struct CCDataStream coin;
|
||||
//
|
||||
// CCSparkMintMeta(uint64_t height, const char *id, int isUsed,
|
||||
// const char *txid, uint64_t i, const unsigned char *d,
|
||||
// int dLength, uint64_t v, const unsigned char *k,
|
||||
@@ -145,7 +145,7 @@ struct CCSparkMintMeta {
|
||||
// char type, const CCDataStream &coinData);
|
||||
//
|
||||
// ~CCSparkMintMeta();
|
||||
};
|
||||
//};
|
||||
|
||||
/*
|
||||
* FFI-friendly wrapper for a spark::CoverSetData.
|
||||
@@ -153,21 +153,15 @@ struct CCSparkMintMeta {
|
||||
* CoverSetData: https://github.com/firoorg/sparkmobile/blob/8bf17cd3deba6c3b0d10e89282e02936d7e71cdd/src/spend_transaction.h#L28
|
||||
*/
|
||||
struct CCoverSetData {
|
||||
struct CCDataStream **cover_set; // vs. struct CCoin* cover_set;
|
||||
struct CCDataStream *cover_set; // vs. struct CCoin* cover_set;
|
||||
int cover_setLength;
|
||||
const unsigned char *cover_set_representation;
|
||||
int cover_set_representationLength;
|
||||
|
||||
int setId;
|
||||
};
|
||||
|
||||
/*
|
||||
* FFI-friendly wrapper for a std::unordered_map<uint64_t, spark::CoverSetData>.
|
||||
*
|
||||
* See https://github.com/firoorg/sparkmobile/blob/23099b0d9010a970ad75b9cfe05d568d634088f3/src/spark.cpp#L197
|
||||
*/
|
||||
struct CCoverSets {
|
||||
struct CCoverSetData* cover_sets;
|
||||
int cover_setsLength;
|
||||
};
|
||||
|
||||
|
||||
struct OutputScript {
|
||||
unsigned char *bytes;
|
||||
@@ -195,19 +189,22 @@ struct AggregateCoinData {
|
||||
int nonceLength;
|
||||
};
|
||||
|
||||
/*
|
||||
* Aggregate data structure to handle passing spark spend data across FFI.
|
||||
*
|
||||
* Contains the serialized transaction or the error message if isError is true.
|
||||
*/
|
||||
struct SparkSpendTransactionResult {
|
||||
unsigned char *data;
|
||||
int dataLength;
|
||||
|
||||
//struct IdentifiedCoinData {
|
||||
// uint64_t i; // diversifier
|
||||
// std::vector<unsigned char> d; // encrypted diversifier
|
||||
// uint64_t v; // value
|
||||
// Scalar k; // nonce
|
||||
// std::string memo; // memo
|
||||
//};
|
||||
//
|
||||
//struct RecoveredCoinData {
|
||||
// Scalar s; // serial
|
||||
// GroupElement T; // tag
|
||||
//};
|
||||
struct OutputScript* outputScripts;
|
||||
int outputScriptsLength;
|
||||
|
||||
int fee;
|
||||
|
||||
int isError;
|
||||
};
|
||||
|
||||
//#ifdef __cplusplus
|
||||
//}
|
||||
|
||||
371
src/utils.cpp
371
src/utils.cpp
@@ -64,27 +64,12 @@ spark::Coin fromFFI(const CCoin& c_struct) {
|
||||
|
||||
spark::Coin fromFFI(CCDataStream& cdStream) {
|
||||
spark::Coin coin;
|
||||
CDataStream coinStream(cdStream.data, &cdStream.data[cdStream.length - 1], SER_NETWORK, PROTOCOL_VERSION);
|
||||
std::vector<unsigned char> vec(cdStream.data, cdStream.data + cdStream.length);
|
||||
CDataStream coinStream(vec, SER_NETWORK, PROTOCOL_VERSION);
|
||||
coinStream >> coin;
|
||||
return coin;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Utility function to convert a C++ Coin struct to an FFI-friendly C CCDataStream struct.
|
||||
*/
|
||||
CCDataStream toFFI(const spark::Coin& coin) {
|
||||
// Serialize the Coin object into a CDataStream
|
||||
CDataStream ccoinStream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ccoinStream << coin;
|
||||
|
||||
CCDataStream ccStream;
|
||||
ccStream.data = ccoinStream.data();
|
||||
ccStream.length = ccoinStream.size();
|
||||
|
||||
return ccStream;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to convert a C++ IdentifiedCoinData struct to an FFI-friendly struct.
|
||||
*/
|
||||
@@ -355,27 +340,27 @@ CSparkMintMeta createCSparkMintMeta(
|
||||
/*
|
||||
* Utility function to convert a C++ CSparkMintMeta struct to an FFI-friendly C CCSparkMintMeta.
|
||||
*/
|
||||
CSparkMintMeta fromFFI(const CCSparkMintMeta& c_struct) {
|
||||
CSparkMintMeta cpp_struct;
|
||||
cpp_struct.nHeight = c_struct.height;
|
||||
cpp_struct.nId = std::stoull(c_struct.id);
|
||||
cpp_struct.isUsed = c_struct.isUsed;
|
||||
cpp_struct.txid = uint256S(c_struct.txid);
|
||||
cpp_struct.i = c_struct.i;
|
||||
cpp_struct.d = std::vector<unsigned char>(c_struct.d, c_struct.d + c_struct.dLength);
|
||||
cpp_struct.v = c_struct.v;
|
||||
cpp_struct.k = bytesToScalar(c_struct.k, c_struct.kLength);
|
||||
cpp_struct.memo = std::string(c_struct.memo);
|
||||
cpp_struct.serial_context = std::vector<unsigned char>(c_struct.serial_context,
|
||||
c_struct.serial_context +
|
||||
c_struct.serial_contextLength);
|
||||
cpp_struct.type = c_struct.type;
|
||||
// c_struct.coin is a const, but we need a non-const reference to pass to fromFFI.
|
||||
// Convert c_struct.coin to a non-const.
|
||||
CCDataStream coin = c_struct.coin;
|
||||
cpp_struct.coin = fromFFI(coin);
|
||||
return cpp_struct;
|
||||
}
|
||||
//CSparkMintMeta fromFFI(const CCSparkMintMeta& c_struct) {
|
||||
// CSparkMintMeta cpp_struct;
|
||||
// cpp_struct.nHeight = c_struct.height;
|
||||
// cpp_struct.nId = std::stoull(c_struct.id);
|
||||
// cpp_struct.isUsed = c_struct.isUsed;
|
||||
// cpp_struct.txid = uint256S(c_struct.txid);
|
||||
// cpp_struct.i = c_struct.i;
|
||||
// cpp_struct.d = std::vector<unsigned char>(c_struct.d, c_struct.d + c_struct.dLength);
|
||||
// cpp_struct.v = c_struct.v;
|
||||
// cpp_struct.k = bytesToScalar(c_struct.k, c_struct.kLength);
|
||||
// cpp_struct.memo = std::string(c_struct.memo);
|
||||
// cpp_struct.serial_context = std::vector<unsigned char>(c_struct.serial_context,
|
||||
// c_struct.serial_context +
|
||||
// c_struct.serial_contextLength);
|
||||
// cpp_struct.type = c_struct.type;
|
||||
// // c_struct.coin is a const, but we need a non-const reference to pass to fromFFI.
|
||||
// // Convert c_struct.coin to a non-const.
|
||||
// CCDataStream coin = c_struct.coin;
|
||||
// cpp_struct.coin = fromFFI(coin);
|
||||
// return cpp_struct;
|
||||
//}
|
||||
|
||||
///*
|
||||
// * CCSparkMintMeta constructor.
|
||||
@@ -409,161 +394,161 @@ CSparkMintMeta fromFFI(const CCSparkMintMeta& c_struct) {
|
||||
// free(const_cast<char*>(memo));
|
||||
// delete[] serial_context;
|
||||
//}
|
||||
|
||||
/*
|
||||
* CCSparkMintMeta factory.
|
||||
*
|
||||
* A CSparkMintMeta is a struct that contains a height, id, isUsed, txid, diversifier, encrypted
|
||||
* diversifier, value, nonce, memo, serial context, type, and coin. We accept these as a
|
||||
* CCSparkMintMeta from the Dart interface, and convert them to a C++ CSparkMintMeta struct.
|
||||
*/
|
||||
CCSparkMintMeta createCCSparkMintMeta(const uint64_t height, const uint64_t id, const int isUsed, const char* txid, const uint64_t diversifier, const char* encryptedDiversifier, const uint64_t value, const char* nonce, const char* memo, const unsigned char* serial_context, const int serial_contextLength, const char type, const CCoin coin) {
|
||||
// Create a string version of the id
|
||||
std::string idStr = std::to_string(id);
|
||||
const char* idCStr = idStr.c_str();
|
||||
|
||||
// Convert encryptedDiversifier and nonce to unsigned char*
|
||||
auto encryptedDiversifierCStr = reinterpret_cast<const unsigned char*>(encryptedDiversifier);
|
||||
auto nonceCStr = reinterpret_cast<const unsigned char*>(nonce);
|
||||
|
||||
// Convert coin to CDataStream
|
||||
spark::Coin coinStruct = fromFFI(coin);
|
||||
CCDataStream coinStream = toFFI(coinStruct);
|
||||
|
||||
CCSparkMintMeta meta;
|
||||
|
||||
meta.height = height;
|
||||
meta.id = idCStr;
|
||||
meta.isUsed = isUsed;
|
||||
meta.txid = txid;
|
||||
meta.i = diversifier;
|
||||
meta.d = encryptedDiversifierCStr;
|
||||
meta.dLength = std::strlen(encryptedDiversifier);
|
||||
meta.v = value;
|
||||
meta.k = nonceCStr;
|
||||
meta.kLength = std::strlen(nonce);
|
||||
meta.memo = memo;
|
||||
meta.memoLength = std::strlen(memo);
|
||||
meta.serial_context = const_cast<unsigned char*>(serial_context);
|
||||
meta.serial_contextLength = serial_contextLength;
|
||||
meta.type = type;
|
||||
meta.coin = coinStream;
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to convert an FFI-friendly C CCSparkMintMeta struct to a C++ CSparkMintMeta.
|
||||
*/
|
||||
CCSparkMintMeta toFFI(const CSparkMintMeta& cpp_struct) {
|
||||
// Convert the id, txid, d, k, memo, and serial_context to appropriate types
|
||||
std::string idStr = std::to_string(cpp_struct.nId);
|
||||
const char* idCStr = idStr.c_str();
|
||||
|
||||
CCDataStream coinStream = toFFI(cpp_struct.coin);
|
||||
|
||||
std::vector<unsigned char> scalarBytes(32);
|
||||
cpp_struct.k.serialize(scalarBytes.data());
|
||||
|
||||
CCSparkMintMeta meta;
|
||||
|
||||
meta.height = cpp_struct.nHeight;
|
||||
meta.id = idCStr;
|
||||
meta.isUsed = cpp_struct.isUsed;
|
||||
meta.txid = cpp_struct.txid.ToString().c_str();
|
||||
meta.i = cpp_struct.i;
|
||||
meta.d = copyBytes(cpp_struct.d.data(), cpp_struct.d.size());
|
||||
meta.dLength = cpp_struct.d.size();
|
||||
meta.v = cpp_struct.v;
|
||||
meta.k = copyBytes(scalarBytes.data(), scalarBytes.size());
|
||||
meta.kLength = 32;
|
||||
meta.memo = strdup(cpp_struct.memo.c_str());
|
||||
meta.memoLength = cpp_struct.memo.size();
|
||||
meta.serial_context = copyBytes(cpp_struct.serial_context.data(), cpp_struct.serial_context.size());
|
||||
meta.serial_contextLength = cpp_struct.serial_context.size();
|
||||
meta.type = cpp_struct.type;
|
||||
meta.coin = coinStream;
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
/*
|
||||
* CoverSetData factory.
|
||||
*/
|
||||
spark::CoverSetData createCoverSetData(
|
||||
const std::vector<spark::Coin>& cover_set,
|
||||
const std::vector<unsigned char>& cover_set_representations
|
||||
) {
|
||||
spark::CoverSetData coverSetData;
|
||||
coverSetData.cover_set = cover_set;
|
||||
coverSetData.cover_set_representation = cover_set_representations;
|
||||
return coverSetData;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to convert an FFI-friendly C CCoverSetData struct to a C++ CoverSetData.
|
||||
*/
|
||||
spark::CoverSetData fromFFI(const CCoverSetData& c_struct) {
|
||||
std::vector<spark::Coin> cover_set;
|
||||
|
||||
for (int i = 0; i < c_struct.cover_setLength; i++) {
|
||||
spark::Coin coin;
|
||||
CDataStream coinStream(
|
||||
*c_struct.cover_set[i]->data,
|
||||
c_struct.cover_set[i]->data[c_struct.cover_set[i]->length - 1],
|
||||
SER_NETWORK, PROTOCOL_VERSION);
|
||||
coinStream >> coin;
|
||||
cover_set.emplace_back(coin);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> cover_set_representation(c_struct.cover_set_representation, c_struct.cover_set_representation + c_struct.cover_set_representationLength);
|
||||
|
||||
return createCoverSetData(cover_set, cover_set_representation);
|
||||
}
|
||||
|
||||
/*
|
||||
* CCoverSetData factory.
|
||||
*/
|
||||
CCoverSetData createCCoverSetData(const CCoin* cover_set,
|
||||
const unsigned char* cover_set_representation,
|
||||
const int cover_set_representationLength) {
|
||||
std::vector<CCDataStream> cover_set_streams;
|
||||
|
||||
for (int i = 0; i < cover_set_representationLength; i++) {
|
||||
// Convert CCoin to Coin.
|
||||
spark::Coin coin = fromFFI(cover_set[i]);
|
||||
|
||||
// Serialize Coin.
|
||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
stream << coin;
|
||||
|
||||
|
||||
CCDataStream ccStream;
|
||||
ccStream.data = stream.data();
|
||||
ccStream.length = stream.size();
|
||||
|
||||
// Add stream to vector.
|
||||
cover_set_streams.push_back(ccStream);
|
||||
}
|
||||
|
||||
// Create array containing the address of cover_set_streams
|
||||
CCDataStream** cover_set_streams_pp = new CCDataStream*[cover_set_representationLength];
|
||||
|
||||
for (int i = 0; i < cover_set_representationLength; i++) {
|
||||
cover_set_streams_pp[i] = &cover_set_streams[i];
|
||||
}
|
||||
|
||||
// Create the CCoverSetData and set the cover_set.
|
||||
CCoverSetData c_struct;
|
||||
|
||||
// Assign the pointer to pointer
|
||||
c_struct.cover_set = cover_set_streams_pp;
|
||||
|
||||
// Assign the cover_set_representation.
|
||||
c_struct.cover_set_representation = cover_set_representation;
|
||||
c_struct.cover_set_representationLength = cover_set_representationLength;
|
||||
return c_struct;
|
||||
}
|
||||
//
|
||||
///*
|
||||
// * CCSparkMintMeta factory.
|
||||
// *
|
||||
// * A CSparkMintMeta is a struct that contains a height, id, isUsed, txid, diversifier, encrypted
|
||||
// * diversifier, value, nonce, memo, serial context, type, and coin. We accept these as a
|
||||
// * CCSparkMintMeta from the Dart interface, and convert them to a C++ CSparkMintMeta struct.
|
||||
// */
|
||||
//CCSparkMintMeta createCCSparkMintMeta(const uint64_t height, const uint64_t id, const int isUsed, const char* txid, const uint64_t diversifier, const char* encryptedDiversifier, const uint64_t value, const char* nonce, const char* memo, const unsigned char* serial_context, const int serial_contextLength, const char type, const CCoin coin) {
|
||||
// // Create a string version of the id
|
||||
// std::string idStr = std::to_string(id);
|
||||
// const char* idCStr = idStr.c_str();
|
||||
//
|
||||
// // Convert encryptedDiversifier and nonce to unsigned char*
|
||||
// auto encryptedDiversifierCStr = reinterpret_cast<const unsigned char*>(encryptedDiversifier);
|
||||
// auto nonceCStr = reinterpret_cast<const unsigned char*>(nonce);
|
||||
//
|
||||
// // Convert coin to CDataStream
|
||||
// spark::Coin coinStruct = fromFFI(coin);
|
||||
// CCDataStream coinStream = toFFI(coinStruct);
|
||||
//
|
||||
// CCSparkMintMeta meta;
|
||||
//
|
||||
// meta.height = height;
|
||||
// meta.id = idCStr;
|
||||
// meta.isUsed = isUsed;
|
||||
// meta.txid = txid;
|
||||
// meta.i = diversifier;
|
||||
// meta.d = encryptedDiversifierCStr;
|
||||
// meta.dLength = std::strlen(encryptedDiversifier);
|
||||
// meta.v = value;
|
||||
// meta.k = nonceCStr;
|
||||
// meta.kLength = std::strlen(nonce);
|
||||
// meta.memo = memo;
|
||||
// meta.memoLength = std::strlen(memo);
|
||||
// meta.serial_context = const_cast<unsigned char*>(serial_context);
|
||||
// meta.serial_contextLength = serial_contextLength;
|
||||
// meta.type = type;
|
||||
// meta.coin = coinStream;
|
||||
//
|
||||
// return meta;
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Utility function to convert an FFI-friendly C CCSparkMintMeta struct to a C++ CSparkMintMeta.
|
||||
// */
|
||||
//CCSparkMintMeta toFFI(const CSparkMintMeta& cpp_struct) {
|
||||
// // Convert the id, txid, d, k, memo, and serial_context to appropriate types
|
||||
// std::string idStr = std::to_string(cpp_struct.nId);
|
||||
// const char* idCStr = idStr.c_str();
|
||||
//
|
||||
// CCDataStream coinStream = toFFI(cpp_struct.coin);
|
||||
//
|
||||
// std::vector<unsigned char> scalarBytes(32);
|
||||
// cpp_struct.k.serialize(scalarBytes.data());
|
||||
//
|
||||
// CCSparkMintMeta meta;
|
||||
//
|
||||
// meta.height = cpp_struct.nHeight;
|
||||
// meta.id = idCStr;
|
||||
// meta.isUsed = cpp_struct.isUsed;
|
||||
// meta.txid = cpp_struct.txid.ToString().c_str();
|
||||
// meta.i = cpp_struct.i;
|
||||
// meta.d = copyBytes(cpp_struct.d.data(), cpp_struct.d.size());
|
||||
// meta.dLength = cpp_struct.d.size();
|
||||
// meta.v = cpp_struct.v;
|
||||
// meta.k = copyBytes(scalarBytes.data(), scalarBytes.size());
|
||||
// meta.kLength = 32;
|
||||
// meta.memo = strdup(cpp_struct.memo.c_str());
|
||||
// meta.memoLength = cpp_struct.memo.size();
|
||||
// meta.serial_context = copyBytes(cpp_struct.serial_context.data(), cpp_struct.serial_context.size());
|
||||
// meta.serial_contextLength = cpp_struct.serial_context.size();
|
||||
// meta.type = cpp_struct.type;
|
||||
// meta.coin = coinStream;
|
||||
//
|
||||
// return meta;
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * CoverSetData factory.
|
||||
// */
|
||||
//spark::CoverSetData createCoverSetData(
|
||||
// const std::vector<spark::Coin>& cover_set,
|
||||
// const std::vector<unsigned char>& cover_set_representations
|
||||
//) {
|
||||
// spark::CoverSetData coverSetData;
|
||||
// coverSetData.cover_set = cover_set;
|
||||
// coverSetData.cover_set_representation = cover_set_representations;
|
||||
// return coverSetData;
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * Utility function to convert an FFI-friendly C CCoverSetData struct to a C++ CoverSetData.
|
||||
// */
|
||||
//spark::CoverSetData fromFFI(const CCoverSetData& c_struct) {
|
||||
// std::vector<spark::Coin> cover_set;
|
||||
//
|
||||
// for (int i = 0; i < c_struct.cover_setLength; i++) {
|
||||
// spark::Coin coin = fromFFI(c_struct.cover_set[i].data)
|
||||
// CDataStream coinStream(
|
||||
// *c_struct.cover_set[i]->data,
|
||||
// c_struct.cover_set[i]->data[c_struct.cover_set[i]->length - 1],
|
||||
// SER_NETWORK, PROTOCOL_VERSION);
|
||||
// coinStream >> coin;
|
||||
// cover_set.emplace_back(coin);
|
||||
// }
|
||||
//
|
||||
// std::vector<unsigned char> cover_set_representation(c_struct.cover_set_representation, c_struct.cover_set_representation + c_struct.cover_set_representationLength);
|
||||
//
|
||||
// return createCoverSetData(cover_set, cover_set_representation);
|
||||
//}
|
||||
//
|
||||
///*
|
||||
// * CCoverSetData factory.
|
||||
// */
|
||||
//CCoverSetData createCCoverSetData(const CCoin* cover_set,
|
||||
// const unsigned char* cover_set_representation,
|
||||
// const int cover_set_representationLength) {
|
||||
// std::vector<CCDataStream> cover_set_streams;
|
||||
//
|
||||
// for (int i = 0; i < cover_set_representationLength; i++) {
|
||||
// // Convert CCoin to Coin.
|
||||
// spark::Coin coin = fromFFI(cover_set[i]);
|
||||
//
|
||||
// // Serialize Coin.
|
||||
// CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
// stream << coin;
|
||||
//
|
||||
//
|
||||
// CCDataStream ccStream;
|
||||
// ccStream.data = stream.data();
|
||||
// ccStream.length = stream.size();
|
||||
//
|
||||
// // Add stream to vector.
|
||||
// cover_set_streams.push_back(ccStream);
|
||||
// }
|
||||
//
|
||||
// // Create array containing the address of cover_set_streams
|
||||
// CCDataStream** cover_set_streams_pp = new CCDataStream*[cover_set_representationLength];
|
||||
//
|
||||
// for (int i = 0; i < cover_set_representationLength; i++) {
|
||||
// cover_set_streams_pp[i] = &cover_set_streams[i];
|
||||
// }
|
||||
//
|
||||
// // Create the CCoverSetData and set the cover_set.
|
||||
// CCoverSetData c_struct;
|
||||
//
|
||||
// // Assign the pointer to pointer
|
||||
// c_struct.cover_set = cover_set_streams_pp;
|
||||
//
|
||||
// // Assign the cover_set_representation.
|
||||
// c_struct.cover_set_representation = cover_set_representation;
|
||||
// c_struct.cover_set_representationLength = cover_set_representationLength;
|
||||
// return c_struct;
|
||||
//}
|
||||
|
||||
/*
|
||||
* Utility function to convert a C++ CoverSetData struct to an FFI-friendly CCoverSetData.
|
||||
|
||||
24
src/utils.h
24
src/utils.h
@@ -17,8 +17,6 @@ spark::Coin fromFFI(CCDataStream& coinStream);
|
||||
|
||||
CCoin createCCoin(char type, const unsigned char* k, int kLength, const char* address, uint64_t v, const unsigned char* memo, int memoLength, const unsigned char* serial_context, int serial_contextLength);
|
||||
|
||||
CCDataStream toFFI(const spark::Coin& cpp_struct);
|
||||
|
||||
spark::IdentifiedCoinData fromFFI(const CIdentifiedCoinData& c_struct);
|
||||
|
||||
CIdentifiedCoinData toFFI(const spark::IdentifiedCoinData& cpp_struct);
|
||||
@@ -53,19 +51,19 @@ COutputCoinData createCOutputCoinData(const char* address, uint64_t value, const
|
||||
|
||||
COutputCoinData toFFI(const spark::OutputCoinData& cpp_struct, int isTestNet);
|
||||
|
||||
CSparkMintMeta createCSparkMintMeta(const uint64_t height, const uint64_t id, const int isUsed, const char* txid, const uint64_t diversifier, const char* encryptedDiversifier, const uint64_t value, const char* nonce, const char* memo, const unsigned char* serialContext, const int serialContextLength, const char type, const CCoin coin);
|
||||
//CSparkMintMeta createCSparkMintMeta(const uint64_t height, const uint64_t id, const int isUsed, const char* txid, const uint64_t diversifier, const char* encryptedDiversifier, const uint64_t value, const char* nonce, const char* memo, const unsigned char* serialContext, const int serialContextLength, const char type, const CCoin coin);
|
||||
//
|
||||
//CSparkMintMeta fromFFI(const CCSparkMintMeta& c_struct);
|
||||
|
||||
CSparkMintMeta fromFFI(const CCSparkMintMeta& c_struct);
|
||||
//CCSparkMintMeta createCCSparkMintMeta(const uint64_t height, const uint64_t id, const int isUsed, const char* txid, const uint64_t diversifier, const char* encryptedDiversifier, const uint64_t value, const char* nonce, const char* memo, const unsigned char* serialContext, const int serialContextLength, const char type, const CCoin coin);
|
||||
//
|
||||
//CCSparkMintMeta toFFI(const CSparkMintMeta& cpp_struct);
|
||||
|
||||
CCSparkMintMeta createCCSparkMintMeta(const uint64_t height, const uint64_t id, const int isUsed, const char* txid, const uint64_t diversifier, const char* encryptedDiversifier, const uint64_t value, const char* nonce, const char* memo, const unsigned char* serialContext, const int serialContextLength, const char type, const CCoin coin);
|
||||
|
||||
CCSparkMintMeta toFFI(const CSparkMintMeta& cpp_struct);
|
||||
|
||||
spark::CoverSetData createCoverSetData(const std::vector<spark::Coin>& cover_set, const std::vector<std::vector<unsigned char>>& cover_set_representations);
|
||||
|
||||
spark::CoverSetData fromFFI(const CCoverSetData& c_struct);
|
||||
|
||||
CCoverSetData createCCoverSetData(const CCoin* cover_set, const unsigned char* cover_set_representation, const int cover_set_representationLength);
|
||||
//spark::CoverSetData createCoverSetData(const std::vector<spark::Coin>& cover_set, const std::vector<std::vector<unsigned char>>& cover_set_representations);
|
||||
//
|
||||
//spark::CoverSetData fromFFI(const CCoverSetData& c_struct);
|
||||
//
|
||||
//CCoverSetData createCCoverSetData(const CCoin* cover_set, const unsigned char* cover_set_representation, const int cover_set_representationLength);
|
||||
|
||||
char const hexArray[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
|
||||
'e', 'f'};
|
||||
|
||||
Reference in New Issue
Block a user