Skip to content

Commit

Permalink
Prepare support for Zcash Sapling update
Browse files Browse the repository at this point in the history
  • Loading branch information
KhalilBellakrid committed Oct 22, 2018
1 parent 09fb3af commit 3fc6577
Show file tree
Hide file tree
Showing 19 changed files with 111 additions and 50 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ include(UseBackportedModules)
# The project version number.
set(VERSION_MAJOR 1 CACHE STRING "Project major version number.")
set(VERSION_MINOR 1 CACHE STRING "Project minor version number.")
set(VERSION_PATCH 2 CACHE STRING "Project patch version number.")
set(VERSION_PATCH 3 CACHE STRING "Project patch version number.")
mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY build)
Expand Down
6 changes: 5 additions & 1 deletion api/core/java/BitcoinLikeTransactionBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ public abstract class BitcoinLikeTransactionBuilder {
/** Reset the current instance to its initial state */
public abstract void reset();

public static native BitcoinLikeTransaction parseRawUnsignedTransaction(Currency currency, byte[] rawTransaction);
/**
* Parsing unsigned transaction
* parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight)
*/
public static native BitcoinLikeTransaction parseRawUnsignedTransaction(Currency currency, byte[] rawTransaction, Integer currentBlockHeight);

private static final class CppProxy extends BitcoinLikeTransactionBuilder
{
Expand Down
19 changes: 13 additions & 6 deletions api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,9 @@ NAN_METHOD(NJSBitcoinLikeTransactionBuilder::reset) {
NAN_METHOD(NJSBitcoinLikeTransactionBuilder::parseRawUnsignedTransaction) {

//Check if method called with right number of arguments
if(info.Length() != 2)
if(info.Length() != 3)
{
return Nan::ThrowError("NJSBitcoinLikeTransactionBuilder::parseRawUnsignedTransaction needs 2 arguments");
return Nan::ThrowError("NJSBitcoinLikeTransactionBuilder::parseRawUnsignedTransaction needs 3 arguments");
}

//Check if parameters have correct types
Expand Down Expand Up @@ -613,16 +613,23 @@ NAN_METHOD(NJSBitcoinLikeTransactionBuilder::parseRawUnsignedTransaction) {
}
}

auto arg_2 = std::experimental::optional<int32_t>();
if(!info[2]->IsNull())
{
auto opt_arg_2 = Nan::To<int32_t>(info[2]).FromJust();
arg_2.emplace(opt_arg_2);
}

auto result = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(arg_0,arg_1);

auto result = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(arg_0,arg_1,arg_2);

//Wrap result in node object
auto arg_2_wrap = NJSBitcoinLikeTransaction::wrap(result);
auto arg_2 = Nan::ObjectWrap::Unwrap<NJSBitcoinLikeTransaction>(arg_2_wrap)->handle();
auto arg_3_wrap = NJSBitcoinLikeTransaction::wrap(result);
auto arg_3 = Nan::ObjectWrap::Unwrap<NJSBitcoinLikeTransaction>(arg_3_wrap)->handle();


//Return result
info.GetReturnValue().Set(arg_2);
info.GetReturnValue().Set(arg_3);
}

NAN_METHOD(NJSBitcoinLikeTransactionBuilder::New) {
Expand Down
5 changes: 5 additions & 0 deletions api/core/nodejs/NJSBitcoinLikeTransactionBuilderCpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define DJINNI_GENERATED_NJSBITCOINLIKETRANSACTIONBUILDER_HPP


#include "../../../core/src/api/../utils/optional.hpp"
#include "../../../core/src/api/BitcoinLikeNetworkParameters.hpp"
#include "../../../core/src/api/BitcoinLikePickingStrategy.hpp"
#include "../../../core/src/api/Currency.hpp"
Expand Down Expand Up @@ -126,6 +127,10 @@ class NJSBitcoinLikeTransactionBuilder: public Nan::ObjectWrap {
/** Reset the current instance to its initial state */
static NAN_METHOD(reset);

/**
* Parsing unsigned transaction
* parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight)
*/
static NAN_METHOD(parseRawUnsignedTransaction);

static NAN_METHOD(New);
Expand Down
6 changes: 5 additions & 1 deletion api/core/nodejs/ledgerapp_nodejs_doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -1707,7 +1707,11 @@ declare class NJSBitcoinLikeTransactionBuilder
declare function clone(): NJSBitcoinLikeTransactionBuilder;
/** Reset the current instance to its initial state */
declare function reset();
static declare function parseRawUnsignedTransaction(currency: Currency, rawTransaction: Object): NJSBitcoinLikeTransaction;
/**
* Parsing unsigned transaction
* parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight)
*/
static declare function parseRawUnsignedTransaction(currency: Currency, rawTransaction: Object, currentBlockHeight: ?number): NJSBitcoinLikeTransaction;
}
/**
*Callback triggered by main completed task,
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ branches:
image:
- Visual Studio 2015
environment:
LIB_VERSION: 1.1.2 #Hardcode the LIB_VERSION : should be retrieved by building libcore node module and run tests/lib_version.js
LIB_VERSION: 1.1.3 #Hardcode the LIB_VERSION : should be retrieved by building libcore node module and run tests/lib_version.js
nodejs_version: "9"
appveyor_rdp_password:
secure: jb1LsDmcxCww7tA38S3xSw==
Expand Down
4 changes: 3 additions & 1 deletion core/idl/wallet/bitcoin/bitcoin_like_wallet.djinni
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,9 @@ BitcoinLikeTransactionBuilder = interface +c {
# Reset the current instance to its initial state
reset();

static parseRawUnsignedTransaction(currency: Currency, rawTransaction: binary): BitcoinLikeTransaction;
# Parsing unsigned transaction
# parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight)
static parseRawUnsignedTransaction(currency: Currency, rawTransaction: binary, currentBlockHeight: optional<i32>): BitcoinLikeTransaction;
}

#Class representing a Bitcoin account
Expand Down
7 changes: 6 additions & 1 deletion core/src/api/BitcoinLikeTransactionBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#ifndef DJINNI_GENERATED_BITCOINLIKETRANSACTIONBUILDER_HPP
#define DJINNI_GENERATED_BITCOINLIKETRANSACTIONBUILDER_HPP

#include "../utils/optional.hpp"
#include <cstdint>
#include <memory>
#include <string>
Expand Down Expand Up @@ -109,7 +110,11 @@ class BitcoinLikeTransactionBuilder {
/** Reset the current instance to its initial state */
virtual void reset() = 0;

static std::shared_ptr<BitcoinLikeTransaction> parseRawUnsignedTransaction(const Currency & currency, const std::vector<uint8_t> & rawTransaction);
/**
* Parsing unsigned transaction
* parsing a tx might change depending on block height we are on (if an update is effective starting from a given hight)
*/
static std::shared_ptr<BitcoinLikeTransaction> parseRawUnsignedTransaction(const Currency & currency, const std::vector<uint8_t> & rawTransaction, std::experimental::optional<int32_t> currentBlockHeight);
};

} } } // namespace ledger::core::api
Expand Down
5 changes: 3 additions & 2 deletions core/src/jni/jni/BitcoinLikeTransactionBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,13 @@ CJNIEXPORT void JNICALL Java_co_ledger_core_BitcoinLikeTransactionBuilder_00024C
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, )
}

