Skip to content

Commit

Permalink
PPCoin: Allow multiple outputs for coinbase and coinstake
Browse files Browse the repository at this point in the history
        Upgrade requirements: upgrade with deadline, possible fork
  • Loading branch information
sunnyking committed Aug 24, 2012
1 parent 2a4202a commit 4ffa595
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1232,7 +1232,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs,
if (!GetCoinAge(txdb, nCoinAge))
return error("ConnectInputs() : %s unable to get coin age for coinstake", GetHash().ToString().substr(0,10).c_str());
int64 nStakeReward = GetValueOut() - nValueIn;
if (nStakeReward > GetProofOfStakeReward(nCoinAge))
if (nStakeReward > GetProofOfStakeReward(nCoinAge) - GetMinFee() + MIN_TX_FEE)
return DoS(100, error("ConnectInputs() : %s stake reward exceeded", GetHash().ToString().substr(0,10).c_str()));
}
else
Expand Down Expand Up @@ -1908,7 +1908,7 @@ bool CBlock::CheckBlock() const
return DoS(50, error("CheckBlock() : coinstake timestamp is too early"));

// Check coinbase reward
if (vtx[0].GetValueOut() > (IsProofOfWork()? GetProofOfWorkReward(nBits) : 0))
if (vtx[0].GetValueOut() > (IsProofOfWork()? (GetProofOfWorkReward(nBits) - vtx[0].GetMinFee() + MIN_TX_FEE) : 0))
return DoS(50, error("CheckBlock() : coinbase reward exceeded %s > %s",
FormatMoney(vtx[0].GetValueOut()).c_str(),
FormatMoney(IsProofOfWork()? GetProofOfWorkReward(nBits) : 0).c_str()));
Expand Down
4 changes: 2 additions & 2 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,13 +502,13 @@ class CTransaction

bool IsCoinBase() const
{
return (vin.size() == 1 && vin[0].prevout.IsNull() && vout.size() == 1);
return (vin.size() == 1 && vin[0].prevout.IsNull() && vout.size() >= 1);
}

bool IsCoinStake() const
{
// ppcoin: the coin stake transaction is marked with the first output empty
return (vin.size() > 0 && vout.size() == 2 && vout[0].IsEmpty());
return (vin.size() > 0 && (!vin[0].prevout.IsNull()) && vout.size() >= 2 && vout[0].IsEmpty());
}

/** Check for standard transaction types
Expand Down
42 changes: 30 additions & 12 deletions src/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1288,21 +1288,39 @@ bool CWallet::CreateCoinStake(unsigned int nBits, CTransaction& txNew)
return error("CreateCoinStake : failed to calculate coin age");
nCredit += GetProofOfStakeReward(nCoinAge);
}
// Set output amount
txNew.vout[1].nValue = nCredit;

// Sign
int nIn = 0;
BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev)
int64 nMinFee = 0;
loop
{
if (!SignSignature(*this, *pcoin, txNew, nIn++))
return error("CreateCoinStake : failed to sign coinstake");
}
// Set output amount
txNew.vout[1].nValue = nCredit - nMinFee;

// Limit size
unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
return false;
// Sign
int nIn = 0;
BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev)
{
if (!SignSignature(*this, *pcoin, txNew, nIn++))
return error("CreateCoinStake : failed to sign coinstake");
}

// Limit size
unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
return false;

// Check enough fee is paid
if (nMinFee < txNew.GetMinFee() - MIN_TX_FEE)
{
nMinFee = txNew.GetMinFee() - MIN_TX_FEE;
continue; // try signing again
}
else
{
if (fDebug && GetBoolArg("-printfee"))
printf("CreateCoinStake : fee for coinstake %s\n", FormatMoney(nMinFee).c_str());
break;
}
}

// Successfully generated coinstake
return true;
Expand Down

0 comments on commit 4ffa595

Please sign in to comment.