Skip to content

Commit

Permalink
fix unlocking full amount
Browse files Browse the repository at this point in the history
  • Loading branch information
alex v committed Aug 23, 2024
1 parent e3411ff commit 8e2c096
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 15 deletions.
63 changes: 52 additions & 11 deletions src/blsct/wallet/txfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ void TxFactoryBase::AddOutput(const SubAddress& destination, const CAmount& nAmo
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)
bool TxFactoryBase::AddInput(const CAmount& amount, const MclScalar& gamma, const PrivateKey& spendingKey, const TokenId& token_id, const COutPoint& outpoint, const bool& stakedCommitment, 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});
vInputs[token_id].push_back({CTxIn(outpoint, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::SEQUENCE_FINAL), amount, gamma, spendingKey, stakedCommitment});

if (nAmounts.count(token_id) == 0)
nAmounts[token_id] = {0, 0};
Expand All @@ -61,6 +61,7 @@ TxFactoryBase::BuildTx(const blsct::DoublePublicKey& changeDestination, const CA
Scalar outputGammas;
CAmount nFee = 0;


for (auto& out_ : vOutputs) {
for (auto& out : out_.second) {
this->tx.vout.push_back(out.out);
Expand All @@ -78,8 +79,28 @@ TxFactoryBase::BuildTx(const blsct::DoublePublicKey& changeDestination, const CA
std::map<TokenId, CAmount> mapInputs;
std::vector<Signature> txSigs = outputSignatures;

if (type == STAKED_COMMITMENT_UNSTAKE || type == STAKED_COMMITMENT) {
for (auto& in_ : vInputs) {
for (auto& in : in_.second) {
if (!in.is_staked_commitment) continue;

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& in_ : vInputs) {
for (auto& in : in_.second) {
if (in.is_staked_commitment) continue;

tx.vin.push_back(in.in);
gammaAcc = gammaAcc + in.gamma;
txSigs.push_back(in.sk.Sign(in.in.GetHash()));
Expand All @@ -105,7 +126,7 @@ TxFactoryBase::BuildTx(const blsct::DoublePublicKey& changeDestination, const CA
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);
auto changeOutput = CreateOutput(changeDestination, change.second, "Change", change.first, MclScalar::Rand(), NORMAL, minStake);

gammaAcc = gammaAcc - changeOutput.gamma;

Expand Down Expand Up @@ -140,7 +161,7 @@ std::optional<CMutableTransaction> TxFactoryBase::CreateTransaction(const std::v
if (output.is_staked_commitment)
inputFromStakedCommitments += output.amount;

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

if (nAmount + inputFromStakedCommitments < minStake) {
Expand All @@ -151,8 +172,29 @@ std::optional<CMutableTransaction> TxFactoryBase::CreateTransaction(const std::v

tx.AddOutput(destination, nAmount + inputFromStakedCommitments, sMemo, token_id, type, minStake, fSubtractFeeFromAmount);
} else {
CAmount inputFromStakedCommitments = 0;

for (const auto& output : inputCandidates) {
tx.AddInput(output.amount, output.gamma, output.spendingKey, output.token_id, COutPoint(output.outpoint.hash, output.outpoint.n));
if (output.is_staked_commitment) {
if (!(type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE || type == CreateTransactionType::STAKED_COMMITMENT))
continue;
inputFromStakedCommitments += output.amount;
}

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

if (type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE) {
if (inputFromStakedCommitments - nAmount < 0) {
throw std::runtime_error(strprintf("Not enough staked coins"));
} else if (inputFromStakedCommitments - nAmount < minStake && inputFromStakedCommitments - nAmount > 0) {
throw std::runtime_error(strprintf("A minimum of %s is required to stake", FormatMoney(minStake)));
}

if (inputFromStakedCommitments - nAmount > 0) {
// CHANGE
tx.AddOutput(destination, inputFromStakedCommitments - nAmount, sMemo, token_id, CreateTransactionType::STAKED_COMMITMENT, minStake, false);
}
}

bool fSubtractFeeFromAmount = false; // type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE;
Expand All @@ -163,7 +205,7 @@ std::optional<CMutableTransaction> TxFactoryBase::CreateTransaction(const std::v
return tx.BuildTx(changeDestination, minStake, type);
}

bool TxFactory::AddInput(const CCoinsViewCache& cache, const COutPoint& outpoint, const bool& rbf)
bool TxFactory::AddInput(const CCoinsViewCache& cache, const COutPoint& outpoint, const bool& stakedCommitment, const bool& rbf)
{
Coin coin;

Expand All @@ -178,7 +220,7 @@ bool TxFactory::AddInput(const CCoinsViewCache& cache, const COutPoint& outpoint
if (vInputs.count(coin.out.tokenId) == 0)
vInputs[coin.out.tokenId] = std::vector<UnsignedInput>();

vInputs[coin.out.tokenId].push_back({CTxIn(outpoint, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::SEQUENCE_FINAL), recoveredInfo.amounts[0].amount, recoveredInfo.amounts[0].gamma, km->GetSpendingKeyForOutput(coin.out)});
vInputs[coin.out.tokenId].push_back({CTxIn(outpoint, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::SEQUENCE_FINAL), recoveredInfo.amounts[0].amount, recoveredInfo.amounts[0].gamma, km->GetSpendingKeyForOutput(coin.out), stakedCommitment});

if (nAmounts.count(coin.out.tokenId) == 0)
nAmounts[coin.out.tokenId] = {0, 0};
Expand All @@ -188,7 +230,7 @@ bool TxFactory::AddInput(const CCoinsViewCache& cache, const COutPoint& outpoint
return true;
}

bool TxFactory::AddInput(wallet::CWallet* wallet, const COutPoint& outpoint, const bool& rbf)
bool TxFactory::AddInput(wallet::CWallet* wallet, const COutPoint& outpoint, const bool& stakedCommitment, const bool& rbf)
{
AssertLockHeld(wallet->cs_wallet);

Expand All @@ -204,7 +246,7 @@ bool TxFactory::AddInput(wallet::CWallet* wallet, const COutPoint& outpoint, con

auto recoveredInfo = tx->GetBLSCTRecoveryData(outpoint.n);

vInputs[out.tokenId].push_back({CTxIn(outpoint, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::SEQUENCE_FINAL), recoveredInfo.amount, recoveredInfo.gamma, km->GetSpendingKeyForOutput(out)});
vInputs[out.tokenId].push_back({CTxIn(outpoint, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::SEQUENCE_FINAL), recoveredInfo.amount, recoveredInfo.gamma, km->GetSpendingKeyForOutput(out), stakedCommitment});

if (nAmounts.count(out.tokenId) == 0)
nAmounts[out.tokenId] = {0, 0};
Expand Down Expand Up @@ -243,12 +285,11 @@ void TxFactoryBase::AddAvailableCoins(wallet::CWallet* wallet, blsct::KeyMan* bl
wallet::CoinFilterParams coins_params;
coins_params.min_amount = 0;
coins_params.only_blsct = true;
coins_params.include_staked_commitment = (type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE);
coins_params.token_id = token_id;

AddAvailableCoins(wallet, blsct_km, coins_params, inputCandidates);

if (type == CreateTransactionType::STAKED_COMMITMENT) {
if (type == CreateTransactionType::STAKED_COMMITMENT || type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE) {
coins_params.include_staked_commitment = true;
AddAvailableCoins(wallet, blsct_km, coins_params, inputCandidates);
}
Expand Down
6 changes: 3 additions & 3 deletions src/blsct/wallet/txfactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class TxFactoryBase
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);
bool AddInput(const CAmount& amount, const MclScalar& gamma, const blsct::PrivateKey& spendingKey, const TokenId& token_id, const COutPoint& outpoint, const bool& stakedCommitment = false, 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);
Expand All @@ -51,8 +51,8 @@ class TxFactory : public TxFactoryBase
public:
TxFactory(KeyMan* km) : km(km){};

bool AddInput(wallet::CWallet* wallet, const COutPoint& outpoint, const bool& rbf = false) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
bool AddInput(const CCoinsViewCache& cache, const COutPoint& outpoint, const bool& rbf = false);
bool AddInput(wallet::CWallet* wallet, const COutPoint& outpoint, const bool& stakedCommitment = false, const bool& rbf = false) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
bool AddInput(const CCoinsViewCache& cache, const COutPoint& outpoint, const bool& stakedCommitment = false, 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);
};
Expand Down
1 change: 1 addition & 0 deletions src/blsct/wallet/txfactory_global.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct UnsignedInput {
Scalar value;
Scalar gamma;
PrivateKey sk;
bool is_staked_commitment;
};

struct Amounts {
Expand Down
15 changes: 14 additions & 1 deletion src/ctokens/tokenid.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#include <tinyformat.h>
#include <uint256.h>

const uint256 stakedCommitmentToken = uint256();
const uint64_t stakedCommitmentSubId = 1;

class TokenId
{
public:
Expand All @@ -18,6 +21,11 @@ class TokenId

TokenId(const uint256& t = uint256(), const uint64_t& i = std::numeric_limits<uint64_t>::max()) : token(t), subid(i) {}

static TokenId StakedCommitment()
{
return TokenId(stakedCommitmentToken, stakedCommitmentSubId);
}

void SetNull()
{
token = uint256();
Expand All @@ -26,7 +34,12 @@ class TokenId

bool IsNull() const { return token == uint256() && subid == std::numeric_limits<uint64_t>::max(); }

std::string ToString() const { return strprintf("%s%s", token.ToString(), subid == std::numeric_limits<uint64_t>::max() ? "" : strprintf("#%d", subid)); }
bool IsStakedCommitment() const
{
return token == stakedCommitmentToken && subid == stakedCommitmentSubId;
}

std::string ToString() const { return strprintf("%s%s", token.ToString(), strprintf("#%d", subid)); }

friend bool operator==(const TokenId& a, const TokenId& b) { return a.token == b.token && a.subid == b.subid; }

Expand Down

0 comments on commit 8e2c096

Please sign in to comment.