CJNIEXPORT jobject JNICALL Java_co_ledger_core_BitcoinLikeTransactionBuilder_parseRawUnsignedTransaction(JNIEnv* jniEnv, jobject /*this*/, jobject j_currency, jbyteArray j_rawTransaction)
CJNIEXPORT jobject JNICALL Java_co_ledger_core_BitcoinLikeTransactionBuilder_parseRawUnsignedTransaction(JNIEnv* jniEnv, jobject /*this*/, jobject j_currency, jbyteArray j_rawTransaction, jobject j_currentBlockHeight)
{
try {
DJINNI_FUNCTION_PROLOGUE0(jniEnv);
auto r = ::ledger::core::api::BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(::djinni_generated::Currency::toCpp(jniEnv, j_currency),
::djinni::Binary::toCpp(jniEnv, j_rawTransaction));
::djinni::Binary::toCpp(jniEnv, j_rawTransaction),
::djinni::Optional<std::experimental::optional, ::djinni::I32>::toCpp(jniEnv, j_currentBlockHeight));
return ::djinni::release(::djinni_generated::BitcoinLikeTransaction::fromCpp(jniEnv, r));
} JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */)
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/wallet/bitcoin/BitcoinLikeAccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ namespace ledger {
//Store newly broadcasted tx in db
//First parse it
auto txHash = seq.str();
auto tx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(self->getWallet()->getCurrency(), transaction);
auto tx = BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(self->getWallet()->getCurrency(), transaction, self->_currentBlockHeight);

//Get a BitcoinLikeBlockchainExplorer::Transaction from a BitcoinLikeTransaction
BitcoinLikeBlockchainExplorer::Transaction txExplorer;
Expand Down Expand Up @@ -599,7 +599,7 @@ namespace ledger {
getContext(),
getWallet()->getCurrency(),
logger(),
_picker->getBuildFunction(getUTXO, getTransaction, _explorer, _keychain, logger())
_picker->getBuildFunction(getUTXO, getTransaction, _explorer, _keychain, _currentBlockHeight,logger())
);
}

