Skip to content

Commit 3899187

Browse files
authored
Merge pull request tronprotocol#2014 from tronprotocol/release_v3.5
Release v3.5
2 parents 042f0dd + eb4ecaa commit 3899187

16 files changed

+438
-3
lines changed

src/main/java/org/tron/core/actuator/TransferActuator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import org.tron.core.exception.BalanceInsufficientException;
1515
import org.tron.core.exception.ContractExeException;
1616
import org.tron.core.exception.ContractValidateException;
17+
import org.tron.core.exception.WhitelistException;
18+
import org.tron.core.services.WhitelistService;
1719
import org.tron.protos.Contract.TransferContract;
1820
import org.tron.protos.Protocol.AccountType;
1921
import org.tron.protos.Protocol.Transaction.Result.code;
@@ -115,7 +117,6 @@ public boolean validate() throws ContractValidateException {
115117
}
116118

117119
try {
118-
119120
AccountCapsule toAccount = dbManager.getAccountStore().get(toAddress);
120121
if (toAccount == null) {
121122
fee = fee + dbManager.getDynamicPropertiesStore().getCreateNewAccountFeeInSystemContract();

src/main/java/org/tron/core/config/args/Args.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.beust.jcommander.JCommander;
44
import com.beust.jcommander.Parameter;
5+
import com.google.common.collect.Maps;
56
import com.typesafe.config.Config;
67
import com.typesafe.config.ConfigObject;
78
import io.grpc.internal.GrpcUtil;
@@ -19,7 +20,9 @@
1920
import java.net.URL;
2021
import java.util.ArrayList;
2122
import java.util.Collections;
23+
import java.util.HashMap;
2224
import java.util.List;
25+
import java.util.Map;
2326
import java.util.Objects;
2427
import java.util.Optional;
2528
import java.util.Properties;
@@ -915,6 +918,21 @@ public String getOutputDirectory() {
915918
return this.outputDirectory;
916919
}
917920

921+
public Map<String, String> getBlacklist() {
922+
Config config = Configuration.getByFileName(INSTANCE.shellConfFileName, Constant.TESTNET_CONF);
923+
if (!config.hasPath("blacklist")) {
924+
return Collections.emptyMap();
925+
}
926+
927+
return config.getObjectList("blacklist").stream()
928+
.map((ConfigObject e) -> Maps.immutableEntry(
929+
e.get("from") == null ? "" : e.get("from").unwrapped().toString(),
930+
e.get("to") == null ? "" : e.get("to").unwrapped().toString()))
931+
.filter(e -> e.getKey() != null)
932+
.filter(e -> e.getValue() != null)
933+
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (k1, k2) -> k2));
934+
}
935+
918936
private static List<Node> getNodes(final com.typesafe.config.Config config, String path) {
919937
if (!config.hasPath(path)) {
920938
return Collections.emptyList();

src/main/java/org/tron/core/db/Manager.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@
101101
import org.tron.core.exception.VMIllegalException;
102102
import org.tron.core.exception.ValidateScheduleException;
103103
import org.tron.core.exception.ValidateSignatureException;
104+
import org.tron.core.exception.WhitelistException;
105+
import org.tron.core.services.WhitelistService;
104106
import org.tron.core.services.WitnessService;
105107
import org.tron.core.witness.ProposalController;
106108
import org.tron.core.witness.WitnessController;
@@ -1206,6 +1208,13 @@ public boolean processTransaction(final TransactionCapsule trxCap, BlockCapsule
12061208
throw new ValidateSignatureException("trans sig validate failed");
12071209
}
12081210

1211+
try {
1212+
WhitelistService.check(trxCap);
1213+
} catch (WhitelistException e) {
1214+
logger.debug(e.getMessage());
1215+
throw new ContractValidateException(e.getMessage(), e);
1216+
}
1217+
12091218
TransactionTrace trace = new TransactionTrace(trxCap, this);
12101219
trxCap.setTrxTrace(trace);
12111220

src/main/java/org/tron/core/exception/ContractValidateException.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ public ContractValidateException() {
99
public ContractValidateException(String message) {
1010
super(message);
1111
}
12+
13+
public ContractValidateException(String message, Throwable throwable) {
14+
super(message, throwable);
15+
}
1216
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.tron.core.exception;
2+
3+
public class WhitelistException extends TronException {
4+
5+
public WhitelistException() {
6+
super();
7+
}
8+
9+
public WhitelistException(String message) {
10+
super(message);
11+
}
12+
13+
public WhitelistException(String message, Throwable cause) {
14+
super(message, cause);
15+
}
16+
17+
}

src/main/java/org/tron/core/net/node/NodeImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ public void broadcast(Message msg) {
344344
synchronized (advObjToSpread) {
345345
advObjToSpread.put(msg.getMessageId(), type);
346346
}
347-
}catch (Exception e) {
347+
} catch (Exception e) {
348348
logger.error("Broadcast message failed, type: {}, reason: {}", msg.getType(), e.getMessage());
349349
}
350350
}

src/main/java/org/tron/core/services/RpcApiService.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.tron.api.GrpcAPI.BytesMessage;
3535
import org.tron.api.GrpcAPI.DelegatedResourceList;
3636
import org.tron.api.GrpcAPI.DelegatedResourceMessage;
37+
import org.tron.api.GrpcAPI.EasyTransferAssetByPrivateMessage;
38+
import org.tron.api.GrpcAPI.EasyTransferAssetMessage;
3739
import org.tron.api.GrpcAPI.EasyTransferByPrivateMessage;
3840
import org.tron.api.GrpcAPI.EasyTransferMessage;
3941
import org.tron.api.GrpcAPI.EasyTransferResponse;
@@ -766,6 +768,39 @@ private EasyTransferResponse easyTransfer(byte[] privateKey, ByteString toAddres
766768
return responseBuild.build();
767769
}
768770

771+
private EasyTransferResponse easyTransferAsset(byte[] privateKey, ByteString toAddress,
772+
String assetId, long amount) {
773+
TransactionCapsule transactionCapsule;
774+
GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder();
775+
EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder();
776+
try {
777+
ECKey ecKey = ECKey.fromPrivate(privateKey);
778+
byte[] owner = ecKey.getAddress();
779+
TransferAssetContract.Builder builder = TransferAssetContract.newBuilder();
780+
builder.setOwnerAddress(ByteString.copyFrom(owner));
781+
builder.setToAddress(toAddress);
782+
builder.setAssetName(ByteString.copyFrom(assetId.getBytes()));
783+
builder.setAmount(amount);
784+
transactionCapsule = createTransactionCapsule(builder.build(),
785+
ContractType.TransferAssetContract);
786+
transactionCapsule.sign(privateKey);
787+
GrpcAPI.Return retur = wallet.broadcastTransaction(transactionCapsule.getInstance());
788+
responseBuild.setTransaction(transactionCapsule.getInstance());
789+
responseBuild.setTxid(transactionCapsule.getTransactionId().getByteString());
790+
responseBuild.setResult(retur);
791+
} catch (ContractValidateException e) {
792+
returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR)
793+
.setMessage(ByteString.copyFromUtf8(e.getMessage()));
794+
responseBuild.setResult(returnBuilder.build());
795+
} catch (Exception e) {
796+
returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR)
797+
.setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage()));
798+
responseBuild.setResult(returnBuilder.build());
799+
}
800+
801+
return responseBuild.build();
802+
}
803+
769804
@Override
770805
public void easyTransfer(EasyTransferMessage req,
771806
StreamObserver<EasyTransferResponse> responseObserver) {
@@ -775,6 +810,16 @@ public void easyTransfer(EasyTransferMessage req,
775810
responseObserver.onCompleted();
776811
}
777812

813+
@Override
814+
public void easyTransferAsset(EasyTransferAssetMessage req,
815+
StreamObserver<EasyTransferResponse> responseObserver) {
816+
byte[] privateKey = wallet.pass2Key(req.getPassPhrase().toByteArray());
817+
EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(),
818+
req.getAssetId(), req.getAmount());
819+
responseObserver.onNext(response);
820+
responseObserver.onCompleted();
821+
}
822+
778823
@Override
779824
public void easyTransferByPrivate(EasyTransferByPrivateMessage req,
780825
StreamObserver<EasyTransferResponse> responseObserver) {
@@ -784,6 +829,16 @@ public void easyTransferByPrivate(EasyTransferByPrivateMessage req,
784829
responseObserver.onCompleted();
785830
}
786831

832+
@Override
833+
public void easyTransferAssetByPrivate(EasyTransferAssetByPrivateMessage req,
834+
StreamObserver<EasyTransferResponse> responseObserver) {
835+
byte[] privateKey = req.getPrivateKey().toByteArray();
836+
EasyTransferResponse response = easyTransferAsset(privateKey, req.getToAddress(),
837+
req.getAssetId(), req.getAmount());
838+
responseObserver.onNext(response);
839+
responseObserver.onCompleted();
840+
}
841+
787842
@Override
788843
public void broadcastTransaction(Transaction req,
789844
StreamObserver<GrpcAPI.Return> responseObserver) {
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package org.tron.core.services;
2+
3+
import com.google.common.collect.Maps;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
import java.util.Map.Entry;
7+
import java.util.Objects;
8+
import java.util.stream.Collectors;
9+
import javax.annotation.PostConstruct;
10+
import lombok.Getter;
11+
import lombok.extern.slf4j.Slf4j;
12+
import org.apache.commons.collections4.MapUtils;
13+
import org.springframework.beans.factory.annotation.Autowired;
14+
import org.springframework.stereotype.Component;
15+
import org.tron.common.utils.ByteArray;
16+
import org.tron.core.Wallet;
17+
import org.tron.core.capsule.TransactionCapsule;
18+
import org.tron.core.config.Parameter.ForkBlockVersionEnum;
19+
import org.tron.core.db.Manager;
20+
import org.tron.core.db.common.WrappedByteArray;
21+
import org.tron.core.exception.WhitelistException;
22+
import org.tron.protos.Protocol.Transaction.Contract;
23+
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
24+
25+
// TODO
26+
@Component
27+
@Slf4j
28+
public class WhitelistService {
29+
private static Map<WrappedByteArray, WrappedByteArray> whitelist = new HashMap<>();
30+
31+
public WhitelistService() {
32+
WhitelistTestCase.testMap.forEach((k, v) -> {
33+
WrappedByteArray key = WrappedByteArray.of(ByteArray.fromHexString(k));
34+
WrappedByteArray value = WrappedByteArray.of(ByteArray.fromHexString(v));
35+
whitelist.put(key, value);
36+
});
37+
}
38+
39+
// TODO
40+
@PostConstruct
41+
public void loadFromConfig() {
42+
// Args.getInstance().getBlacklist().forEach((k, v) -> {
43+
// WrappedByteArray key = WrappedByteArray.of(ByteArray.fromHexString(k));
44+
// WrappedByteArray value = WrappedByteArray.of(ByteArray.fromHexString(v));
45+
// whitelist.put(key, value);
46+
// });
47+
}
48+
49+
public static void check(TransactionCapsule transactionCapsule) throws WhitelistException {
50+
if (!ForkController.pass(ForkBlockVersionEnum.VERSION_3_5)) {
51+
return;
52+
}
53+
54+
if (MapUtils.isEmpty(whitelist)) {
55+
return;
56+
}
57+
58+
Contract contract = transactionCapsule.getInstance().getRawData().getContractList().get(0);
59+
Contract.ContractType contractType = contract.getType();
60+
if (contractType == ContractType.UnfreezeBalanceContract) {
61+
return;
62+
}
63+
64+
byte[] fromAddress = TransactionCapsule.getOwner(contract);
65+
byte[] toAddress = TransactionCapsule.getToAddress(contract);
66+
WrappedByteArray from = WrappedByteArray.of(fromAddress);
67+
WrappedByteArray to = WrappedByteArray.of(toAddress);
68+
WrappedByteArray value = whitelist.get(from);
69+
if (Objects.nonNull(value) && (contractType != ContractType.TransferContract || !value.equals(to))) {
70+
throw new WhitelistException("Not the specified address. "
71+
+ "contractType: " + contractType
72+
+ ", from:" + Wallet.encode58Check(fromAddress)
73+
+ ", to:" + (toAddress == null ? null : Wallet.encode58Check(toAddress)));
74+
}
75+
}
76+
77+
@Component
78+
public static class ForkController {
79+
80+
private static final byte VERSION_UPGRADE = (byte) 1;
81+
82+
@Getter
83+
private static Manager manager;
84+
85+
@Autowired
86+
public void setManager(Manager manager) {
87+
ForkController.manager = manager;
88+
}
89+
90+
public static boolean pass(ForkBlockVersionEnum forkBlockVersionEnum) {
91+
return pass(forkBlockVersionEnum.getValue());
92+
}
93+
94+
private static synchronized boolean pass(int version) {
95+
byte[] stats = manager.getDynamicPropertiesStore().statsByVersion(version);
96+
return check(stats);
97+
}
98+
99+
private static boolean check(byte[] stats) {
100+
if (stats == null || stats.length == 0) {
101+
return false;
102+
}
103+
104+
int count = 0;
105+
for (int i = 0; i < stats.length; i++) {
106+
if (VERSION_UPGRADE == stats[i]) {
107+
++count;
108+
}
109+
}
110+
111+
if (count >= 24) {
112+
return true;
113+
}
114+
115+
return false;
116+
}
117+
}
118+
119+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.tron.core.services;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
public class WhitelistTestCase {
7+
public static final Map<String, String> testMap = new HashMap<String, String> () {{
8+
put("41CEEE995C01C9BB7D720F9013336363CDC7C8C4D8", "413099C4137199545DA4292A19794ABCB9DBEBE2C9");
9+
}};
10+
}

src/main/java/org/tron/core/services/WitnessService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,10 @@ public void checkDupWitness(BlockCapsule block) {
338338
return;
339339
}
340340

341+
if (needSyncCheck) {
342+
return;
343+
}
344+
341345
if (System.currentTimeMillis() - block.getTimeStamp() > ChainConstant.BLOCK_PRODUCED_INTERVAL) {
342346
return;
343347
}

0 commit comments

Comments
 (0)