Skip to content

Commit

Permalink
calculate fee from tx weight
Browse files Browse the repository at this point in the history
  • Loading branch information
alex v committed Aug 9, 2024
1 parent 464d3a1 commit 3e6d826
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 45 deletions.
102 changes: 59 additions & 43 deletions src/blsct/wallet/txfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,23 @@ 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)
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;
nAmounts[token_id].nFromOutputs += nAmount - nFee;

if (vOutputs.count(token_id) == 0)
vOutputs[token_id] = std::vector<UnsignedOutput>();
Expand All @@ -47,55 +55,77 @@ bool TxFactoryBase::AddInput(const CAmount& amount, const MclScalar& gamma, cons
std::optional<CMutableTransaction>
TxFactoryBase::BuildTx(const blsct::DoublePublicKey& changeDestination, const CAmount& minStake, const CreateTransactionType& type, const bool& fSubtractedFee)
{
CAmount nFee = BLSCT_DEFAULT_FEE * (vInputs.size() + vOutputs.size());
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;
CMutableTransaction tx = this->tx;
tx.nVersion |= CTransaction::BLSCT_MARKER;

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

for (auto& amounts : nAmounts) {
if (amounts.second.nFromInputs < amounts.second.nFromOutputs + nFee)
return std::nullopt;
mapChange[amounts.first] = amounts.second.nFromInputs - amounts.second.nFromOutputs - nFee;
}
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& out_ : vOutputs) {
for (auto& out : out_.second) {
tx.vout.push_back(out.out);
gammaAcc = gammaAcc - out.gamma;
txSigs.push_back(PrivateKey(out.blindingKey).Sign(out.out.GetHash()));
}
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);
tx.vout.push_back(changeOutput.out);

gammaAcc = gammaAcc - changeOutput.gamma;

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

if (nFee == (long long)(BLSCT_DEFAULT_FEE * (tx.vin.size() + tx.vout.size()))) {
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 = BLSCT_DEFAULT_FEE * (tx.vin.size() + tx.vout.size());
nFee = GetTransactionWeight(CTransaction(tx)) * BLSCT_DEFAULT_FEE;
}

return std::nullopt;
Expand All @@ -108,45 +138,31 @@ std::optional<CMutableTransaction> TxFactoryBase::CreateTransaction(const std::v

if (type == STAKED_COMMITMENT) {
CAmount inputFromStakedCommitments = 0;
for (const auto& output : inputCandidates) {
if (!output.is_staked_commitment)
continue;

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

inputFromStakedCommitments += output.amount;
}
for (const auto& output : inputCandidates) {
if (output.is_staked_commitment)
continue;
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));

inAmount += output.amount;

if (tx.nAmounts[token_id].nFromInputs - inputFromStakedCommitments > nAmount + (long long)(BLSCT_DEFAULT_FEE * (tx.vInputs.size() + 2)))
break;
}

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

tx.AddOutput(destination, nAmount + inputFromStakedCommitments, sMemo, token_id, type, 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));
inAmount += output.amount;
if (tx.nAmounts[token_id].nFromInputs > nAmount + (long long)(BLSCT_DEFAULT_FEE * (tx.vInputs.size() + 2))) break;
}

CAmount subtract = 0;
bool fChangeNeeded = inAmount > nAmount;

if (type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE)
subtract = (BLSCT_DEFAULT_FEE * (tx.vInputs.size() + 1 + fChangeNeeded));
bool fSubtractFeeFromAmount = false; // type == CreateTransactionType::STAKED_COMMITMENT_UNSTAKE;

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

return tx.BuildTx(changeDestination, minStake, type);
Expand Down
2 changes: 1 addition & 1 deletion src/blsct/wallet/txfactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class TxFactoryBase
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);
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);
Expand Down
11 changes: 10 additions & 1 deletion src/blsct/wallet/txfactory_global.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ using Points = Elements<Point>;
using Scalar = T::Scalar;
using Scalars = Elements<Scalar>;

#define BLSCT_DEFAULT_FEE 200000
#define BLSCT_DEFAULT_FEE 50

namespace blsct {
struct UnsignedOutput {
Expand Down Expand Up @@ -68,6 +68,15 @@ enum CreateTransactionType {
CTransactionRef
AggregateTransactions(const std::vector<CTransactionRef>& txs);
UnsignedOutput CreateOutput(const blsct::DoublePublicKey& destination, const CAmount& nAmount, std::string sMemo, const TokenId& tokenId = TokenId(), const Scalar& blindingKey = Scalar::Rand(), const CreateTransactionType& type = NORMAL, const CAmount& minStake = 0);
int32_t GetTransactionWeight(const CTransaction& tx)
{
return ::GetSerializeSize(TX_WITH_WITNESS(tx));
}

int32_t GetTransactioOutputWeight(const CTxOut& out)
{
return ::GetSerializeSize(out);
}
} // namespace blsct

#endif // TXFACTORY_GLOBAL_H

0 comments on commit 3e6d826

Please sign in to comment.