Expand Down
34 changes: 20 additions & 14 deletions core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ namespace ledger {
namespace core {


BitcoinLikeTransactionApi::BitcoinLikeTransactionApi(const api::Currency& currency, bool isSegwit) {
_currency = currency;
BitcoinLikeTransactionApi::BitcoinLikeTransactionApi(const api::Currency& currency,
bool isSegwit,
uint64_t currentBlockHeight) :
_currency(currency), _isSegwit(isSegwit), _currentBlockHeight(currentBlockHeight) {
_version = 1;
_writable = true;
_isSegwit = isSegwit;
}

BitcoinLikeTransactionApi::BitcoinLikeTransactionApi(const std::shared_ptr<OperationApi> &operation) : BitcoinLikeTransactionApi(operation->getCurrency()) {
Expand Down Expand Up @@ -229,21 +230,23 @@ namespace ledger {
void BitcoinLikeTransactionApi::serializeProlog(BytesWriter &writer) {

auto &additionalBIPs = _currency.bitcoinLikeNetworkParameters.value().AdditionalBIPs;
auto it = std::find(additionalBIPs.begin(), additionalBIPs.end(), "ZIP143");
auto it = std::find(additionalBIPs.begin(), additionalBIPs.end(), "ZIP");
auto zipParameters = _currentBlockHeight > networks::ZIP_SAPLING_PARAMETERS.blockHeight ?
networks::ZIP_SAPLING_PARAMETERS : networks::ZIP143_PARAMETERS;

if (it != additionalBIPs.end()) {
setVersion(networks::ZIP143_PARAMETERS.version);
setVersion(zipParameters.version);

//New version and overwinter flag
auto header = networks::ZIP143_PARAMETERS.overwinterFlag;
auto header = zipParameters.overwinterFlag;
header.push_back(0x00);
header.push_back(0x00);
header.push_back(networks::ZIP143_PARAMETERS.version);
header.push_back(zipParameters.version);
//Push header (0x80000003 in LE)
writer.writeLeByteArray(header);

//Version group Id (0x03C48270 in LE)
writer.writeLeByteArray(networks::ZIP143_PARAMETERS.versionGroupId);
writer.writeLeByteArray(zipParameters.versionGroupId);

} else {
writer.writeLeValue<int32_t>(_version);
Expand Down Expand Up @@ -311,22 +314,25 @@ namespace ledger {


std::shared_ptr<api::BitcoinLikeTransaction> api::BitcoinLikeTransactionBuilder::parseRawUnsignedTransaction(
const Currency &currency, const std::vector<uint8_t> &rawTransaction) {
const Currency &currency, const std::vector<uint8_t> &rawTransaction, std::experimental::optional<int32_t> currentBlockHeight) {

BytesReader reader(rawTransaction);

// Parse version
auto version = reader.readNextLeUint();

//Parse additionalBIPs if there are any
auto &additionalBIPs = currency.bitcoinLikeNetworkParameters.value().AdditionalBIPs;
auto it = std::find(additionalBIPs.begin(), additionalBIPs.end(), "ZIP143");

auto it = std::find(additionalBIPs.begin(), additionalBIPs.end(), "ZIP");
auto zipParameters = currentBlockHeight.value_or(0) > networks::ZIP_SAPLING_PARAMETERS.blockHeight ?
networks::ZIP_SAPLING_PARAMETERS : networks::ZIP143_PARAMETERS;
if (it != additionalBIPs.end()) {
//Substract overwinterFlag
auto overwinterFlag = networks::ZIP143_PARAMETERS.overwinterFlag[0];
auto overwinterFlag = zipParameters.overwinterFlag[0];
version -= (~ (overwinterFlag << 24) + 1);

//Read version group Id
reader.read(networks::ZIP143_PARAMETERS.versionGroupId.size());
reader.read(zipParameters.versionGroupId.size());
}

// Parse timestamp
Expand All @@ -345,7 +351,7 @@ namespace ledger {
auto flag = reader.readNextByte();
}

auto tx = std::make_shared<BitcoinLikeTransactionApi>(currency, isSegwit);
auto tx = std::make_shared<BitcoinLikeTransactionApi>(currency, isSegwit, currentBlockHeight.value_or(0));
tx->setVersion(version);
if (usesTimeStamp) {
tx->setTimestamp(timeStamp);
Expand Down
3 changes: 2 additions & 1 deletion core/src/wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace ledger {
class BytesWriter;
class BitcoinLikeTransactionApi : public api::BitcoinLikeTransaction {
public:
explicit BitcoinLikeTransactionApi(const api::Currency& currency, bool isSegwit = false);
explicit BitcoinLikeTransactionApi(const api::Currency& currency, bool isSegwit = false, uint64_t currentBlockHeight = 0);
explicit BitcoinLikeTransactionApi(const std::shared_ptr<OperationApi>& operation);
std::vector<std::shared_ptr<api::BitcoinLikeInput>> getInputs() override;
std::vector<std::shared_ptr<api::BitcoinLikeOutput>> getOutputs() override;
Expand Down Expand Up @@ -98,6 +98,7 @@ namespace ledger {
Option<uint32_t> _timestamp;
bool _writable;
bool _isSegwit;
uint64_t _currentBlockHeight;
};
}
}
Expand Down
14 changes: 11 additions & 3 deletions core/src/wallet/bitcoin/networks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,18 @@ namespace ledger {
};

//Zcash overwinter
const ZIP143Parameters ZIP143_PARAMETERS = {
const ZIPParameters ZIP143_PARAMETERS = {
3,
{0x80},
{0x03, 0xC4, 0x82, 0x70}
{0x03, 0xC4, 0x82, 0x70},
347500
};
//Zcash Sapling (starting from block 419200)
const ZIPParameters ZIP_SAPLING_PARAMETERS = {
4,
{0x80},
{0x89, 0x2F, 0x20, 0x85},
419200
};

const api::BitcoinLikeNetworkParameters getNetworkParameters(const std::string &networkName) {
Expand Down Expand Up @@ -128,7 +136,7 @@ namespace ledger {
false,
0,
{sigHashType::SIGHASH_ALL},
{"ZIP143"}
{"ZIP"}
);
return ZCASH;
} else if (networkName == "zencash") {
Expand Down
10 changes: 5 additions & 5 deletions core/src/wallet/bitcoin/networks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ namespace ledger {
};
extern LIBCORE_EXPORT const BIP115Parameters BIP115_PARAMETERS;

//ZIP143 (ex: Zcash overwinter)
//extern LIBCORE_EXPORT const std::string ZIP143;
struct ZIP143Parameters {
//ZIP: Zcash improvements/updates (ex: Zcash overwinter, Sapling ...)
struct ZIPParameters {
uint32_t version;
std::vector<uint8_t> overwinterFlag;
std::vector<uint8_t> versionGroupId;
uint64_t blockHeight; //block height at which ZIP will be effective
};
extern LIBCORE_EXPORT const ZIP143Parameters ZIP143_PARAMETERS;

extern LIBCORE_EXPORT const ZIPParameters ZIP143_PARAMETERS;
extern LIBCORE_EXPORT const ZIPParameters ZIP_SAPLING_PARAMETERS;
template<class Archive>
void serialize(Archive & archive,
api::BitcoinLikeNetworkParameters & p)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ namespace ledger {
const BitcoinLikeGetTxFunction& getTransaction,
const std::shared_ptr<BitcoinLikeBlockchainExplorer> &explorer,
const std::shared_ptr<BitcoinLikeKeychain> &keychain,
const uint64_t currentBlockHeight,
const std::shared_ptr<spdlog::logger>& logger
) {
auto self = shared_from_this();
logger->info("Get build function");
return [=] (const BitcoinLikeTransactionBuildRequest& r) -> Future<std::shared_ptr<api::BitcoinLikeTransaction>> {
return self->async<std::shared_ptr<Buddy>>([=] () {
auto tx = std::make_shared<BitcoinLikeTransactionApi>(self->_currency, keychain->isSegwit());
logger->info("Constructing BitcoinLikeTransactionBuildFunction with blockHeight: {}", currentBlockHeight);
auto tx = std::make_shared<BitcoinLikeTransactionApi>(self->_currency, keychain->isSegwit(), currentBlockHeight);
auto filteredGetUtxo = createFilteredUtxoFunction(r, getUtxo);
return std::make_shared<Buddy>(r, filteredGetUtxo, getTransaction, explorer, keychain, logger, tx);
}).flatMap<std::shared_ptr<api::BitcoinLikeTransaction>>(ImmediateExecutionContext::INSTANCE, [=] (const std::shared_ptr<Buddy>& buddy) -> Future<std::shared_ptr<api::BitcoinLikeTransaction>> {
Expand All @@ -71,7 +73,7 @@ namespace ledger {
return buddy->transaction;
});;
});
};
};;
}

const api::Currency &BitcoinLikeUtxoPicker::getCurrency() const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace ledger {
const BitcoinLikeGetTxFunction& getTransaction,
const std::shared_ptr<BitcoinLikeBlockchainExplorer>& explorer,
const std::shared_ptr<BitcoinLikeKeychain>& keychain,
const uint64_t currentBlockHeight,
const std::shared_ptr<spdlog::logger>& logger
);
const api::Currency& getCurrency() const;
Expand Down
Loading

0 comments on commit 3fc6577

Please sign in to comment.