Skip to content

Commit

Permalink
Merge branch 'master' of github.com:nav-io/navio-core into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
alex v authored and gogoex committed Aug 18, 2024
2 parents 4cb021c + 05a19d2 commit 959048e
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 290 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ BLSCT_H = \
blsct/wallet/keyman.h \
blsct/wallet/keyring.h \
blsct/wallet/txfactory.h \
blsct/wallet/txfactory_base.h \
blsct/wallet/txfactory_global.h \
blsct/wallet/verification.h

Expand Down Expand Up @@ -717,6 +718,7 @@ libbitcoin_wallet_a_SOURCES = \
blsct/wallet/keyman.cpp \
blsct/wallet/keyring.cpp \
blsct/wallet/txfactory.cpp \
blsct/wallet/txfactory_base.cpp \
blsct/wallet/txfactory_global.cpp \
blsct/wallet/verification.cpp \
wallet/coincontrol.cpp \
Expand Down
163 changes: 4 additions & 159 deletions src/blsct/wallet/txfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,161 +13,6 @@ using Scalars = Elements<Scalar>;

namespace blsct {

void TxFactoryBase::AddOutput(const SubAddress& destination, const CAmount& nAmount, std::string sMemo, const TokenId& token_id, const CreateTransactionType& type, const CAmount& minStake, const bool& fSubtractFeeFromAmount)
{
UnsignedOutput out;

out = CreateOutput(destination.GetKeys(), nAmount, sMemo, token_id, Scalar::Rand(), type, minStake);

CAmount nFee = 0;

if (fSubtractFeeFromAmount) {
nFee = GetTransactioOutputWeight(out.out) * BLSCT_DEFAULT_FEE;
out = CreateOutput(destination.GetKeys(), nAmount - nFee, sMemo, token_id, Scalar::Rand(), type, minStake);
};

if (nAmounts.count(token_id) == 0)
nAmounts[token_id] = {0, 0};

nAmounts[token_id].nFromOutputs += nAmount - nFee;

if (vOutputs.count(token_id) == 0)
vOutputs[token_id] = std::vector<UnsignedOutput>();

vOutputs[token_id].push_back(out);
}

bool TxFactoryBase::AddInput(const CAmount& amount, const MclScalar& gamma, const PrivateKey& spendingKey, const TokenId& token_id, const COutPoint& outpoint, const bool& rbf)
{
if (vInputs.count(token_id) == 0)
vInputs[token_id] = std::vector<UnsignedInput>();

vInputs[token_id].push_back({CTxIn(outpoint, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::SEQUENCE_FINAL), amount, gamma, spendingKey});

if (nAmounts.count(token_id) == 0)
nAmounts[token_id] = {0, 0};

nAmounts[token_id].nFromInputs += amount;

return true;
}

std::optional<CMutableTransaction>
TxFactoryBase::BuildTx(const blsct::DoublePublicKey& changeDestination, const CAmount& minStake, const CreateTransactionType& type, const bool& fSubtractedFee)
{
this->tx = CMutableTransaction();

std::vector<Signature> outputSignatures;
Scalar outputGammas;
CAmount nFee = 0;

for (auto& out_ : vOutputs) {
for (auto& out : out_.second) {
this->tx.vout.push_back(out.out);
outputGammas = outputGammas - out.gamma;
outputSignatures.push_back(PrivateKey(out.blindingKey).Sign(out.out.GetHash()));
}
}

while (true) {
CMutableTransaction tx = this->tx;
tx.nVersion |= CTransaction::BLSCT_MARKER;

Scalar gammaAcc = outputGammas;
std::map<TokenId, CAmount> mapChange;
std::map<TokenId, CAmount> mapInputs;
std::vector<Signature> txSigs = outputSignatures;

for (auto& in_ : vInputs) {
auto tokenFee = (in_.first == TokenId() ? nFee : 0);

for (auto& in : in_.second) {
tx.vin.push_back(in.in);
gammaAcc = gammaAcc + in.gamma;
txSigs.push_back(in.sk.Sign(in.in.GetHash()));

if (!mapInputs[in_.first]) mapInputs[in_.first] = 0;

mapInputs[in_.first] += in.value.GetUint64();

if (mapInputs[in_.first] > nAmounts[in_.first].nFromOutputs + nFee) break;
}
}

for (auto& amounts : nAmounts) {
auto tokenFee = (amounts.first == TokenId() ? nFee : 0);

auto nFromInputs = mapInputs[amounts.first];

if (nFromInputs < amounts.second.nFromOutputs + tokenFee) return std::nullopt;

mapChange[amounts.first] = nFromInputs - amounts.second.nFromOutputs - tokenFee;
}

for (auto& change : mapChange) {
if (change.second == 0) continue;

auto changeOutput = CreateOutput(changeDestination, change.second, "Change", change.first, MclScalar::Rand(), type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE ? STAKED_COMMITMENT : NORMAL, minStake);

gammaAcc = gammaAcc - changeOutput.gamma;

tx.vout.push_back(changeOutput.out);
txSigs.push_back(PrivateKey(changeOutput.blindingKey).Sign(changeOutput.out.GetHash()));
}

if (nFee == GetTransactionWeight(CTransaction(tx)) * BLSCT_DEFAULT_FEE) {
CTxOut fee_out{nFee, CScript(OP_RETURN)};

tx.vout.push_back(fee_out);
txSigs.push_back(PrivateKey(gammaAcc).SignBalance());
tx.txSig = Signature::Aggregate(txSigs);

return tx;
}

nFee = GetTransactionWeight(CTransaction(tx)) * BLSCT_DEFAULT_FEE;
}

return std::nullopt;
}

std::optional<CMutableTransaction> TxFactoryBase::CreateTransaction(const std::vector<InputCandidates>& inputCandidates, const blsct::DoublePublicKey& changeDestination, const SubAddress& destination, const CAmount& nAmount, std::string sMemo, const TokenId& token_id, const CreateTransactionType& type, const CAmount& minStake)
{
auto tx = blsct::TxFactoryBase();
CAmount inAmount = 0;

if (type == STAKED_COMMITMENT) {
CAmount inputFromStakedCommitments = 0;

for (const auto& output : inputCandidates) {
if (output.is_staked_commitment)
inputFromStakedCommitments += output.amount;
if (!output.is_staked_commitment)
inAmount += output.amount;

tx.AddInput(output.amount, output.gamma, output.spendingKey, output.token_id, COutPoint(output.outpoint.hash, output.outpoint.n));
}

if (nAmount + inputFromStakedCommitments < minStake) {
throw std::runtime_error(strprintf("A minimum of %s is required to stake", FormatMoney(minStake)));
}

bool fSubtractFeeFromAmount = false; // nAmount == inAmount + inputFromStakedCommitments;

tx.AddOutput(destination, nAmount + inputFromStakedCommitments, sMemo, token_id, type, minStake, fSubtractFeeFromAmount);
} else {
for (const auto& output : inputCandidates) {
tx.AddInput(output.amount, output.gamma, output.spendingKey, output.token_id, COutPoint(output.outpoint.hash, output.outpoint.n));
}

bool fSubtractFeeFromAmount = false; // type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE;

tx.AddOutput(destination, nAmount, sMemo, token_id, type, minStake, fSubtractFeeFromAmount);
}

return tx.BuildTx(changeDestination, minStake, type);
}

bool TxFactory::AddInput(const CCoinsViewCache& cache, const COutPoint& outpoint, const bool& rbf)
{
Coin coin;
Expand Down Expand Up @@ -225,7 +70,7 @@ TxFactory::BuildTx()
return TxFactoryBase::BuildTx(std::get<blsct::DoublePublicKey>(km->GetNewDestination(-1).value()));
}

void TxFactoryBase::AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const wallet::CoinFilterParams& coins_params, std::vector<InputCandidates>& inputCandidates) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet)
void TxFactory::AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const wallet::CoinFilterParams& coins_params, std::vector<InputCandidates>& inputCandidates) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet)
{
LOCK(wallet->cs_wallet);

Expand All @@ -242,7 +87,7 @@ void TxFactoryBase::AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* bl
}
}

