forked from Qortal/qortal
Proxy forging improvements + account flags fixes
Proxy forging recipient no longer needs a public key on the blockchain at the point PROXY_FORGING transaction is submitted. Proxy forging recipient is given a last-reference, if they don't have one, when they receive their first block rewards. Split block fees in proxy forging scenario, using same share proportion. 100% proxy sharing is now allowed. Fixed account flags processing for accounts in genesis block.
This commit is contained in:
parent
3ffcf50d7c
commit
7a318c9fc7
@ -1050,10 +1050,8 @@ public class Block {
|
||||
for (Transaction transaction : transactions)
|
||||
transaction.process();
|
||||
|
||||
// If fees are non-zero then add fees to generator's balance
|
||||
BigDecimal blockFee = this.blockData.getTotalFees();
|
||||
if (blockFee.compareTo(BigDecimal.ZERO) > 0)
|
||||
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).add(blockFee));
|
||||
// Give transaction fees to generator/proxy
|
||||
rewardTransactionFees();
|
||||
|
||||
// Process AT fees and save AT states into repository
|
||||
ATRepository atRepository = this.repository.getATRepository();
|
||||
@ -1102,7 +1100,7 @@ public class Block {
|
||||
// Is generator public key actually a proxy forge key?
|
||||
ProxyForgerData proxyForgerData = this.repository.getAccountRepository().getProxyForgeData(this.blockData.getGeneratorPublicKey());
|
||||
if (proxyForgerData != null) {
|
||||
// Split reward to forger and recipient;
|
||||
// Split reward between forger and recipient
|
||||
Account recipient = new Account(this.repository, proxyForgerData.getRecipient());
|
||||
BigDecimal recipientShare = reward.multiply(proxyForgerData.getShare().movePointLeft(2)).setScale(8, RoundingMode.DOWN);
|
||||
recipient.setConfirmedBalance(Asset.QORA, recipient.getConfirmedBalance(Asset.QORA).add(recipientShare));
|
||||
@ -1117,6 +1115,31 @@ public class Block {
|
||||
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).add(reward));
|
||||
}
|
||||
|
||||
protected void rewardTransactionFees() throws DataException {
|
||||
BigDecimal blockFees = this.blockData.getTotalFees();
|
||||
|
||||
// No transaction fees?
|
||||
if (blockFees.compareTo(BigDecimal.ZERO) <= 0)
|
||||
return;
|
||||
|
||||
// Is generator public key actually a proxy forge key?
|
||||
ProxyForgerData proxyForgerData = this.repository.getAccountRepository().getProxyForgeData(this.blockData.getGeneratorPublicKey());
|
||||
if (proxyForgerData != null) {
|
||||
// Split fees between forger and recipient
|
||||
Account recipient = new Account(this.repository, proxyForgerData.getRecipient());
|
||||
BigDecimal recipientShare = blockFees.multiply(proxyForgerData.getShare().movePointLeft(2)).setScale(8, RoundingMode.DOWN);
|
||||
recipient.setConfirmedBalance(Asset.QORA, recipient.getConfirmedBalance(Asset.QORA).add(recipientShare));
|
||||
|
||||
Account forger = new PublicKeyAccount(this.repository, proxyForgerData.getForgerPublicKey());
|
||||
BigDecimal forgerShare = blockFees.subtract(recipientShare);
|
||||
forger.setConfirmedBalance(Asset.QORA, forger.getConfirmedBalance(Asset.QORA).add(forgerShare));
|
||||
return;
|
||||
}
|
||||
|
||||
// Give transaction fees to generator
|
||||
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).add(blockFees));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes block from blockchain undoing transactions and adding them to unconfirmed pile.
|
||||
*
|
||||
@ -1145,10 +1168,8 @@ public class Block {
|
||||
// Block rewards removed after transactions undone
|
||||
orphanBlockRewards();
|
||||
|
||||
// If fees are non-zero then remove fees from generator's balance
|
||||
BigDecimal blockFee = this.blockData.getTotalFees();
|
||||
if (blockFee.compareTo(BigDecimal.ZERO) > 0)
|
||||
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).subtract(blockFee));
|
||||
// Deduct any transaction fees from generator/proxy
|
||||
deductTransactionFees();
|
||||
|
||||
// Return AT fees and delete AT states from repository
|
||||
ATRepository atRepository = this.repository.getATRepository();
|
||||
@ -1175,7 +1196,7 @@ public class Block {
|
||||
// Is generator public key actually a proxy forge key?
|
||||
ProxyForgerData proxyForgerData = this.repository.getAccountRepository().getProxyForgeData(this.blockData.getGeneratorPublicKey());
|
||||
if (proxyForgerData != null) {
|
||||
// Split reward from forger and recipient;
|
||||
// Split reward between forger and recipient
|
||||
Account recipient = new Account(this.repository, proxyForgerData.getRecipient());
|
||||
BigDecimal recipientShare = reward.multiply(proxyForgerData.getShare().movePointLeft(2)).setScale(8, RoundingMode.DOWN);
|
||||
recipient.setConfirmedBalance(Asset.QORA, recipient.getConfirmedBalance(Asset.QORA).subtract(recipientShare));
|
||||
@ -1190,6 +1211,31 @@ public class Block {
|
||||
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).subtract(reward));
|
||||
}
|
||||
|
||||
protected void deductTransactionFees() throws DataException {
|
||||
BigDecimal blockFees = this.blockData.getTotalFees();
|
||||
|
||||
// No transaction fees?
|
||||
if (blockFees.compareTo(BigDecimal.ZERO) <= 0)
|
||||
return;
|
||||
|
||||
// Is generator public key actually a proxy forge key?
|
||||
ProxyForgerData proxyForgerData = this.repository.getAccountRepository().getProxyForgeData(this.blockData.getGeneratorPublicKey());
|
||||
if (proxyForgerData != null) {
|
||||
// Split fees between forger and recipient
|
||||
Account recipient = new Account(this.repository, proxyForgerData.getRecipient());
|
||||
BigDecimal recipientShare = blockFees.multiply(proxyForgerData.getShare().movePointLeft(2)).setScale(8, RoundingMode.DOWN);
|
||||
recipient.setConfirmedBalance(Asset.QORA, recipient.getConfirmedBalance(Asset.QORA).subtract(recipientShare));
|
||||
|
||||
Account forger = new PublicKeyAccount(this.repository, proxyForgerData.getForgerPublicKey());
|
||||
BigDecimal forgerShare = blockFees.subtract(recipientShare);
|
||||
forger.setConfirmedBalance(Asset.QORA, forger.getConfirmedBalance(Asset.QORA).subtract(forgerShare));
|
||||
return;
|
||||
}
|
||||
|
||||
// Deduct transaction fees to generator
|
||||
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).subtract(blockFees));
|
||||
}
|
||||
|
||||
protected BigDecimal getRewardAtHeight(int ourHeight) {
|
||||
List<RewardByHeight> rewardsByHeight = BlockChain.getInstance().getBlockRewardsByHeight();
|
||||
|
||||
|
@ -78,7 +78,6 @@ public class HSQLDBAccountRepository implements AccountRepository {
|
||||
if (resultSet == null)
|
||||
return null;
|
||||
|
||||
// Column is NOT NULL so this should never implicitly convert to 0
|
||||
return resultSet.getInt(1);
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Unable to fetch account's flags from repository", e);
|
||||
|
@ -91,13 +91,17 @@ public class AccountFlagsTransaction extends Transaction {
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
Account target = getTarget();
|
||||
int previousFlags = target.getFlags();
|
||||
Integer previousFlags = target.getFlags();
|
||||
|
||||
accountFlagsTransactionData.setPreviousFlags(previousFlags);
|
||||
|
||||
// Save this transaction with target account's previous flags value
|
||||
this.repository.getTransactionRepository().save(accountFlagsTransactionData);
|
||||
|
||||
// If account doesn't have entry in database yet (e.g. genesis block) then flags are zero
|
||||
if (previousFlags == null)
|
||||
previousFlags = 0;
|
||||
|
||||
// Set account's new flags
|
||||
int newFlags = previousFlags & accountFlagsTransactionData.getAndMask()
|
||||
| accountFlagsTransactionData.getOrMask() ^ accountFlagsTransactionData.getXorMask();
|
||||
@ -117,7 +121,13 @@ public class AccountFlagsTransaction extends Transaction {
|
||||
// Revert
|
||||
Account target = getTarget();
|
||||
|
||||
target.setFlags(accountFlagsTransactionData.getPreviousFlags());
|
||||
Integer previousFlags = accountFlagsTransactionData.getPreviousFlags();
|
||||
|
||||
// If previousFlags are null then account didn't exist before this transaction
|
||||
if (previousFlags == null)
|
||||
this.repository.getAccountRepository().delete(target.getAddress());
|
||||
else
|
||||
target.setFlags(previousFlags);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(accountFlagsTransactionData);
|
||||
|
@ -10,7 +10,6 @@ import org.qora.account.Forging;
|
||||
import org.qora.account.PublicKeyAccount;
|
||||
import org.qora.asset.Asset;
|
||||
import org.qora.crypto.Crypto;
|
||||
import org.qora.data.account.AccountData;
|
||||
import org.qora.data.account.ProxyForgerData;
|
||||
import org.qora.data.transaction.ProxyForgingTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
@ -80,7 +79,7 @@ public class ProxyForgingTransaction extends Transaction {
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Check reward share given to recipient
|
||||
if (this.proxyForgingTransactionData.getShare().compareTo(BigDecimal.ZERO) <= 0
|
||||
|| this.proxyForgingTransactionData.getShare().compareTo(MAX_SHARE) >= 0)
|
||||
|| this.proxyForgingTransactionData.getShare().compareTo(MAX_SHARE) > 0)
|
||||
return ValidationResult.INVALID_FORGE_SHARE;
|
||||
|
||||
PublicKeyAccount creator = getCreator();
|
||||
@ -97,10 +96,12 @@ public class ProxyForgingTransaction extends Transaction {
|
||||
if (!Crypto.isValidAddress(recipient.getAddress()))
|
||||
return ValidationResult.INVALID_ADDRESS;
|
||||
|
||||
/* Not needed?
|
||||
// Check recipient has known public key
|
||||
AccountData recipientData = this.repository.getAccountRepository().getAccount(recipient.getAddress());
|
||||
if (recipientData == null || recipientData.getPublicKey() == null)
|
||||
return ValidationResult.PUBLIC_KEY_UNKNOWN;
|
||||
*/
|
||||
|
||||
// Check fee is positive
|
||||
if (proxyForgingTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
|
||||
@ -140,6 +141,11 @@ public class ProxyForgingTransaction extends Transaction {
|
||||
|
||||
// Update forger's reference
|
||||
forger.setLastReference(proxyForgingTransactionData.getSignature());
|
||||
|
||||
// If proxy recipient has no last-reference then use this transaction's signature as last-reference so they can spend their block rewards
|
||||
Account recipient = new Account(this.repository, proxyForgingTransactionData.getRecipient());
|
||||
if (recipient.getLastReference() == null)
|
||||
recipient.setLastReference(proxyForgingTransactionData.getSignature());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -166,6 +172,11 @@ public class ProxyForgingTransaction extends Transaction {
|
||||
|
||||
// Update forger's reference
|
||||
forger.setLastReference(proxyForgingTransactionData.getReference());
|
||||
|
||||
// If recipient didn't have a last-reference prior to this transaction then remove it
|
||||
Account recipient = new Account(this.repository, proxyForgingTransactionData.getRecipient());
|
||||
if (Arrays.equals(recipient.getLastReference(), proxyForgingTransactionData.getSignature()))
|
||||
recipient.setLastReference(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user