Browse Source

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.
pull/67/head
catbref 5 years ago
parent
commit
9af18aad34
  1. 2
      src/main/java/org/qora/repository/AccountRepository.java
  2. 21
      src/main/java/org/qora/transaction/ProxyForgingTransaction.java
  3. 12
      src/test/java/org/qora/test/common/AccountUtils.java
  4. 110
      src/test/java/org/qora/test/forging/ProxyForgingTests.java
  5. 1
      src/test/resources/test-chain-v2.json

2
src/main/java/org/qora/repository/AccountRepository.java

@ -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;
}

21
src/main/java/org/qora/transaction/ProxyForgingTransaction.java

@ -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

12
src/test/java/org/qora/test/common/AccountUtils.java

@ -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

@ -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);
}
}
}

1
src/test/resources/test-chain-v2.json

@ -8,6 +8,7 @@
"maxBytesPerUnitFee": 1024,
"unitFee": "0.1",
"requireGroupForApproval": false,
"maxProxyRelationships": 8,
"genesisInfo": {
"version": 4,
"timestamp": 0,

Loading…
Cancel
Save