void TxFactoryBase::AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const TokenId& token_id, const CreateTransactionType& type, std::vector<InputCandidates>& inputCandidates)
void TxFactory::AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const TokenId& token_id, const CreateTransactionType& type, std::vector<InputCandidates>& inputCandidates)
{
wallet::CoinFilterParams coins_params;
coins_params.min_amount = 0;
Expand All @@ -262,12 +107,12 @@ std::optional<CMutableTransaction> TxFactory::CreateTransaction(wallet::CWallet*
{
std::vector<InputCandidates> inputCandidates;

TxFactoryBase::AddAvailableCoins(wallet, blsct_km, token_id, type, inputCandidates);
AddAvailableCoins(wallet, blsct_km, token_id, type, inputCandidates);

auto changeType = type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE ? STAKING_ACCOUNT : CHANGE_ACCOUNT;
auto changeAddress = std::get<blsct::DoublePublicKey>(blsct_km->GetNewDestination(changeType).value());

return TxFactoryBase::CreateTransaction(inputCandidates, changeAddress, destination, nAmount, sMemo, token_id, type, minStake);
}

} // namespace blsct
} // namespace blsct
33 changes: 4 additions & 29 deletions src/blsct/wallet/txfactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <blsct/arith/elements.h>
#include <blsct/wallet/keyman.h>
#include <blsct/wallet/txfactory_base.h>
#include <blsct/wallet/txfactory_global.h>
#include <policy/fees.h>
#include <util/rbf.h>
Expand All @@ -15,34 +16,6 @@

