forked from Qortal/qortal
Setting proxy forging reward share to 0% removes proxy forging relationship.
Included unit test to cover change. Modified test blockchain config "test-chain-v2.json" to add maxProxyRelationships. Added comments to some proxy-related methods in AccountRepository class.
This commit is contained in:
parent
46dc91e5a0
commit
9af18aad34
@ -99,6 +99,7 @@ public interface AccountRepository {
|
||||
|
||||
public void save(ProxyForgerData proxyForgerData) throws DataException;
|
||||
|
||||
/** Delete proxy forging relationship from repository using passed forger's public key and recipient's address. */
|
||||
public void delete(byte[] forgerPublickey, String recipient) throws DataException;
|
||||
|
||||
// Forging accounts used by BlockGenerator
|
||||
@ -107,6 +108,7 @@ public interface AccountRepository {
|
||||
|
||||
public void save(ForgingAccountData forgingAccountData) throws DataException;
|
||||
|
||||
/** Delete forging account info, used by BlockGenerator, from repository using passed private key. */
|
||||
public int delete(byte[] forgingAccountSeed) throws DataException;
|
||||
|
||||
}
|
||||
|
@ -97,13 +97,19 @@ public class ProxyForgingTransaction extends Transaction {
|
||||
if (!Crypto.isValidAddress(recipient.getAddress()))
|
||||
return ValidationResult.INVALID_ADDRESS;
|
||||
|
||||
// If proxy public key aleady exists in repository, then it must be for the same forger-recipient combo
|
||||
// If proxy public key already exists in repository, then it must be for the same forger-recipient combo
|
||||
ProxyForgerData proxyForgerData = this.repository.getAccountRepository().getProxyForgeData(this.proxyForgingTransactionData.getProxyPublicKey());
|
||||
if (proxyForgerData != null) {
|
||||
if (!proxyForgerData.getRecipient().equals(recipient.getAddress()) || !Arrays.equals(proxyForgerData.getForgerPublicKey(), creator.getPublicKey()))
|
||||
return ValidationResult.INVALID_PUBLIC_KEY;
|
||||
} else {
|
||||
// This is a new relationship - check that the generator hasn't reach maximum number of relationships
|
||||
// This is a new relationship
|
||||
|
||||
// No point starting a new relationship with 0% share (i.e. delete relationship)
|
||||
if (this.proxyForgingTransactionData.getShare().compareTo(BigDecimal.ZERO) == 0)
|
||||
return ValidationResult.INVALID_FORGE_SHARE;
|
||||
|
||||
// Check that the generator hasn't reach maximum number of relationships
|
||||
int relationshipCount = this.repository.getAccountRepository().countProxyAccounts(creator.getPublicKey());
|
||||
if (relationshipCount >= BlockChain.getInstance().getMaxProxyRelationships())
|
||||
return ValidationResult.MAXIMUM_PROXY_RELATIONSHIPS;
|
||||
@ -134,9 +140,14 @@ public class ProxyForgingTransaction extends Transaction {
|
||||
// Save this transaction, with previous share info
|
||||
this.repository.getTransactionRepository().save(proxyForgingTransactionData);
|
||||
|
||||
// Save proxy forging info
|
||||
proxyForgerData = new ProxyForgerData(forger.getPublicKey(), proxyForgingTransactionData.getRecipient(), proxyForgingTransactionData.getProxyPublicKey(), proxyForgingTransactionData.getShare());
|
||||
this.repository.getAccountRepository().save(proxyForgerData);
|
||||
// 0% share is actually a request to delete existing relationship
|
||||
if (proxyForgingTransactionData.getShare().compareTo(BigDecimal.ZERO) == 0) {
|
||||
this.repository.getAccountRepository().delete(forger.getPublicKey(), proxyForgingTransactionData.getRecipient());
|
||||
} else {
|
||||
// Save proxy forging info
|
||||
proxyForgerData = new ProxyForgerData(forger.getPublicKey(), proxyForgingTransactionData.getRecipient(), proxyForgingTransactionData.getProxyPublicKey(), proxyForgingTransactionData.getShare());
|
||||
this.repository.getAccountRepository().save(proxyForgerData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,7 +33,7 @@ public class AccountUtils {
|
||||
TransactionUtils.signAndForge(repository, transactionData, sendingAccount);
|
||||
}
|
||||
|
||||
public static byte[] proxyForging(Repository repository, String forger, String recipient, BigDecimal share) throws DataException {
|
||||
public static TransactionData createProxyForging(Repository repository, String forger, String recipient, BigDecimal share) throws DataException {
|
||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, forger);
|
||||
PrivateKeyAccount recipientAccount = Common.getTestAccount(repository, recipient);
|
||||
|
||||
@ -46,8 +46,18 @@ public class AccountUtils {
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, forgingAccount.getPublicKey(), fee, null);
|
||||
TransactionData transactionData = new ProxyForgingTransactionData(baseTransactionData, recipientAccount.getAddress(), proxyAccount.getPublicKey(), share);
|
||||
|
||||
return transactionData;
|
||||
}
|
||||
|
||||
public static byte[] proxyForging(Repository repository, String forger, String recipient, BigDecimal share) throws DataException {
|
||||
TransactionData transactionData = createProxyForging(repository, forger, recipient, share);
|
||||
|
||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, forger);
|
||||
TransactionUtils.signAndForge(repository, transactionData, forgingAccount);
|
||||
|
||||
PrivateKeyAccount recipientAccount = Common.getTestAccount(repository, recipient);
|
||||
byte[] proxyPrivateKey = forgingAccount.getSharedSecret(recipientAccount.getPublicKey());
|
||||
|
||||
return proxyPrivateKey;
|
||||
}
|
||||
|
||||
|
110
src/test/java/org/qora/test/forging/ProxyForgingTests.java
Normal file
110
src/test/java/org/qora/test/forging/ProxyForgingTests.java
Normal file
@ -0,0 +1,110 @@
|
||||
package org.qora.test.forging;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.data.account.ProxyForgerData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
import org.qora.test.common.AccountUtils;
|
||||
import org.qora.test.common.BlockUtils;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.utils.Base58;
|
||||
|
||||
public class ProxyForgingTests extends Common {
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws DataException {
|
||||
Common.orphanCheck();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRelationship() throws DataException {
|
||||
final BigDecimal share = new BigDecimal("12.8");
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount aliceAccount = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bobAccount = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create relationship
|
||||
byte[] proxyPrivateKey = AccountUtils.proxyForging(repository, "alice", "bob", share);
|
||||
PrivateKeyAccount proxyAccount = new PrivateKeyAccount(repository, proxyPrivateKey);
|
||||
|
||||
// Confirm relationship info set correctly
|
||||
|
||||
// Fetch using proxy public key
|
||||
ProxyForgerData proxyForgerData = repository.getAccountRepository().getProxyForgeData(proxyAccount.getPublicKey());
|
||||
assertEquals("Incorrect generator public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(proxyForgerData.getForgerPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), proxyForgerData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect reward share", share, proxyForgerData.getShare());
|
||||
|
||||
// Fetch using generator public key and recipient address combination
|
||||
proxyForgerData = repository.getAccountRepository().getProxyForgeData(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertEquals("Incorrect generator public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(proxyForgerData.getForgerPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), proxyForgerData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect reward share", share, proxyForgerData.getShare());
|
||||
|
||||
// Delete relationship
|
||||
byte[] newProxyPrivateKey = AccountUtils.proxyForging(repository, "alice", "bob", BigDecimal.ZERO);
|
||||
PrivateKeyAccount newProxyAccount = new PrivateKeyAccount(repository, newProxyPrivateKey);
|
||||
|
||||
// Confirm proxy keys match
|
||||
assertEquals("Proxy private keys differ", Base58.encode(proxyPrivateKey), Base58.encode(newProxyPrivateKey));
|
||||
assertEquals("Proxy public keys differ", Base58.encode(proxyAccount.getPublicKey()), Base58.encode(newProxyAccount.getPublicKey()));
|
||||
|
||||
// Confirm relationship no longer exists in repository
|
||||
|
||||
// Fetch using proxy public key
|
||||
ProxyForgerData newProxyForgerData = repository.getAccountRepository().getProxyForgeData(proxyAccount.getPublicKey());
|
||||
assertNull("Proxy relationship data shouldn't exist", newProxyForgerData);
|
||||
|
||||
// Fetch using generator public key and recipient address combination
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNull("Proxy relationship data shouldn't exist", newProxyForgerData);
|
||||
|
||||
// Orphan last block to restore prior proxy relationship
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm proxy relationship restored correctly
|
||||
|
||||
// Fetch using proxy public key
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(proxyAccount.getPublicKey());
|
||||
assertNotNull("Proxy relationship data should have been restored", newProxyForgerData);
|
||||
assertEquals("Incorrect generator public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(newProxyForgerData.getForgerPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), newProxyForgerData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect reward share", share, newProxyForgerData.getShare());
|
||||
|
||||
// Fetch using generator public key and recipient address combination
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNotNull("Proxy relationship data should have been restored", newProxyForgerData);
|
||||
assertEquals("Incorrect generator public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(newProxyForgerData.getForgerPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), newProxyForgerData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect reward share", share, newProxyForgerData.getShare());
|
||||
|
||||
// Orphan another block to remove initial proxy relationship
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm proxy relationship no longer exists
|
||||
|
||||
// Fetch using proxy public key
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(proxyAccount.getPublicKey());
|
||||
assertNull("Proxy relationship data shouldn't exist", newProxyForgerData);
|
||||
|
||||
// Fetch using generator public key and recipient address combination
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNull("Proxy relationship data shouldn't exist", newProxyForgerData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
"maxBytesPerUnitFee": 1024,
|
||||
"unitFee": "0.1",
|
||||
"requireGroupForApproval": false,
|
||||
"maxProxyRelationships": 8,
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
"timestamp": 0,
|
||||
|
Loading…
Reference in New Issue
Block a user