Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(freezeV2): optimize unfreeze vote #4741

Merged
merged 1 commit into from
Oct 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package org.tron.core.actuator;

import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR;
import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD;
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;

import com.google.common.collect.Lists;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.tron.common.utils.DecodeUtil;
Expand All @@ -19,17 +26,10 @@
import org.tron.protos.Protocol;
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
import org.tron.protos.Protocol.Transaction.Result.code;
import org.tron.protos.Protocol.Vote;
import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract;
import org.tron.protos.contract.Common;

import java.util.Iterator;
import java.util.List;
import java.util.Objects;

import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR;
import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD;
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;

@Slf4j(topic = "actuator")
public class UnfreezeBalanceV2Actuator extends AbstractActuator {

Expand Down Expand Up @@ -81,7 +81,7 @@ public boolean execute(Object result) throws ContractExeException {
accountCapsule.addUnfrozenV2List(freezeType, unfreezeBalance, expireTime);

this.updateTotalResourceWeight(unfreezeBalanceV2Contract, unfreezeBalance);
this.clearVotes(accountCapsule,unfreezeBalanceV2Contract, ownerAddress);
this.updateVote(accountCapsule, unfreezeBalanceV2Contract, ownerAddress);

if (dynamicStore.supportAllowNewResourceModel()
&& !accountCapsule.oldTronPowerIsInvalid()) {
Expand Down Expand Up @@ -154,7 +154,7 @@ public boolean validate() throws ContractValidateException {
throw new ContractValidateException("no frozenBalance(TronPower)");
}
} else {
throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]");
throw new ContractValidateException("ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]");
}
break;
default:
Expand All @@ -167,7 +167,7 @@ public boolean validate() throws ContractValidateException {

if (!checkUnfreezeBalance(accountCapsule, unfreezeBalanceV2Contract, unfreezeBalanceV2Contract.getResource())) {
throw new ContractValidateException(
"Invalid unfreeze_balance, [" + unfreezeBalanceV2Contract.getUnfreezeBalance() + "] is error"
"Invalid unfreeze_balance, [" + unfreezeBalanceV2Contract.getUnfreezeBalance() + "] is error"
);
}

Expand Down Expand Up @@ -208,8 +208,8 @@ public boolean checkExistFreezedBalance(AccountCapsule accountCapsule, Common.Re
}

public boolean checkUnfreezeBalance(AccountCapsule accountCapsule,
final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract,
Common.ResourceCode freezeType) {
final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract,
Common.ResourceCode freezeType) {
boolean checkOk = false;

long frozenAmount = 0L;
Expand All @@ -222,7 +222,7 @@ public boolean checkUnfreezeBalance(AccountCapsule accountCapsule,
}

if (unfreezeBalanceV2Contract.getUnfreezeBalance() > 0
&& unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) {
&& unfreezeBalanceV2Contract.getUnfreezeBalance() <= frozenAmount) {
checkOk = true;
}

Expand All @@ -240,10 +240,10 @@ public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsu
List<Protocol.Account.FreezeV2> freezeV2List = accountCapsule.getFrozenV2List();
for (int i = 0; i < freezeV2List.size(); i++) {
if (freezeV2List.get(i).getType().equals(freezeType)) {
Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder()
.setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance)
.setType(freezeV2List.get(i).getType())
.build();
Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder()
.setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance)
.setType(freezeV2List.get(i).getType())
.build();
accountCapsule.updateFrozenV2List(i, freezeV2);
break;
}
Expand All @@ -266,15 +266,15 @@ public void unfreezeExpire(AccountCapsule accountCapsule, long now) {
}

accountCapsule.setInstance(
accountCapsule.getInstance().toBuilder()
accountCapsule.getInstance().toBuilder()
.setBalance(accountCapsule.getBalance() + unfreezeBalance)
.clearUnfrozenV2()
.addAllUnfrozenV2(unFrozenV2List).build()
);
}

public void updateTotalResourceWeight(final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract,
long unfreezeBalance) {
long unfreezeBalance) {
DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore();
switch (unfreezeBalanceV2Contract.getResource()) {
case BANDWIDTH:
Expand All @@ -292,38 +292,86 @@ public void updateTotalResourceWeight(final UnfreezeBalanceV2Contract unfreezeBa
}
}

private void clearVotes(AccountCapsule accountCapsule,
private void updateVote(AccountCapsule accountCapsule,
final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract,
byte[] ownerAddress) {
DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore();
VotesStore votesStore = chainBaseManager.getVotesStore();

boolean needToClearVote = true;
if (dynamicStore.supportAllowNewResourceModel()
&& accountCapsule.oldTronPowerIsInvalid()) {
switch (unfreezeBalanceV2Contract.getResource()) {
case BANDWIDTH:
case ENERGY:
needToClearVote = false;
break;
default:
break;
if (accountCapsule.getVotesList().isEmpty()) {
return;
}
if (dynamicStore.supportAllowNewResourceModel()) {
if (accountCapsule.oldTronPowerIsInvalid()) {
switch (unfreezeBalanceV2Contract.getResource()) {
case BANDWIDTH:
case ENERGY:
// there is no need to change votes
return;
default:
break;
}
} else {
// clear all votes at once when new resource model start
VotesCapsule votesCapsule;
if (!votesStore.has(ownerAddress)) {
votesCapsule = new VotesCapsule(
unfreezeBalanceV2Contract.getOwnerAddress(),
accountCapsule.getVotesList()
);
} else {
votesCapsule = votesStore.get(ownerAddress);
}
accountCapsule.clearVotes();
votesCapsule.clearNewVotes();
votesStore.put(ownerAddress, votesCapsule);
return;
}
}

if (needToClearVote) {
VotesCapsule votesCapsule;
if (!votesStore.has(ownerAddress)) {
votesCapsule = new VotesCapsule(
unfreezeBalanceV2Contract.getOwnerAddress(),
accountCapsule.getVotesList()
);
} else {
votesCapsule = votesStore.get(ownerAddress);
long totalVote = 0;
for (Protocol.Vote vote : accountCapsule.getVotesList()) {
totalVote += vote.getVoteCount();
}
long ownedTronPower;
if (dynamicStore.supportAllowNewResourceModel()) {
ownedTronPower = accountCapsule.getAllTronPower();
} else {
ownedTronPower = accountCapsule.getTronPower();
}

// tron power is enough to total votes
if (ownedTronPower >= totalVote * TRX_PRECISION) {
return;
}
if (totalVote == 0) {
return;
}

VotesCapsule votesCapsule;
if (!votesStore.has(ownerAddress)) {
votesCapsule = new VotesCapsule(
unfreezeBalanceV2Contract.getOwnerAddress(),
accountCapsule.getVotesList()
);
} else {
votesCapsule = votesStore.get(ownerAddress);
}

// Update Owner Voting
votesCapsule.clearNewVotes();
for (Vote vote : accountCapsule.getVotesList()) {
long newVoteCount = (long)
((double) vote.getVoteCount() / totalVote * ownedTronPower / TRX_PRECISION);
if (newVoteCount > 0) {
votesCapsule.addNewVotes(vote.getVoteAddress(), newVoteCount);
}
accountCapsule.clearVotes();
votesCapsule.clearNewVotes();
votesStore.put(ownerAddress, votesCapsule);
}
votesStore.put(ownerAddress, votesCapsule);

accountCapsule.clearVotes();
for (Vote vote : votesCapsule.getNewVotes()) {
accountCapsule.addVotes(vote.getVoteAddress(), vote.getVoteCount());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.junit.AfterClass;
import org.junit.Assert;
Expand Down Expand Up @@ -318,57 +316,60 @@ public void noFrozenBalance() {
}

@Test
public void testClearVotes() {
public void testVotes() {
byte[] ownerAddressBytes = ByteArray.fromHexString(OWNER_ADDRESS);
ByteString ownerAddress = ByteString.copyFrom(ownerAddressBytes);
long unfreezeBalance = frozenBalance;
long unfreezeBalance = frozenBalance / 2;
long now = System.currentTimeMillis();
dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now);

dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(0);
AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddressBytes);
accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000_000L);

accountCapsule.addVotes(ByteString.copyFrom(RECEIVER_ADDRESS.getBytes()), 500);
accountCapsule.addVotes(ByteString.copyFrom(OWNER_ACCOUNT_INVALID.getBytes()), 500);
dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule);

UnfreezeBalanceV2Actuator actuator = new UnfreezeBalanceV2Actuator();
actuator.setChainBaseManager(dbManager.getChainBaseManager())
.setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance));
TransactionResultCapsule ret = new TransactionResultCapsule();

dbManager.getVotesStore().reset();
Assert.assertNull(dbManager.getVotesStore().get(ownerAddressBytes));
try {
actuator.validate();
actuator.execute(ret);
VotesCapsule votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes);
Assert.assertNotNull(votesCapsule);
Assert.assertEquals(0, votesCapsule.getNewVotes().size());
} catch (ContractValidateException e) {
Assert.assertFalse(e instanceof ContractValidateException);
} catch (ContractExeException e) {
Assert.assertFalse(e instanceof ContractExeException);
for (Vote vote : votesCapsule.getOldVotes()) {
Assert.assertEquals(vote.getVoteCount(), 500);
}
for (Vote vote : votesCapsule.getNewVotes()) {
Assert.assertEquals(vote.getVoteCount(), 250);
}
accountCapsule = dbManager.getAccountStore().get(ownerAddressBytes);
for (Vote vote : accountCapsule.getVotesList()) {
Assert.assertEquals(vote.getVoteCount(), 250);
}
} catch (ContractValidateException | ContractExeException e) {
Assert.fail("cannot run here.");
}

// if had votes
List<Vote> oldVotes = new ArrayList<Vote>();
VotesCapsule votesCapsule = new VotesCapsule(
ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), oldVotes);
votesCapsule.addNewVotes(
ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), 100);
dbManager.getVotesStore().put(ByteArray.fromHexString(OWNER_ADDRESS), votesCapsule);
accountCapsule.addFrozenBalanceForBandwidthV2(1_000_000_000L);
dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule);
// clear for new resource model
dbManager.getDynamicPropertiesStore().saveAllowNewResourceModel(1);
actuator.setChainBaseManager(dbManager.getChainBaseManager())
.setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance / 2));
try {
actuator.validate();
actuator.execute(ret);
votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes);
VotesCapsule votesCapsule = dbManager.getVotesStore().get(ownerAddressBytes);
Assert.assertNotNull(votesCapsule);
for (Vote vote : votesCapsule.getOldVotes()) {
Assert.assertEquals(vote.getVoteCount(), 500);
}
Assert.assertEquals(0, votesCapsule.getNewVotes().size());
} catch (ContractValidateException e) {
Assert.assertFalse(e instanceof ContractValidateException);
} catch (ContractExeException e) {
Assert.assertFalse(e instanceof ContractExeException);
accountCapsule = dbManager.getAccountStore().get(ownerAddressBytes);
Assert.assertEquals(0, accountCapsule.getVotesList().size());
} catch (ContractValidateException | ContractExeException e) {
Assert.fail("cannot run here.");
}

}

@Test
Expand Down