namespace blsct {

struct InputCandidates {
CAmount amount;
MclScalar gamma;
blsct::PrivateKey spendingKey;
TokenId token_id;
COutPoint outpoint;
bool is_staked_commitment;
};

class TxFactoryBase
{
protected:
CMutableTransaction tx;
std::map<TokenId, std::vector<UnsignedOutput>> vOutputs;
std::map<TokenId, std::vector<UnsignedInput>> vInputs;
std::map<TokenId, Amounts> nAmounts;

public:
TxFactoryBase(){};

void AddOutput(const SubAddress& destination, const CAmount& nAmount, std::string sMemo, const TokenId& token_id = TokenId(), const CreateTransactionType& type = NORMAL, const CAmount& minStake = 0, const bool& fSubtractFeeFromAmount = false);
bool AddInput(const CAmount& amount, const MclScalar& gamma, const blsct::PrivateKey& spendingKey, const TokenId& token_id, const COutPoint& outpoint, const bool& rbf = false);
std::optional<CMutableTransaction> BuildTx(const blsct::DoublePublicKey& changeDestination, const CAmount& minStake = 0, const CreateTransactionType& type = NORMAL, const bool& fSubtractedFee = false);
static std::optional<CMutableTransaction> CreateTransaction(const std::vector<InputCandidates>& inputCandidates, const blsct::DoublePublicKey& changeDestination, const SubAddress& destination, const CAmount& nAmount, std::string sMemo, const TokenId& token_id = TokenId(), const CreateTransactionType& type = NORMAL, const CAmount& minStake = 0);
static void AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const wallet::CoinFilterParams& coins_params, std::vector<InputCandidates>& inputCandidates) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
static void AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const TokenId& token_id, const CreateTransactionType& type, std::vector<InputCandidates>& inputCandidates);
};

class TxFactory : public TxFactoryBase
{
private:
Expand All @@ -55,7 +28,9 @@ class TxFactory : public TxFactoryBase
bool AddInput(const CCoinsViewCache& cache, const COutPoint& outpoint, const bool& rbf = false);
std::optional<CMutableTransaction> BuildTx();
static std::optional<CMutableTransaction> CreateTransaction(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const SubAddress& destination, const CAmount& nAmount, std::string sMemo, const TokenId& token_id = TokenId(), const CreateTransactionType& type = NORMAL, const CAmount& minStake = 0);
static void AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const wallet::CoinFilterParams& coins_params, std::vector<InputCandidates>& inputCandidates) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
static void AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* blsct_km, const TokenId& token_id, const CreateTransactionType& type, std::vector<InputCandidates>& inputCandidates);
};
} // namespace blsct

#endif // TXFACTORY_H
#endif // TXFACTORY_H
Loading

0 comments on commit 959048e

Please sign in to comment.