From 6157b15bd13cacc17c0298a2bd12853bd71e8a72 Mon Sep 17 00:00:00 2001 From: wubin01 Date: Mon, 19 Aug 2019 15:28:37 +0800 Subject: [PATCH] add consensus --- .../java/org/tron/common/crypto/ECKey.java | 2462 ++++++++--------- .../crypto/jce/ECAlgorithmParameters.java | 0 .../common/crypto/jce/ECKeyAgreement.java | 0 .../tron/common/crypto/jce/ECKeyFactory.java | 0 .../common/crypto/jce/ECKeyPairGenerator.java | 0 .../common/crypto/jce/ECSignatureFactory.java | 0 .../java/org/tron/common/utils/BIUtil.java | 117 + .../tron/core/store/WitnessScheduleStore.java | 74 + consensus/build.gradle | 197 ++ .../java/org/tron/consensus/Consensus.java | 37 + .../org/tron/consensus/ConsensusDelegate.java | 155 ++ .../org/tron/consensus/base/BlockHandle.java | 17 + .../consensus/base/ConsensusInterface.java | 15 + .../org/tron/consensus/base/Constant.java | 17 + .../java/org/tron/consensus/base/Param.java | 40 + .../java/org/tron/consensus/base/State.java | 15 + .../org/tron/consensus/dpos/DposService.java | 144 + .../org/tron/consensus/dpos/DposSlot.java | 65 + .../org/tron/consensus/dpos/DposTask.java | 141 + .../tron/consensus/dpos/IncentiveManager.java | 47 + .../consensus/dpos/MaintenanceManager.java | 191 ++ .../org/tron/consensus/dpos/StateManager.java | 123 + .../tron/consensus/dpos/StatisticManager.java | 58 + .../common/utils/SlidingWindowCounter.java | 35 - .../tron/common/utils/SlotBaseCounter.java | 39 + .../tron/core/capsule/TransactionCapsule.java | 2 - .../org/tron/core/services/RpcApiService.java | 2 - .../java/org/tron/core/db/ManagerTest.java | 3 - .../tron/core/db/TransactionStoreTest.java | 1 - .../core/zksnark/ShieldedReceiveTest.java | 1 - .../wallet/account/WalletTestAccount001.java | 2 - .../wallet/account/WalletTestAccount003.java | 3 - .../wallet/account/WalletTestAccount004.java | 1 - .../wallet/account/WalletTestAccount005.java | 1 - .../wallet/account/WalletTestAccount006.java | 2 - .../wallet/account/WalletTestAccount007.java | 6 - .../tron/wallet/block/WalletTestBlock003.java | 1 - .../tron/wallet/block/WalletTestBlock004.java | 2 - .../tron/wallet/block/WalletTestBlock005.java | 1 - .../committee/WalletTestCommittee001.java | 10 - .../client/utils/PublicMethedForMutiSign.java | 1 - .../common/client/utils/TransactionUtils.java | 1 - .../delaytransaction/DelayTransaction001.java | 14 - .../delaytransaction/DelayTransaction002.java | 2 - .../delaytransaction/DelayTransaction003.java | 1 - .../delaytransaction/DelayTransaction004.java | 3 - .../delaytransaction/DelayTransaction007.java | 1 - .../delaytransaction/DelayTransaction010.java | 5 - .../delaytransaction/DelayTransaction011.java | 2 - .../http/HttpTestEasyAccount001.java | 1 - .../manual/ContractScenario015.java | 1 - .../tvmnewcommand/create2/Create2Test004.java | 1 - .../tvmnewcommand/create2/Create2Test015.java | 1 - .../tvmnewcommand/create2/Create2Test023.java | 4 - .../tvmnewcommand/create2/Create2Test025.java | 5 - .../extCodeHash/ExtCodeHashTest002.java | 1 - .../extCodeHash/ExtCodeHashTest005.java | 1 - .../extCodeHash/ExtCodeHashTest010.java | 2 - .../exchangeandtoken/WalletExchange001.java | 1 - .../tron/wallet/fulltest/AttackSendcoin.java | 4 - .../stest/tron/wallet/fulltest/Fuzzytest.java | 8 - .../fulltest/ParticipateAssetIssue.java | 3 - .../stest/tron/wallet/fulltest/TronDice.java | 2 - .../onlinestress/DelayTransactionStress.java | 2 - .../transfer/WalletTestTransfer001.java | 1 - .../transfer/WalletTestTransfer003.java | 3 - .../transfer/WalletTestTransfer004.java | 9 - .../MutisignOperationerGodicTest.java | 1 - .../wallet/witness/WalletTestWitness002.java | 1 - settings.gradle | 2 +- 70 files changed, 2724 insertions(+), 1387 deletions(-) rename {framework => chainbase}/src/main/java/org/tron/common/crypto/ECKey.java (97%) rename {framework => chainbase}/src/main/java/org/tron/common/crypto/jce/ECAlgorithmParameters.java (100%) rename {framework => chainbase}/src/main/java/org/tron/common/crypto/jce/ECKeyAgreement.java (100%) rename {framework => chainbase}/src/main/java/org/tron/common/crypto/jce/ECKeyFactory.java (100%) rename {framework => chainbase}/src/main/java/org/tron/common/crypto/jce/ECKeyPairGenerator.java (100%) rename {framework => chainbase}/src/main/java/org/tron/common/crypto/jce/ECSignatureFactory.java (100%) create mode 100644 chainbase/src/main/java/org/tron/common/utils/BIUtil.java create mode 100644 chainbase/src/main/java/org/tron/core/store/WitnessScheduleStore.java create mode 100644 consensus/build.gradle create mode 100644 consensus/src/main/java/org/tron/consensus/Consensus.java create mode 100644 consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java create mode 100644 consensus/src/main/java/org/tron/consensus/base/BlockHandle.java create mode 100644 consensus/src/main/java/org/tron/consensus/base/ConsensusInterface.java create mode 100644 consensus/src/main/java/org/tron/consensus/base/Constant.java create mode 100644 consensus/src/main/java/org/tron/consensus/base/Param.java create mode 100644 consensus/src/main/java/org/tron/consensus/base/State.java create mode 100644 consensus/src/main/java/org/tron/consensus/dpos/DposService.java create mode 100644 consensus/src/main/java/org/tron/consensus/dpos/DposSlot.java create mode 100644 consensus/src/main/java/org/tron/consensus/dpos/DposTask.java create mode 100644 consensus/src/main/java/org/tron/consensus/dpos/IncentiveManager.java create mode 100644 consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java create mode 100644 consensus/src/main/java/org/tron/consensus/dpos/StateManager.java create mode 100644 consensus/src/main/java/org/tron/consensus/dpos/StatisticManager.java create mode 100644 framework/src/main/java/org/tron/common/utils/SlotBaseCounter.java diff --git a/framework/src/main/java/org/tron/common/crypto/ECKey.java b/chainbase/src/main/java/org/tron/common/crypto/ECKey.java similarity index 97% rename from framework/src/main/java/org/tron/common/crypto/ECKey.java rename to chainbase/src/main/java/org/tron/common/crypto/ECKey.java index 948b686ee7a..40104eb7000 100644 --- a/framework/src/main/java/org/tron/common/crypto/ECKey.java +++ b/chainbase/src/main/java/org/tron/common/crypto/ECKey.java @@ -1,1231 +1,1231 @@ - /* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ - -package org.tron.common.crypto; - -import static org.tron.common.utils.BIUtil.isLessThan; -import static org.tron.common.utils.ByteUtil.bigIntegerToBytes; -import static org.tron.common.utils.Commons.computeAddress; - -import java.io.IOException; -import java.io.Serializable; -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.security.InvalidKeyException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.PrivateKey; -import java.security.Provider; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.Signature; -import java.security.SignatureException; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import javax.annotation.Nullable; -import javax.crypto.KeyAgreement; -import lombok.extern.slf4j.Slf4j; -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1Integer; -import org.spongycastle.asn1.DLSequence; -import org.spongycastle.asn1.sec.SECNamedCurves; -import org.spongycastle.asn1.x9.X9ECParameters; -import org.spongycastle.asn1.x9.X9IntegerConverter; -import org.spongycastle.crypto.agreement.ECDHBasicAgreement; -import org.spongycastle.crypto.digests.SHA256Digest; -import org.spongycastle.crypto.engines.AESEngine; -import org.spongycastle.crypto.modes.SICBlockCipher; -import org.spongycastle.crypto.params.ECDomainParameters; -import org.spongycastle.crypto.params.ECPrivateKeyParameters; -import org.spongycastle.crypto.params.ECPublicKeyParameters; -import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.crypto.params.ParametersWithIV; -import org.spongycastle.crypto.signers.ECDSASigner; -import org.spongycastle.crypto.signers.HMacDSAKCalculator; -import org.spongycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; -import org.spongycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; -import org.spongycastle.jce.spec.ECParameterSpec; -import org.spongycastle.jce.spec.ECPrivateKeySpec; -import org.spongycastle.jce.spec.ECPublicKeySpec; -import org.spongycastle.math.ec.ECAlgorithms; -import org.spongycastle.math.ec.ECCurve; -import org.spongycastle.math.ec.ECPoint; -import org.spongycastle.util.BigIntegers; -import org.spongycastle.util.encoders.Base64; -import org.spongycastle.util.encoders.Hex; -import org.tron.common.crypto.jce.ECKeyAgreement; -import org.tron.common.crypto.jce.ECKeyFactory; -import org.tron.common.crypto.jce.ECKeyPairGenerator; -import org.tron.common.crypto.jce.ECSignatureFactory; -import org.tron.common.crypto.jce.TronCastleProvider; -import org.tron.common.utils.ByteUtil; - -@Slf4j(topic = "crypto") -public class ECKey implements Serializable { - - /** - * The parameters of the secp256k1 curve. - */ - public static final ECDomainParameters CURVE; - public static final ECParameterSpec CURVE_SPEC; - - /** - * Equal to CURVE.getN().shiftRight(1), used for canonicalising the S value of a signature. ECDSA - * signatures are mutable in the sense that for a given (R, S) pair, then both (R, S) and (R, N - - * S mod N) are valid signatures. Canonical signatures are those where 1 <= S <= N/2 - * - *

See https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki - * #Low_S_values_in_signatures - */ - - public static final BigInteger HALF_CURVE_ORDER; - private static final BigInteger SECP256K1N = - new BigInteger("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16); - private static final SecureRandom secureRandom; - private static final long serialVersionUID = -728224901792295832L; - - static { - // All clients must agree on the curve to use by agreement. - X9ECParameters params = SECNamedCurves.getByName("secp256k1"); - CURVE = new ECDomainParameters(params.getCurve(), params.getG(), - params.getN(), params.getH()); - CURVE_SPEC = new ECParameterSpec(params.getCurve(), params.getG(), - params.getN(), params.getH()); - HALF_CURVE_ORDER = params.getN().shiftRight(1); - secureRandom = new SecureRandom(); - } - - protected final ECPoint pub; - // The two parts of the key. If "priv" is set, "pub" can always be - // calculated. If "pub" is set but not "priv", we - // can only verify signatures not make them. - // TODO: Redesign this class to use consistent internals and more - // efficient serialization. - private final PrivateKey privKey; - // the Java Cryptographic Architecture provider to use for Signature - // this is set along with the PrivateKey privKey and must be compatible - // this provider will be used when selecting a Signature instance - // https://docs.oracle.com/javase/8/docs/technotes/guides/security - // /SunProviders.html - private final Provider provider; - - // Transient because it's calculated on demand. - private transient byte[] pubKeyHash; - private transient byte[] nodeId; - - /** - * Generates an entirely new keypair. - * - *

BouncyCastle will be used as the Java Security Provider - */ - public ECKey() { - this(secureRandom); - } - - /** - * Generate a new keypair using the given Java Security Provider. - * - *

All private key operations will use the provider. - */ - public ECKey(Provider provider, SecureRandom secureRandom) { - this.provider = provider; - - final KeyPairGenerator keyPairGen = ECKeyPairGenerator.getInstance(provider, secureRandom); - final KeyPair keyPair = keyPairGen.generateKeyPair(); - - this.privKey = keyPair.getPrivate(); - - final PublicKey pubKey = keyPair.getPublic(); - if (pubKey instanceof BCECPublicKey) { - pub = ((BCECPublicKey) pubKey).getQ(); - } else if (pubKey instanceof ECPublicKey) { - pub = extractPublicKey((ECPublicKey) pubKey); - } else { - throw new AssertionError( - "Expected Provider " + provider.getName() - + " to produce a subtype of ECPublicKey, found " - + pubKey.getClass()); - } - } - - /** - * Generates an entirely new keypair with the given {@link SecureRandom} object.

BouncyCastle - * will be used as the Java Security Provider - * - * @param secureRandom - - */ - public ECKey(SecureRandom secureRandom) { - this(TronCastleProvider.getInstance(), secureRandom); - } - - /** - * Pair a private key with a public EC point. - * - *

All private key operations will use the provider. - */ - - public ECKey(Provider provider, @Nullable PrivateKey privKey, ECPoint pub) { - this.provider = provider; - - if (privKey == null || isECPrivateKey(privKey)) { - this.privKey = privKey; - } else { - throw new IllegalArgumentException( - "Expected EC private key, given a private key object with" + - " class " - + privKey.getClass().toString() + - " and algorithm " - + privKey.getAlgorithm()); - } - - if (pub == null) { - throw new IllegalArgumentException("Public key may not be null"); - } else { - this.pub = pub; - } - } - - /** - * Pair a private key integer with a public EC point

BouncyCastle will be used as the Java - * Security Provider - */ - public ECKey(@Nullable BigInteger priv, ECPoint pub) { - this( - TronCastleProvider.getInstance(), - privateKeyFromBigInteger(priv), - pub - ); - } - - /* Convert a Java JCE ECPublicKey into a BouncyCastle ECPoint - */ - private static ECPoint extractPublicKey(final ECPublicKey ecPublicKey) { - final java.security.spec.ECPoint publicPointW = ecPublicKey.getW(); - final BigInteger xCoord = publicPointW.getAffineX(); - final BigInteger yCoord = publicPointW.getAffineY(); - - return CURVE.getCurve().createPoint(xCoord, yCoord); - } - - /* Test if a generic private key is an EC private key - * - * it is not sufficient to check that privKey is a subtype of ECPrivateKey - * as the SunPKCS11 Provider will return a generic PrivateKey instance - * a fallback that covers this case is to check the key algorithm - */ - private static boolean isECPrivateKey(PrivateKey privKey) { - return privKey instanceof ECPrivateKey || privKey.getAlgorithm() - .equals("EC"); - } - - /* Convert a BigInteger into a PrivateKey object - */ - private static PrivateKey privateKeyFromBigInteger(BigInteger priv) { - if (priv == null) { - return null; - } else { - try { - return ECKeyFactory - .getInstance(TronCastleProvider.getInstance()) - .generatePrivate(new ECPrivateKeySpec(priv, - CURVE_SPEC)); - } catch (InvalidKeySpecException ex) { - throw new AssertionError("Assumed correct key spec statically"); - } - } - } - - /** - * Utility for compressing an elliptic curve point. Returns the same point if it's already - * compressed. See the ECKey class docs for a discussion of point compression. - * - * @param uncompressed - - * @return - - * @deprecated per-point compression property will be removed in Bouncy Castle - */ - public static ECPoint compressPoint(ECPoint uncompressed) { - return CURVE.getCurve().decodePoint(uncompressed.getEncoded(true)); - } - - /** - * Utility for decompressing an elliptic curve point. Returns the same point if it's already - * compressed. See the ECKey class docs for a discussion of point compression. - * - * @param compressed - - * @return - - * @deprecated per-point compression property will be removed in Bouncy Castle - */ - public static ECPoint decompressPoint(ECPoint compressed) { - return CURVE.getCurve().decodePoint(compressed.getEncoded(false)); - } - - /** - * Creates an ECKey given the private key only. - * - * @param privKey - - * @return - - */ - public static ECKey fromPrivate(BigInteger privKey) { - return new ECKey(privKey, CURVE.getG().multiply(privKey)); - } - - /** - * Creates an ECKey given the private key only. - * - * @param privKeyBytes - - * @return - - */ - public static ECKey fromPrivate(byte[] privKeyBytes) { - return fromPrivate(new BigInteger(1, privKeyBytes)); - } - - /** - * Creates an ECKey that simply trusts the caller to ensure that point is really the result of - * multiplying the generator point by the private key. This is used to speed things up when you - * know you have the right values already. The compression state of pub will be preserved. - * - * @param priv - - * @param pub - - * @return - - */ - public static ECKey fromPrivateAndPrecalculatedPublic(BigInteger priv, - ECPoint pub) { - return new ECKey(priv, pub); - } - - /** - * Creates an ECKey that simply trusts the caller to ensure that point is really the result of - * multiplying the generator point by the private key. This is used to speed things up when you - * know you have the right values already. The compression state of the point will be preserved. - * - * @param priv - - * @param pub - - * @return - - */ - public static ECKey fromPrivateAndPrecalculatedPublic(byte[] priv, byte[] - pub) { - check(priv != null, "Private key must not be null"); - check(pub != null, "Public key must not be null"); - return new ECKey(new BigInteger(1, priv), CURVE.getCurve() - .decodePoint(pub)); - } - - /** - * Creates an ECKey that cannot be used for signing, only verifying signatures, from the given - * point. The compression state of pub will be preserved. - * - * @param pub - - * @return - - */ - public static ECKey fromPublicOnly(ECPoint pub) { - return new ECKey(null, pub); - } - - /** - * Creates an ECKey that cannot be used for signing, only verifying signatures, from the given - * encoded point. The compression state of pub will be preserved. - * - * @param pub - - * @return - - */ - public static ECKey fromPublicOnly(byte[] pub) { - return new ECKey(null, CURVE.getCurve().decodePoint(pub)); - } - - /** - * Returns public key bytes from the given private key. To convert a byte array into a BigInteger, - * use new BigInteger(1, bytes); - * - * @param privKey - - * @param compressed - - * @return - - */ - public static byte[] publicKeyFromPrivate(BigInteger privKey, boolean - compressed) { - ECPoint point = CURVE.getG().multiply(privKey); - return point.getEncoded(compressed); - } - - /** - * Compute the encoded X, Y coordinates of a public point.

This is the encoded public key - * without the leading byte. - * - * @param pubPoint a public point - * @return 64-byte X,Y point pair - */ - public static byte[] pubBytesWithoutFormat(ECPoint pubPoint) { - final byte[] pubBytes = pubPoint.getEncoded(/* uncompressed */ false); - return Arrays.copyOfRange(pubBytes, 1, pubBytes.length); - } - - /** - * Recover the public key from an encoded node id. - * - * @param nodeId a 64-byte X,Y point pair - */ - public static ECKey fromNodeId(byte[] nodeId) { - check(nodeId.length == 64, "Expected a 64 byte node id"); - byte[] pubBytes = new byte[65]; - System.arraycopy(nodeId, 0, pubBytes, 1, nodeId.length); - pubBytes[0] = 0x04; // uncompressed - return ECKey.fromPublicOnly(pubBytes); - } - - public static byte[] signatureToKeyBytes(byte[] messageHash, String - signatureBase64) throws SignatureException { - byte[] signatureEncoded; - try { - signatureEncoded = Base64.decode(signatureBase64); - } catch (RuntimeException e) { - // This is what you getData back from Bouncy Castle if base64 doesn't - // decode :( - throw new SignatureException("Could not decode base64", e); - } - // Parse the signature bytes into r/s and the selector value. - if (signatureEncoded.length < 65) { - throw new SignatureException("Signature truncated, expected 65 " + - "bytes and got " + signatureEncoded.length); - } - - return signatureToKeyBytes( - messageHash, - ECDSASignature.fromComponents( - Arrays.copyOfRange(signatureEncoded, 1, 33), - Arrays.copyOfRange(signatureEncoded, 33, 65), - (byte) (signatureEncoded[0] & 0xFF))); - } - - public static byte[] signatureToKeyBytes(byte[] messageHash, - ECDSASignature sig) throws - SignatureException { - check(messageHash.length == 32, "messageHash argument has length " + - messageHash.length); - int header = sig.v; - // The header byte: 0x1B = first key with even y, 0x1C = first key - // with odd y, - // 0x1D = second key with even y, 0x1E = second key - // with odd y - if (header < 27 || header > 34) { - throw new SignatureException("Header byte out of range: " + header); - } - if (header >= 31) { - header -= 4; - } - int recId = header - 27; - byte[] key = ECKey.recoverPubBytesFromSignature(recId, sig, - messageHash); - if (key == null) { - throw new SignatureException("Could not recover public key from " + - "signature"); - } - return key; - } - - /** - * Compute the address of the key that signed the given signature. - * - * @param messageHash 32-byte hash of message - * @param signatureBase64 Base-64 encoded signature - * @return 20-byte address - */ - public static byte[] signatureToAddress(byte[] messageHash, String - signatureBase64) throws SignatureException { - return computeAddress(signatureToKeyBytes(messageHash, - signatureBase64)); - } - - /** - * Compute the address of the key that signed the given signature. - * - * @param messageHash 32-byte hash of message - * @param sig - - * @return 20-byte address - */ - public static byte[] signatureToAddress(byte[] messageHash, - ECDSASignature sig) throws - SignatureException { - return computeAddress(signatureToKeyBytes(messageHash, sig)); - } - - /** - * Compute the key that signed the given signature. - * - * @param messageHash 32-byte hash of message - * @param signatureBase64 Base-64 encoded signature - * @return ECKey - */ - public static ECKey signatureToKey(byte[] messageHash, String - signatureBase64) throws SignatureException { - final byte[] keyBytes = signatureToKeyBytes(messageHash, - signatureBase64); - return ECKey.fromPublicOnly(keyBytes); - } - - /** - * Compute the key that signed the given signature. - * - * @param messageHash 32-byte hash of message - * @param sig - - * @return ECKey - */ - public static ECKey signatureToKey(byte[] messageHash, ECDSASignature - sig) throws SignatureException { - final byte[] keyBytes = signatureToKeyBytes(messageHash, sig); - return ECKey.fromPublicOnly(keyBytes); - } - - /** - *

Verifies the given ECDSA signature against the message bytes using the public key bytes.

- *

When using native ECDSA verification, data must be 32 bytes, and no element may be - * larger than 520 bytes.

- * - * @param data Hash of the data to verify. - * @param signature signature. - * @param pub The public key bytes to use. - * @return - - */ - public static boolean verify(byte[] data, ECDSASignature signature, - byte[] pub) { - ECDSASigner signer = new ECDSASigner(); - ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE - .getCurve().decodePoint(pub), CURVE); - signer.init(false, params); - try { - return signer.verifySignature(data, signature.r, signature.s); - } catch (NullPointerException npe) { - // Bouncy Castle contains a bug that can cause NPEs given - // specially crafted signatures. - // Those signatures are inherently invalid/attack sigs so we just - // fail them here rather than crash the thread. - logger.error("Caught NPE inside bouncy castle", npe); - return false; - } - } - - /** - * Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key. - * - * @param data Hash of the data to verify. - * @param signature signature. - * @param pub The public key bytes to use. - * @return - - */ - public static boolean verify(byte[] data, byte[] signature, byte[] pub) { - return verify(data, ECDSASignature.decodeFromDER(signature), pub); - } - - /** - * Returns true if the given pubkey is canonical, i.e. the correct length taking into account - * compression. - * - * @param pubkey - - * @return - - */ - public static boolean isPubKeyCanonical(byte[] pubkey) { - if (pubkey[0] == 0x04) { - // Uncompressed pubkey - return pubkey.length == 65; - } else if (pubkey[0] == 0x02 || pubkey[0] == 0x03) { - // Compressed pubkey - return pubkey.length == 33; - } else { - return false; - } - } - - /** - *

Given the components of a signature and a selector value, recover and return the public key - * that generated the signature according to the algorithm in SEC1v2 section 4.1.6.

- * - *

The recId is an index from 0 to 3 which indicates which of the 4 possible allKeys is the - * correct one. Because the key recovery operation yields multiple potential allKeys, the correct - * key must either be stored alongside the signature, or you must be willing to try each recId in - * turn until you find one that outputs the key you are expecting.

- * - *

If this method returns null it means recovery was not possible and recId should be - * iterated.

- * - *

Given the above two points, a correct usage of this method is inside a for loop from 0 - * to 3, and if the output is null OR a key that is not the one you expect, you try again with the - * next recId.

- * - * @param recId Which possible key to recover. - * @param sig the R and S components of the signature, wrapped. - * @param messageHash Hash of the data that was signed. - * @return 65-byte encoded public key - */ - @Nullable - public static byte[] recoverPubBytesFromSignature(int recId, - ECDSASignature sig, - byte[] messageHash) { - check(recId >= 0, "recId must be positive"); - check(sig.r.signum() >= 0, "r must be positive"); - check(sig.s.signum() >= 0, "s must be positive"); - check(messageHash != null, "messageHash must not be null"); - // 1.0 For j from 0 to h (h == recId here and the loop is outside - // this function) - // 1.1 Let x = r + jn - BigInteger n = CURVE.getN(); // Curve order. - BigInteger i = BigInteger.valueOf((long) recId / 2); - BigInteger x = sig.r.add(i.multiply(n)); - // 1.2. Convert the integer x to an octet string X of length mlen - // using the conversion routine - // specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or - // mlen = ⌈m/8⌉. - // 1.3. Convert the octet string (16 set binary digits)||X to an - // elliptic curve point R using the - // conversion routine specified in Section 2.3.4. If this - // conversion routine outputs “invalid”, then - // do another iteration of Step 1. - // - // More concisely, what these points mean is to use X as a compressed - // public key. - ECCurve.Fp curve = (ECCurve.Fp) CURVE.getCurve(); - BigInteger prime = curve.getQ(); // Bouncy Castle is not consistent - // about the letter it uses for the prime. - if (x.compareTo(prime) >= 0) { - // Cannot have point co-ordinates larger than this as everything - // takes place modulo Q. - return null; - } - // Compressed allKeys require you to know an extra bit of data about the - // y-coord as there are two possibilities. - // So it's encoded in the recId. - ECPoint R = decompressKey(x, (recId & 1) == 1); - // 1.4. If nR != point at infinity, then do another iteration of - // Step 1 (callers responsibility). - if (!R.multiply(n).isInfinity()) { - return null; - } - // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature - // verification. - BigInteger e = new BigInteger(1, messageHash); - // 1.6. For k from 1 to 2 do the following. (loop is outside this - // function via iterating recId) - // 1.6.1. Compute a candidate public key as: - // Q = mi(r) * (sR - eG) - // - // Where mi(x) is the modular multiplicative inverse. We transform - // this into the following: - // Q = (mi(r) * s ** R) + (mi(r) * -e ** G) - // Where -e is the modular additive inverse of e, that is z such that - // z + e = 0 (mod n). In the above equation - // ** is point multiplication and + is point addition (the EC group - // operator). - // - // We can find the additive inverse by subtracting e from zero then - // taking the mod. For example the additive - // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod - // 11 = 8. - BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n); - BigInteger rInv = sig.r.modInverse(n); - BigInteger srInv = rInv.multiply(sig.s).mod(n); - BigInteger eInvrInv = rInv.multiply(eInv).mod(n); - ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE - .getG(), eInvrInv, R, srInv); - return q.getEncoded(/* compressed */ false); - } - - /** - * @param recId Which possible key to recover. - * @param sig the R and S components of the signature, wrapped. - * @param messageHash Hash of the data that was signed. - * @return 20-byte address - */ - @Nullable - public static byte[] recoverAddressFromSignature(int recId, - ECDSASignature sig, - byte[] messageHash) { - final byte[] pubBytes = recoverPubBytesFromSignature(recId, sig, - messageHash); - if (pubBytes == null) { - return null; - } else { - return computeAddress(pubBytes); - } - } - - /** - * @param recId Which possible key to recover. - * @param sig the R and S components of the signature, wrapped. - * @param messageHash Hash of the data that was signed. - * @return ECKey - */ - @Nullable - public static ECKey recoverFromSignature(int recId, ECDSASignature sig, - byte[] messageHash) { - final byte[] pubBytes = recoverPubBytesFromSignature(recId, sig, - messageHash); - if (pubBytes == null) { - return null; - } else { - return ECKey.fromPublicOnly(pubBytes); - } - } - - /** - * Decompress a compressed public key (x co-ord and low-bit of y-coord). - * - * @param xBN - - * @param yBit - - * @return - - */ - - private static ECPoint decompressKey(BigInteger xBN, boolean yBit) { - X9IntegerConverter x9 = new X9IntegerConverter(); - byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE - .getCurve())); - compEnc[0] = (byte) (yBit ? 0x03 : 0x02); - return CURVE.getCurve().decodePoint(compEnc); - } - - private static void check(boolean test, String message) { - if (!test) { - throw new IllegalArgumentException(message); - } - } - - /** - * Returns a copy of this key, but with the public point represented in uncompressed form. - * Normally you would never need this: it's for specialised scenarios or when backwards - * compatibility in encoded form is necessary. - * - * @return - - * @deprecated per-point compression property will be removed in Bouncy Castle - */ - public ECKey decompress() { - if (!pub.isCompressed()) { - return this; - } else { - return new ECKey(this.provider, this.privKey, decompressPoint(pub)); - } - } - - /** - * @deprecated per-point compression property will be removed in Bouncy Castle - */ - public ECKey compress() { - if (pub.isCompressed()) { - return this; - } else { - return new ECKey(this.provider, this.privKey, compressPoint(pub)); - } - } - - /** - * Returns true if this key doesn't have access to private key bytes. This may be because it was - * never given any private key bytes to begin with (a watching key). - * - * @return - - */ - public boolean isPubKeyOnly() { - return privKey == null; - } - - /** - * Returns true if this key has access to private key bytes. Does the opposite of {@link - * #isPubKeyOnly()}. - * - * @return - - */ - public boolean hasPrivKey() { - return privKey != null; - } - - /** - * Gets the address form of the public key. - * - * @return 21-byte address - */ - public byte[] getAddress() { - if (pubKeyHash == null) { - pubKeyHash = computeAddress(this.pub); - } - return pubKeyHash; - } - - /** - * Generates the NodeID based on this key, that is the public key without first format byte - */ - public byte[] getNodeId() { - if (nodeId == null) { - nodeId = pubBytesWithoutFormat(this.pub); - } - return nodeId; - } - - /** - * Gets the encoded public key value. - * - * @return 65-byte encoded public key - */ - public byte[] getPubKey() { - return pub.getEncoded(/* compressed */ false); - } - - /** - * Gets the public key in the form of an elliptic curve point object from Bouncy Castle. - * - * @return - - */ - public ECPoint getPubKeyPoint() { - return pub; - } - - /** - * Gets the private key in the form of an integer field element. The public key is derived by - * performing EC point addition this number of times (i.e. point multiplying). - * - * @return - - * @throws IllegalStateException if the private key bytes are not available. - */ - public BigInteger getPrivKey() { - if (privKey == null) { - throw new MissingPrivateKeyException(); - } else if (privKey instanceof BCECPrivateKey) { - return ((BCECPrivateKey) privKey).getD(); - } else { - throw new MissingPrivateKeyException(); - } - } - - /** - * Returns whether this key is using the compressed form or not. Compressed pubkeys are only 33 - * bytes, not 64. - * - * @return - - */ - public boolean isCompressed() { - return pub.isCompressed(); - } - - public String toString() { - StringBuilder b = new StringBuilder(); - b.append("pub:").append(Hex.toHexString(pub.getEncoded(false))); - return b.toString(); - } - - /** - * Produce a string rendering of the ECKey INCLUDING the private key. Unless you absolutely need - * the private key it is better for security reasons to just use toString(). - * - * @return - - */ - public String toStringWithPrivate() { - StringBuilder b = new StringBuilder(); - b.append(toString()); - if (privKey != null && privKey instanceof BCECPrivateKey) { - b.append(" priv:").append(Hex.toHexString(((BCECPrivateKey) - privKey).getD().toByteArray())); - } - return b.toString(); - } - - /** - * Signs the given hash and returns the R and S components as BigIntegers and putData them in - * ECDSASignature - * - * @param input to sign - * @return ECDSASignature signature that contains the R and S components - */ - public ECDSASignature doSign(byte[] input) { - if (input.length != 32) { - throw new IllegalArgumentException("Expected 32 byte input to " + - "ECDSA signature, not " + input.length); - } - // No decryption of private key required. - if (privKey == null) { - throw new MissingPrivateKeyException(); - } - if (privKey instanceof BCECPrivateKey) { - ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new - SHA256Digest())); - ECPrivateKeyParameters privKeyParams = new ECPrivateKeyParameters - (((BCECPrivateKey) privKey).getD(), CURVE); - signer.init(true, privKeyParams); - BigInteger[] components = signer.generateSignature(input); - return new ECDSASignature(components[0], components[1]) - .toCanonicalised(); - } else { - try { - final Signature ecSig = ECSignatureFactory.getRawInstance - (provider); - ecSig.initSign(privKey); - ecSig.update(input); - final byte[] derSignature = ecSig.sign(); - return ECDSASignature.decodeFromDER(derSignature) - .toCanonicalised(); - } catch (SignatureException | InvalidKeyException ex) { - throw new RuntimeException("ECKey signing error", ex); - } - } - } - - /** - * Takes the keccak hash (32 bytes) of data and returns the ECDSA signature - * - * @param messageHash - - * @return - - * @throws IllegalStateException if this ECKey does not have the private part. - */ - public ECDSASignature sign(byte[] messageHash) { - ECDSASignature sig = doSign(messageHash); - // Now we have to work backwards to figure out the recId needed to - // recover the signature. - int recId = -1; - byte[] thisKey = this.pub.getEncoded(/* compressed */ false); - for (int i = 0; i < 4; i++) { - byte[] k = ECKey.recoverPubBytesFromSignature(i, sig, messageHash); - if (k != null && Arrays.equals(k, thisKey)) { - recId = i; - break; - } - } - if (recId == -1) { - throw new RuntimeException("Could not construct a recoverable key" + - ". This should never happen."); - } - sig.v = (byte) (recId + 27); - return sig; - } - - public BigInteger keyAgreement(ECPoint otherParty) { - if (privKey == null) { - throw new MissingPrivateKeyException(); - } else if (privKey instanceof BCECPrivateKey) { - final ECDHBasicAgreement agreement = new ECDHBasicAgreement(); - agreement.init(new ECPrivateKeyParameters(((BCECPrivateKey) - privKey).getD(), CURVE)); - return agreement.calculateAgreement(new ECPublicKeyParameters - (otherParty, CURVE)); - } else { - try { - final KeyAgreement agreement = ECKeyAgreement.getInstance - (this.provider); - agreement.init(this.privKey); - agreement.doPhase( - ECKeyFactory.getInstance(this.provider) - .generatePublic(new ECPublicKeySpec - (otherParty, CURVE_SPEC)), - /* lastPhase */ true); - return new BigInteger(1, agreement.generateSecret()); - } catch (IllegalStateException | InvalidKeyException | - InvalidKeySpecException ex) { - throw new RuntimeException("ECDH key agreement failure", ex); - } - } - } - - /** - * Decrypt cipher by AES in SIC(also know as CTR) mode - * - * @param cipher -proper cipher - * @return decrypted cipher, equal length to the cipher. - * @deprecated should not use EC private scalar value as an AES key - */ - public byte[] decryptAES(byte[] cipher) { - - if (privKey == null) { - throw new MissingPrivateKeyException(); - } - if (!(privKey instanceof BCECPrivateKey)) { - throw new UnsupportedOperationException("Cannot use the private " + - "key as an AES key"); - } - - AESEngine engine = new AESEngine(); - SICBlockCipher ctrEngine = new SICBlockCipher(engine); - - KeyParameter key = new KeyParameter(BigIntegers.asUnsignedByteArray(( - (BCECPrivateKey) privKey).getD())); - ParametersWithIV params = new ParametersWithIV(key, new byte[16]); - - ctrEngine.init(false, params); - - int i = 0; - byte[] out = new byte[cipher.length]; - while (i < cipher.length) { - ctrEngine.processBlock(cipher, i, out, i); - i += engine.getBlockSize(); - if (cipher.length - i < engine.getBlockSize()) { - break; - } - } - - // process left bytes - if (cipher.length - i > 0) { - byte[] tmpBlock = new byte[16]; - System.arraycopy(cipher, i, tmpBlock, 0, cipher.length - i); - ctrEngine.processBlock(tmpBlock, 0, tmpBlock, 0); - System.arraycopy(tmpBlock, 0, out, i, cipher.length - i); - } - - return out; - } - - /** - * Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key. - * - * @param data Hash of the data to verify. - * @param signature signature. - * @return - - */ - public boolean verify(byte[] data, byte[] signature) { - return ECKey.verify(data, signature, getPubKey()); - } - - /** - * Verifies the given R/S pair (signature) against a hash using the public key. - * - * @param sigHash - - * @param signature - - * @return - - */ - public boolean verify(byte[] sigHash, ECDSASignature signature) { - return ECKey.verify(sigHash, signature, getPubKey()); - } - - /** - * Returns true if this pubkey is canonical, i.e. the correct length taking into account - * compression. - * - * @return - - */ - public boolean isPubKeyCanonical() { - return isPubKeyCanonical(pub.getEncoded(/* uncompressed */ false)); - } - - /** - * Returns a 32 byte array containing the private key, or null if the key is encrypted or public - * only - * - * @return - - */ - @Nullable - public byte[] getPrivKeyBytes() { - if (privKey == null) { - return null; - } else if (privKey instanceof BCECPrivateKey) { - return bigIntegerToBytes(((BCECPrivateKey) privKey).getD(), 32); - } else { - return null; - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - ECKey ecKey = (ECKey) o; - - if (privKey != null && !privKey.equals(ecKey.privKey)) { - return false; - } - return pub == null || pub.equals(ecKey.pub); - } - - @Override - public int hashCode() { - return Arrays.hashCode(getPubKey()); - } - - public static class ECDSASignature { - - /** - * The two components of the signature. - */ - public final BigInteger r, s; - public byte v; - - /** - * Constructs a signature with the given components. Does NOT automatically canonicalise the - * signature. - * - * @param r - - * @param s - - */ - public ECDSASignature(BigInteger r, BigInteger s) { - this.r = r; - this.s = s; - } - - /** - * t - * - * @return - - */ - private static ECDSASignature fromComponents(byte[] r, byte[] s) { - return new ECDSASignature(new BigInteger(1, r), new BigInteger(1, - s)); - } - - /** - * @param r - - * @param s - - * @param v - - * @return - - */ - public static ECDSASignature fromComponents(byte[] r, byte[] s, byte - v) { - ECDSASignature signature = fromComponents(r, s); - signature.v = v; - return signature; - } - - public static boolean validateComponents(BigInteger r, BigInteger s, - byte v) { - - if (v != 27 && v != 28) { - return false; - } - - if (isLessThan(r, BigInteger.ONE)) { - return false; - } - if (isLessThan(s, BigInteger.ONE)) { - return false; - } - - if (!isLessThan(r, SECP256K1N)) { - return false; - } - return isLessThan(s, SECP256K1N); - } - - public static ECDSASignature decodeFromDER(byte[] bytes) { - ASN1InputStream decoder = null; - try { - decoder = new ASN1InputStream(bytes); - DLSequence seq = (DLSequence) decoder.readObject(); - if (seq == null) { - throw new RuntimeException("Reached past end of ASN.1 " + - "stream."); - } - ASN1Integer r, s; - try { - r = (ASN1Integer) seq.getObjectAt(0); - s = (ASN1Integer) seq.getObjectAt(1); - } catch (ClassCastException e) { - throw new IllegalArgumentException(e); - } - // OpenSSL deviates from the DER spec by interpreting these - // values as unsigned, though they should not be - // Thus, we always use the positive versions. See: - // http://r6.ca/blog/20111119T211504Z.html - return new ECDSASignature(r.getPositiveValue(), s - .getPositiveValue()); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - if (decoder != null) { - try { - decoder.close(); - } catch (IOException x) { - - } - } - } - } - - public boolean validateComponents() { - return validateComponents(r, s, v); - } - - public ECDSASignature toCanonicalised() { - if (s.compareTo(HALF_CURVE_ORDER) > 0) { - // The order of the curve is the number of valid points that - // exist on that curve. If S is in the upper - // half of the number of valid points, then bring it back to - // the lower half. Otherwise, imagine that - // N = 10 - // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) - // are valid solutions. - // 10 - 8 == 2, giving us always the latter solution, - // which is canonical. - return new ECDSASignature(r, CURVE.getN().subtract(s)); - } else { - return this; - } - } - - /** - * @return - - */ - public String toBase64() { - byte[] sigData = new byte[65]; // 1 header + 32 bytes for R + 32 - // bytes for S - sigData[0] = v; - System.arraycopy(bigIntegerToBytes(this.r, 32), 0, sigData, 1, 32); - System.arraycopy(bigIntegerToBytes(this.s, 32), 0, sigData, 33, 32); - return new String(Base64.encode(sigData), Charset.forName("UTF-8")); - } - - public byte[] toByteArray() { - final byte fixedV = this.v >= 27 - ? (byte) (this.v - 27) - : this.v; - - return ByteUtil.merge( - ByteUtil.bigIntegerToBytes(this.r, 32), - ByteUtil.bigIntegerToBytes(this.s, 32), - new byte[]{fixedV}); - } - - public String toHex() { - return Hex.toHexString(toByteArray()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - ECDSASignature signature = (ECDSASignature) o; - - if (!r.equals(signature.r)) { - return false; - } - return s.equals(signature.s); - } - - @Override - public int hashCode() { - int result = r.hashCode(); - result = 31 * result + s.hashCode(); - return result; - } - } - - @SuppressWarnings("serial") - public static class MissingPrivateKeyException extends RuntimeException { - - } - -} +package org.tron.common.crypto; +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ + +import static org.tron.common.utils.BIUtil.isLessThan; +import static org.tron.common.utils.ByteUtil.bigIntegerToBytes; +import static org.tron.common.utils.Commons.computeAddress; + +import java.io.IOException; +import java.io.Serializable; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.SignatureException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; +import javax.annotation.Nullable; +import javax.crypto.KeyAgreement; +import lombok.extern.slf4j.Slf4j; +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.DLSequence; +import org.spongycastle.asn1.sec.SECNamedCurves; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.asn1.x9.X9IntegerConverter; +import org.spongycastle.crypto.agreement.ECDHBasicAgreement; +import org.spongycastle.crypto.digests.SHA256Digest; +import org.spongycastle.crypto.engines.AESEngine; +import org.spongycastle.crypto.modes.SICBlockCipher; +import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECPrivateKeyParameters; +import org.spongycastle.crypto.params.ECPublicKeyParameters; +import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.crypto.params.ParametersWithIV; +import org.spongycastle.crypto.signers.ECDSASigner; +import org.spongycastle.crypto.signers.HMacDSAKCalculator; +import org.spongycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; +import org.spongycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; +import org.spongycastle.jce.spec.ECParameterSpec; +import org.spongycastle.jce.spec.ECPrivateKeySpec; +import org.spongycastle.jce.spec.ECPublicKeySpec; +import org.spongycastle.math.ec.ECAlgorithms; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.BigIntegers; +import org.spongycastle.util.encoders.Base64; +import org.spongycastle.util.encoders.Hex; +import org.tron.common.crypto.jce.ECKeyAgreement; +import org.tron.common.crypto.jce.ECKeyFactory; +import org.tron.common.crypto.jce.ECKeyPairGenerator; +import org.tron.common.crypto.jce.ECSignatureFactory; +import org.tron.common.crypto.jce.TronCastleProvider; +import org.tron.common.utils.ByteUtil; + +@Slf4j(topic = "crypto") +public class ECKey implements Serializable { + + /** + * The parameters of the secp256k1 curve. + */ + public static final ECDomainParameters CURVE; + public static final ECParameterSpec CURVE_SPEC; + + /** + * Equal to CURVE.getN().shiftRight(1), used for canonicalising the S value of a signature. ECDSA + * signatures are mutable in the sense that for a given (R, S) pair, then both (R, S) and (R, N - + * S mod N) are valid signatures. Canonical signatures are those where 1 <= S <= N/2 + * + *

See https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki + * #Low_S_values_in_signatures + */ + + public static final BigInteger HALF_CURVE_ORDER; + private static final BigInteger SECP256K1N = + new BigInteger("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16); + private static final SecureRandom secureRandom; + private static final long serialVersionUID = -728224901792295832L; + + static { + // All clients must agree on the curve to use by agreement. + X9ECParameters params = SECNamedCurves.getByName("secp256k1"); + CURVE = new ECDomainParameters(params.getCurve(), params.getG(), + params.getN(), params.getH()); + CURVE_SPEC = new ECParameterSpec(params.getCurve(), params.getG(), + params.getN(), params.getH()); + HALF_CURVE_ORDER = params.getN().shiftRight(1); + secureRandom = new SecureRandom(); + } + + protected final ECPoint pub; + // The two parts of the key. If "priv" is set, "pub" can always be + // calculated. If "pub" is set but not "priv", we + // can only verify signatures not make them. + // TODO: Redesign this class to use consistent internals and more + // efficient serialization. + private final PrivateKey privKey; + // the Java Cryptographic Architecture provider to use for Signature + // this is set along with the PrivateKey privKey and must be compatible + // this provider will be used when selecting a Signature instance + // https://docs.oracle.com/javase/8/docs/technotes/guides/security + // /SunProviders.html + private final Provider provider; + + // Transient because it's calculated on demand. + private transient byte[] pubKeyHash; + private transient byte[] nodeId; + + /** + * Generates an entirely new keypair. + * + *

BouncyCastle will be used as the Java Security Provider + */ + public ECKey() { + this(secureRandom); + } + + /** + * Generate a new keypair using the given Java Security Provider. + * + *

All private key operations will use the provider. + */ + public ECKey(Provider provider, SecureRandom secureRandom) { + this.provider = provider; + + final KeyPairGenerator keyPairGen = ECKeyPairGenerator.getInstance(provider, secureRandom); + final KeyPair keyPair = keyPairGen.generateKeyPair(); + + this.privKey = keyPair.getPrivate(); + + final PublicKey pubKey = keyPair.getPublic(); + if (pubKey instanceof BCECPublicKey) { + pub = ((BCECPublicKey) pubKey).getQ(); + } else if (pubKey instanceof ECPublicKey) { + pub = extractPublicKey((ECPublicKey) pubKey); + } else { + throw new AssertionError( + "Expected Provider " + provider.getName() + + " to produce a subtype of ECPublicKey, found " + + pubKey.getClass()); + } + } + + /** + * Generates an entirely new keypair with the given {@link SecureRandom} object.

BouncyCastle + * will be used as the Java Security Provider + * + * @param secureRandom - + */ + public ECKey(SecureRandom secureRandom) { + this(TronCastleProvider.getInstance(), secureRandom); + } + + /** + * Pair a private key with a public EC point. + * + *

All private key operations will use the provider. + */ + + public ECKey(Provider provider, @Nullable PrivateKey privKey, ECPoint pub) { + this.provider = provider; + + if (privKey == null || isECPrivateKey(privKey)) { + this.privKey = privKey; + } else { + throw new IllegalArgumentException( + "Expected EC private key, given a private key object with" + + " class " + + privKey.getClass().toString() + + " and algorithm " + + privKey.getAlgorithm()); + } + + if (pub == null) { + throw new IllegalArgumentException("Public key may not be null"); + } else { + this.pub = pub; + } + } + + /** + * Pair a private key integer with a public EC point

BouncyCastle will be used as the Java + * Security Provider + */ + public ECKey(@Nullable BigInteger priv, ECPoint pub) { + this( + TronCastleProvider.getInstance(), + privateKeyFromBigInteger(priv), + pub + ); + } + + /* Convert a Java JCE ECPublicKey into a BouncyCastle ECPoint + */ + private static ECPoint extractPublicKey(final ECPublicKey ecPublicKey) { + final java.security.spec.ECPoint publicPointW = ecPublicKey.getW(); + final BigInteger xCoord = publicPointW.getAffineX(); + final BigInteger yCoord = publicPointW.getAffineY(); + + return CURVE.getCurve().createPoint(xCoord, yCoord); + } + + /* Test if a generic private key is an EC private key + * + * it is not sufficient to check that privKey is a subtype of ECPrivateKey + * as the SunPKCS11 Provider will return a generic PrivateKey instance + * a fallback that covers this case is to check the key algorithm + */ + private static boolean isECPrivateKey(PrivateKey privKey) { + return privKey instanceof ECPrivateKey || privKey.getAlgorithm() + .equals("EC"); + } + + /* Convert a BigInteger into a PrivateKey object + */ + private static PrivateKey privateKeyFromBigInteger(BigInteger priv) { + if (priv == null) { + return null; + } else { + try { + return ECKeyFactory + .getInstance(TronCastleProvider.getInstance()) + .generatePrivate(new ECPrivateKeySpec(priv, + CURVE_SPEC)); + } catch (InvalidKeySpecException ex) { + throw new AssertionError("Assumed correct key spec statically"); + } + } + } + + /** + * Utility for compressing an elliptic curve point. Returns the same point if it's already + * compressed. See the ECKey class docs for a discussion of point compression. + * + * @param uncompressed - + * @return - + * @deprecated per-point compression property will be removed in Bouncy Castle + */ + public static ECPoint compressPoint(ECPoint uncompressed) { + return CURVE.getCurve().decodePoint(uncompressed.getEncoded(true)); + } + + /** + * Utility for decompressing an elliptic curve point. Returns the same point if it's already + * compressed. See the ECKey class docs for a discussion of point compression. + * + * @param compressed - + * @return - + * @deprecated per-point compression property will be removed in Bouncy Castle + */ + public static ECPoint decompressPoint(ECPoint compressed) { + return CURVE.getCurve().decodePoint(compressed.getEncoded(false)); + } + + /** + * Creates an ECKey given the private key only. + * + * @param privKey - + * @return - + */ + public static ECKey fromPrivate(BigInteger privKey) { + return new ECKey(privKey, CURVE.getG().multiply(privKey)); + } + + /** + * Creates an ECKey given the private key only. + * + * @param privKeyBytes - + * @return - + */ + public static ECKey fromPrivate(byte[] privKeyBytes) { + return fromPrivate(new BigInteger(1, privKeyBytes)); + } + + /** + * Creates an ECKey that simply trusts the caller to ensure that point is really the result of + * multiplying the generator point by the private key. This is used to speed things up when you + * know you have the right values already. The compression state of pub will be preserved. + * + * @param priv - + * @param pub - + * @return - + */ + public static ECKey fromPrivateAndPrecalculatedPublic(BigInteger priv, + ECPoint pub) { + return new ECKey(priv, pub); + } + + /** + * Creates an ECKey that simply trusts the caller to ensure that point is really the result of + * multiplying the generator point by the private key. This is used to speed things up when you + * know you have the right values already. The compression state of the point will be preserved. + * + * @param priv - + * @param pub - + * @return - + */ + public static ECKey fromPrivateAndPrecalculatedPublic(byte[] priv, byte[] + pub) { + check(priv != null, "Private key must not be null"); + check(pub != null, "Public key must not be null"); + return new ECKey(new BigInteger(1, priv), CURVE.getCurve() + .decodePoint(pub)); + } + + /** + * Creates an ECKey that cannot be used for signing, only verifying signatures, from the given + * point. The compression state of pub will be preserved. + * + * @param pub - + * @return - + */ + public static ECKey fromPublicOnly(ECPoint pub) { + return new ECKey(null, pub); + } + + /** + * Creates an ECKey that cannot be used for signing, only verifying signatures, from the given + * encoded point. The compression state of pub will be preserved. + * + * @param pub - + * @return - + */ + public static ECKey fromPublicOnly(byte[] pub) { + return new ECKey(null, CURVE.getCurve().decodePoint(pub)); + } + + /** + * Returns public key bytes from the given private key. To convert a byte array into a BigInteger, + * use new BigInteger(1, bytes); + * + * @param privKey - + * @param compressed - + * @return - + */ + public static byte[] publicKeyFromPrivate(BigInteger privKey, boolean + compressed) { + ECPoint point = CURVE.getG().multiply(privKey); + return point.getEncoded(compressed); + } + + /** + * Compute the encoded X, Y coordinates of a public point.

This is the encoded public key + * without the leading byte. + * + * @param pubPoint a public point + * @return 64-byte X,Y point pair + */ + public static byte[] pubBytesWithoutFormat(ECPoint pubPoint) { + final byte[] pubBytes = pubPoint.getEncoded(/* uncompressed */ false); + return Arrays.copyOfRange(pubBytes, 1, pubBytes.length); + } + + /** + * Recover the public key from an encoded node id. + * + * @param nodeId a 64-byte X,Y point pair + */ + public static ECKey fromNodeId(byte[] nodeId) { + check(nodeId.length == 64, "Expected a 64 byte node id"); + byte[] pubBytes = new byte[65]; + System.arraycopy(nodeId, 0, pubBytes, 1, nodeId.length); + pubBytes[0] = 0x04; // uncompressed + return ECKey.fromPublicOnly(pubBytes); + } + + public static byte[] signatureToKeyBytes(byte[] messageHash, String + signatureBase64) throws SignatureException { + byte[] signatureEncoded; + try { + signatureEncoded = Base64.decode(signatureBase64); + } catch (RuntimeException e) { + // This is what you getData back from Bouncy Castle if base64 doesn't + // decode :( + throw new SignatureException("Could not decode base64", e); + } + // Parse the signature bytes into r/s and the selector value. + if (signatureEncoded.length < 65) { + throw new SignatureException("Signature truncated, expected 65 " + + "bytes and got " + signatureEncoded.length); + } + + return signatureToKeyBytes( + messageHash, + ECDSASignature.fromComponents( + Arrays.copyOfRange(signatureEncoded, 1, 33), + Arrays.copyOfRange(signatureEncoded, 33, 65), + (byte) (signatureEncoded[0] & 0xFF))); + } + + public static byte[] signatureToKeyBytes(byte[] messageHash, + ECDSASignature sig) throws + SignatureException { + check(messageHash.length == 32, "messageHash argument has length " + + messageHash.length); + int header = sig.v; + // The header byte: 0x1B = first key with even y, 0x1C = first key + // with odd y, + // 0x1D = second key with even y, 0x1E = second key + // with odd y + if (header < 27 || header > 34) { + throw new SignatureException("Header byte out of range: " + header); + } + if (header >= 31) { + header -= 4; + } + int recId = header - 27; + byte[] key = ECKey.recoverPubBytesFromSignature(recId, sig, + messageHash); + if (key == null) { + throw new SignatureException("Could not recover public key from " + + "signature"); + } + return key; + } + + /** + * Compute the address of the key that signed the given signature. + * + * @param messageHash 32-byte hash of message + * @param signatureBase64 Base-64 encoded signature + * @return 20-byte address + */ + public static byte[] signatureToAddress(byte[] messageHash, String + signatureBase64) throws SignatureException { + return computeAddress(signatureToKeyBytes(messageHash, + signatureBase64)); + } + + /** + * Compute the address of the key that signed the given signature. + * + * @param messageHash 32-byte hash of message + * @param sig - + * @return 20-byte address + */ + public static byte[] signatureToAddress(byte[] messageHash, + ECDSASignature sig) throws + SignatureException { + return computeAddress(signatureToKeyBytes(messageHash, sig)); + } + + /** + * Compute the key that signed the given signature. + * + * @param messageHash 32-byte hash of message + * @param signatureBase64 Base-64 encoded signature + * @return ECKey + */ + public static ECKey signatureToKey(byte[] messageHash, String + signatureBase64) throws SignatureException { + final byte[] keyBytes = signatureToKeyBytes(messageHash, + signatureBase64); + return ECKey.fromPublicOnly(keyBytes); + } + + /** + * Compute the key that signed the given signature. + * + * @param messageHash 32-byte hash of message + * @param sig - + * @return ECKey + */ + public static ECKey signatureToKey(byte[] messageHash, ECDSASignature + sig) throws SignatureException { + final byte[] keyBytes = signatureToKeyBytes(messageHash, sig); + return ECKey.fromPublicOnly(keyBytes); + } + + /** + *

Verifies the given ECDSA signature against the message bytes using the public key bytes.

+ *

When using native ECDSA verification, data must be 32 bytes, and no element may be + * larger than 520 bytes.

+ * + * @param data Hash of the data to verify. + * @param signature signature. + * @param pub The public key bytes to use. + * @return - + */ + public static boolean verify(byte[] data, ECDSASignature signature, + byte[] pub) { + ECDSASigner signer = new ECDSASigner(); + ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE + .getCurve().decodePoint(pub), CURVE); + signer.init(false, params); + try { + return signer.verifySignature(data, signature.r, signature.s); + } catch (NullPointerException npe) { + // Bouncy Castle contains a bug that can cause NPEs given + // specially crafted signatures. + // Those signatures are inherently invalid/attack sigs so we just + // fail them here rather than crash the thread. + logger.error("Caught NPE inside bouncy castle", npe); + return false; + } + } + + /** + * Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key. + * + * @param data Hash of the data to verify. + * @param signature signature. + * @param pub The public key bytes to use. + * @return - + */ + public static boolean verify(byte[] data, byte[] signature, byte[] pub) { + return verify(data, ECDSASignature.decodeFromDER(signature), pub); + } + + /** + * Returns true if the given pubkey is canonical, i.e. the correct length taking into account + * compression. + * + * @param pubkey - + * @return - + */ + public static boolean isPubKeyCanonical(byte[] pubkey) { + if (pubkey[0] == 0x04) { + // Uncompressed pubkey + return pubkey.length == 65; + } else if (pubkey[0] == 0x02 || pubkey[0] == 0x03) { + // Compressed pubkey + return pubkey.length == 33; + } else { + return false; + } + } + + /** + *

Given the components of a signature and a selector value, recover and return the public key + * that generated the signature according to the algorithm in SEC1v2 section 4.1.6.

+ * + *

The recId is an index from 0 to 3 which indicates which of the 4 possible allKeys is the + * correct one. Because the key recovery operation yields multiple potential allKeys, the correct + * key must either be stored alongside the signature, or you must be willing to try each recId in + * turn until you find one that outputs the key you are expecting.

+ * + *

If this method returns null it means recovery was not possible and recId should be + * iterated.

+ * + *

Given the above two points, a correct usage of this method is inside a for loop from 0 + * to 3, and if the output is null OR a key that is not the one you expect, you try again with the + * next recId.

+ * + * @param recId Which possible key to recover. + * @param sig the R and S components of the signature, wrapped. + * @param messageHash Hash of the data that was signed. + * @return 65-byte encoded public key + */ + @Nullable + public static byte[] recoverPubBytesFromSignature(int recId, + ECDSASignature sig, + byte[] messageHash) { + check(recId >= 0, "recId must be positive"); + check(sig.r.signum() >= 0, "r must be positive"); + check(sig.s.signum() >= 0, "s must be positive"); + check(messageHash != null, "messageHash must not be null"); + // 1.0 For j from 0 to h (h == recId here and the loop is outside + // this function) + // 1.1 Let x = r + jn + BigInteger n = CURVE.getN(); // Curve order. + BigInteger i = BigInteger.valueOf((long) recId / 2); + BigInteger x = sig.r.add(i.multiply(n)); + // 1.2. Convert the integer x to an octet string X of length mlen + // using the conversion routine + // specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or + // mlen = ⌈m/8⌉. + // 1.3. Convert the octet string (16 set binary digits)||X to an + // elliptic curve point R using the + // conversion routine specified in Section 2.3.4. If this + // conversion routine outputs “invalid”, then + // do another iteration of Step 1. + // + // More concisely, what these points mean is to use X as a compressed + // public key. + ECCurve.Fp curve = (ECCurve.Fp) CURVE.getCurve(); + BigInteger prime = curve.getQ(); // Bouncy Castle is not consistent + // about the letter it uses for the prime. + if (x.compareTo(prime) >= 0) { + // Cannot have point co-ordinates larger than this as everything + // takes place modulo Q. + return null; + } + // Compressed allKeys require you to know an extra bit of data about the + // y-coord as there are two possibilities. + // So it's encoded in the recId. + ECPoint R = decompressKey(x, (recId & 1) == 1); + // 1.4. If nR != point at infinity, then do another iteration of + // Step 1 (callers responsibility). + if (!R.multiply(n).isInfinity()) { + return null; + } + // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature + // verification. + BigInteger e = new BigInteger(1, messageHash); + // 1.6. For k from 1 to 2 do the following. (loop is outside this + // function via iterating recId) + // 1.6.1. Compute a candidate public key as: + // Q = mi(r) * (sR - eG) + // + // Where mi(x) is the modular multiplicative inverse. We transform + // this into the following: + // Q = (mi(r) * s ** R) + (mi(r) * -e ** G) + // Where -e is the modular additive inverse of e, that is z such that + // z + e = 0 (mod n). In the above equation + // ** is point multiplication and + is point addition (the EC group + // operator). + // + // We can find the additive inverse by subtracting e from zero then + // taking the mod. For example the additive + // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod + // 11 = 8. + BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n); + BigInteger rInv = sig.r.modInverse(n); + BigInteger srInv = rInv.multiply(sig.s).mod(n); + BigInteger eInvrInv = rInv.multiply(eInv).mod(n); + ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE + .getG(), eInvrInv, R, srInv); + return q.getEncoded(/* compressed */ false); + } + + /** + * @param recId Which possible key to recover. + * @param sig the R and S components of the signature, wrapped. + * @param messageHash Hash of the data that was signed. + * @return 20-byte address + */ + @Nullable + public static byte[] recoverAddressFromSignature(int recId, + ECDSASignature sig, + byte[] messageHash) { + final byte[] pubBytes = recoverPubBytesFromSignature(recId, sig, + messageHash); + if (pubBytes == null) { + return null; + } else { + return computeAddress(pubBytes); + } + } + + /** + * @param recId Which possible key to recover. + * @param sig the R and S components of the signature, wrapped. + * @param messageHash Hash of the data that was signed. + * @return ECKey + */ + @Nullable + public static ECKey recoverFromSignature(int recId, ECDSASignature sig, + byte[] messageHash) { + final byte[] pubBytes = recoverPubBytesFromSignature(recId, sig, + messageHash); + if (pubBytes == null) { + return null; + } else { + return ECKey.fromPublicOnly(pubBytes); + } + } + + /** + * Decompress a compressed public key (x co-ord and low-bit of y-coord). + * + * @param xBN - + * @param yBit - + * @return - + */ + + private static ECPoint decompressKey(BigInteger xBN, boolean yBit) { + X9IntegerConverter x9 = new X9IntegerConverter(); + byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE + .getCurve())); + compEnc[0] = (byte) (yBit ? 0x03 : 0x02); + return CURVE.getCurve().decodePoint(compEnc); + } + + private static void check(boolean test, String message) { + if (!test) { + throw new IllegalArgumentException(message); + } + } + + /** + * Returns a copy of this key, but with the public point represented in uncompressed form. + * Normally you would never need this: it's for specialised scenarios or when backwards + * compatibility in encoded form is necessary. + * + * @return - + * @deprecated per-point compression property will be removed in Bouncy Castle + */ + public ECKey decompress() { + if (!pub.isCompressed()) { + return this; + } else { + return new ECKey(this.provider, this.privKey, decompressPoint(pub)); + } + } + + /** + * @deprecated per-point compression property will be removed in Bouncy Castle + */ + public ECKey compress() { + if (pub.isCompressed()) { + return this; + } else { + return new ECKey(this.provider, this.privKey, compressPoint(pub)); + } + } + + /** + * Returns true if this key doesn't have access to private key bytes. This may be because it was + * never given any private key bytes to begin with (a watching key). + * + * @return - + */ + public boolean isPubKeyOnly() { + return privKey == null; + } + + /** + * Returns true if this key has access to private key bytes. Does the opposite of {@link + * #isPubKeyOnly()}. + * + * @return - + */ + public boolean hasPrivKey() { + return privKey != null; + } + + /** + * Gets the address form of the public key. + * + * @return 21-byte address + */ + public byte[] getAddress() { + if (pubKeyHash == null) { + pubKeyHash = computeAddress(this.pub); + } + return pubKeyHash; + } + + /** + * Generates the NodeID based on this key, that is the public key without first format byte + */ + public byte[] getNodeId() { + if (nodeId == null) { + nodeId = pubBytesWithoutFormat(this.pub); + } + return nodeId; + } + + /** + * Gets the encoded public key value. + * + * @return 65-byte encoded public key + */ + public byte[] getPubKey() { + return pub.getEncoded(/* compressed */ false); + } + + /** + * Gets the public key in the form of an elliptic curve point object from Bouncy Castle. + * + * @return - + */ + public ECPoint getPubKeyPoint() { + return pub; + } + + /** + * Gets the private key in the form of an integer field element. The public key is derived by + * performing EC point addition this number of times (i.e. point multiplying). + * + * @return - + * @throws IllegalStateException if the private key bytes are not available. + */ + public BigInteger getPrivKey() { + if (privKey == null) { + throw new MissingPrivateKeyException(); + } else if (privKey instanceof BCECPrivateKey) { + return ((BCECPrivateKey) privKey).getD(); + } else { + throw new MissingPrivateKeyException(); + } + } + + /** + * Returns whether this key is using the compressed form or not. Compressed pubkeys are only 33 + * bytes, not 64. + * + * @return - + */ + public boolean isCompressed() { + return pub.isCompressed(); + } + + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("pub:").append(Hex.toHexString(pub.getEncoded(false))); + return b.toString(); + } + + /** + * Produce a string rendering of the ECKey INCLUDING the private key. Unless you absolutely need + * the private key it is better for security reasons to just use toString(). + * + * @return - + */ + public String toStringWithPrivate() { + StringBuilder b = new StringBuilder(); + b.append(toString()); + if (privKey != null && privKey instanceof BCECPrivateKey) { + b.append(" priv:").append(Hex.toHexString(((BCECPrivateKey) + privKey).getD().toByteArray())); + } + return b.toString(); + } + + /** + * Signs the given hash and returns the R and S components as BigIntegers and putData them in + * ECDSASignature + * + * @param input to sign + * @return ECDSASignature signature that contains the R and S components + */ + public ECDSASignature doSign(byte[] input) { + if (input.length != 32) { + throw new IllegalArgumentException("Expected 32 byte input to " + + "ECDSA signature, not " + input.length); + } + // No decryption of private key required. + if (privKey == null) { + throw new MissingPrivateKeyException(); + } + if (privKey instanceof BCECPrivateKey) { + ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new + SHA256Digest())); + ECPrivateKeyParameters privKeyParams = new ECPrivateKeyParameters + (((BCECPrivateKey) privKey).getD(), CURVE); + signer.init(true, privKeyParams); + BigInteger[] components = signer.generateSignature(input); + return new ECDSASignature(components[0], components[1]) + .toCanonicalised(); + } else { + try { + final Signature ecSig = ECSignatureFactory.getRawInstance + (provider); + ecSig.initSign(privKey); + ecSig.update(input); + final byte[] derSignature = ecSig.sign(); + return ECDSASignature.decodeFromDER(derSignature) + .toCanonicalised(); + } catch (SignatureException | InvalidKeyException ex) { + throw new RuntimeException("ECKey signing error", ex); + } + } + } + + /** + * Takes the keccak hash (32 bytes) of data and returns the ECDSA signature + * + * @param messageHash - + * @return - + * @throws IllegalStateException if this ECKey does not have the private part. + */ + public ECDSASignature sign(byte[] messageHash) { + ECDSASignature sig = doSign(messageHash); + // Now we have to work backwards to figure out the recId needed to + // recover the signature. + int recId = -1; + byte[] thisKey = this.pub.getEncoded(/* compressed */ false); + for (int i = 0; i < 4; i++) { + byte[] k = ECKey.recoverPubBytesFromSignature(i, sig, messageHash); + if (k != null && Arrays.equals(k, thisKey)) { + recId = i; + break; + } + } + if (recId == -1) { + throw new RuntimeException("Could not construct a recoverable key" + + ". This should never happen."); + } + sig.v = (byte) (recId + 27); + return sig; + } + + public BigInteger keyAgreement(ECPoint otherParty) { + if (privKey == null) { + throw new MissingPrivateKeyException(); + } else if (privKey instanceof BCECPrivateKey) { + final ECDHBasicAgreement agreement = new ECDHBasicAgreement(); + agreement.init(new ECPrivateKeyParameters(((BCECPrivateKey) + privKey).getD(), CURVE)); + return agreement.calculateAgreement(new ECPublicKeyParameters + (otherParty, CURVE)); + } else { + try { + final KeyAgreement agreement = ECKeyAgreement.getInstance + (this.provider); + agreement.init(this.privKey); + agreement.doPhase( + ECKeyFactory.getInstance(this.provider) + .generatePublic(new ECPublicKeySpec + (otherParty, CURVE_SPEC)), + /* lastPhase */ true); + return new BigInteger(1, agreement.generateSecret()); + } catch (IllegalStateException | InvalidKeyException | + InvalidKeySpecException ex) { + throw new RuntimeException("ECDH key agreement failure", ex); + } + } + } + + /** + * Decrypt cipher by AES in SIC(also know as CTR) mode + * + * @param cipher -proper cipher + * @return decrypted cipher, equal length to the cipher. + * @deprecated should not use EC private scalar value as an AES key + */ + public byte[] decryptAES(byte[] cipher) { + + if (privKey == null) { + throw new MissingPrivateKeyException(); + } + if (!(privKey instanceof BCECPrivateKey)) { + throw new UnsupportedOperationException("Cannot use the private " + + "key as an AES key"); + } + + AESEngine engine = new AESEngine(); + SICBlockCipher ctrEngine = new SICBlockCipher(engine); + + KeyParameter key = new KeyParameter(BigIntegers.asUnsignedByteArray(( + (BCECPrivateKey) privKey).getD())); + ParametersWithIV params = new ParametersWithIV(key, new byte[16]); + + ctrEngine.init(false, params); + + int i = 0; + byte[] out = new byte[cipher.length]; + while (i < cipher.length) { + ctrEngine.processBlock(cipher, i, out, i); + i += engine.getBlockSize(); + if (cipher.length - i < engine.getBlockSize()) { + break; + } + } + + // process left bytes + if (cipher.length - i > 0) { + byte[] tmpBlock = new byte[16]; + System.arraycopy(cipher, i, tmpBlock, 0, cipher.length - i); + ctrEngine.processBlock(tmpBlock, 0, tmpBlock, 0); + System.arraycopy(tmpBlock, 0, out, i, cipher.length - i); + } + + return out; + } + + /** + * Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key. + * + * @param data Hash of the data to verify. + * @param signature signature. + * @return - + */ + public boolean verify(byte[] data, byte[] signature) { + return ECKey.verify(data, signature, getPubKey()); + } + + /** + * Verifies the given R/S pair (signature) against a hash using the public key. + * + * @param sigHash - + * @param signature - + * @return - + */ + public boolean verify(byte[] sigHash, ECDSASignature signature) { + return ECKey.verify(sigHash, signature, getPubKey()); + } + + /** + * Returns true if this pubkey is canonical, i.e. the correct length taking into account + * compression. + * + * @return - + */ + public boolean isPubKeyCanonical() { + return isPubKeyCanonical(pub.getEncoded(/* uncompressed */ false)); + } + + /** + * Returns a 32 byte array containing the private key, or null if the key is encrypted or public + * only + * + * @return - + */ + @Nullable + public byte[] getPrivKeyBytes() { + if (privKey == null) { + return null; + } else if (privKey instanceof BCECPrivateKey) { + return bigIntegerToBytes(((BCECPrivateKey) privKey).getD(), 32); + } else { + return null; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + ECKey ecKey = (ECKey) o; + + if (privKey != null && !privKey.equals(ecKey.privKey)) { + return false; + } + return pub == null || pub.equals(ecKey.pub); + } + + @Override + public int hashCode() { + return Arrays.hashCode(getPubKey()); + } + + public static class ECDSASignature { + + /** + * The two components of the signature. + */ + public final BigInteger r, s; + public byte v; + + /** + * Constructs a signature with the given components. Does NOT automatically canonicalise the + * signature. + * + * @param r - + * @param s - + */ + public ECDSASignature(BigInteger r, BigInteger s) { + this.r = r; + this.s = s; + } + + /** + * t + * + * @return - + */ + private static ECDSASignature fromComponents(byte[] r, byte[] s) { + return new ECDSASignature(new BigInteger(1, r), new BigInteger(1, + s)); + } + + /** + * @param r - + * @param s - + * @param v - + * @return - + */ + public static ECDSASignature fromComponents(byte[] r, byte[] s, byte + v) { + ECDSASignature signature = fromComponents(r, s); + signature.v = v; + return signature; + } + + public static boolean validateComponents(BigInteger r, BigInteger s, + byte v) { + + if (v != 27 && v != 28) { + return false; + } + + if (isLessThan(r, BigInteger.ONE)) { + return false; + } + if (isLessThan(s, BigInteger.ONE)) { + return false; + } + + if (!isLessThan(r, SECP256K1N)) { + return false; + } + return isLessThan(s, SECP256K1N); + } + + public static ECDSASignature decodeFromDER(byte[] bytes) { + ASN1InputStream decoder = null; + try { + decoder = new ASN1InputStream(bytes); + DLSequence seq = (DLSequence) decoder.readObject(); + if (seq == null) { + throw new RuntimeException("Reached past end of ASN.1 " + + "stream."); + } + ASN1Integer r, s; + try { + r = (ASN1Integer) seq.getObjectAt(0); + s = (ASN1Integer) seq.getObjectAt(1); + } catch (ClassCastException e) { + throw new IllegalArgumentException(e); + } + // OpenSSL deviates from the DER spec by interpreting these + // values as unsigned, though they should not be + // Thus, we always use the positive versions. See: + // http://r6.ca/blog/20111119T211504Z.html + return new ECDSASignature(r.getPositiveValue(), s + .getPositiveValue()); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (decoder != null) { + try { + decoder.close(); + } catch (IOException x) { + + } + } + } + } + + public boolean validateComponents() { + return validateComponents(r, s, v); + } + + public ECDSASignature toCanonicalised() { + if (s.compareTo(HALF_CURVE_ORDER) > 0) { + // The order of the curve is the number of valid points that + // exist on that curve. If S is in the upper + // half of the number of valid points, then bring it back to + // the lower half. Otherwise, imagine that + // N = 10 + // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) + // are valid solutions. + // 10 - 8 == 2, giving us always the latter solution, + // which is canonical. + return new ECDSASignature(r, CURVE.getN().subtract(s)); + } else { + return this; + } + } + + /** + * @return - + */ + public String toBase64() { + byte[] sigData = new byte[65]; // 1 header + 32 bytes for R + 32 + // bytes for S + sigData[0] = v; + System.arraycopy(bigIntegerToBytes(this.r, 32), 0, sigData, 1, 32); + System.arraycopy(bigIntegerToBytes(this.s, 32), 0, sigData, 33, 32); + return new String(Base64.encode(sigData), Charset.forName("UTF-8")); + } + + public byte[] toByteArray() { + final byte fixedV = this.v >= 27 + ? (byte) (this.v - 27) + : this.v; + + return ByteUtil.merge( + ByteUtil.bigIntegerToBytes(this.r, 32), + ByteUtil.bigIntegerToBytes(this.s, 32), + new byte[]{fixedV}); + } + + public String toHex() { + return Hex.toHexString(toByteArray()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ECDSASignature signature = (ECDSASignature) o; + + if (!r.equals(signature.r)) { + return false; + } + return s.equals(signature.s); + } + + @Override + public int hashCode() { + int result = r.hashCode(); + result = 31 * result + s.hashCode(); + return result; + } + } + + @SuppressWarnings("serial") + public static class MissingPrivateKeyException extends RuntimeException { + + } + +} + diff --git a/framework/src/main/java/org/tron/common/crypto/jce/ECAlgorithmParameters.java b/chainbase/src/main/java/org/tron/common/crypto/jce/ECAlgorithmParameters.java similarity index 100% rename from framework/src/main/java/org/tron/common/crypto/jce/ECAlgorithmParameters.java rename to chainbase/src/main/java/org/tron/common/crypto/jce/ECAlgorithmParameters.java diff --git a/framework/src/main/java/org/tron/common/crypto/jce/ECKeyAgreement.java b/chainbase/src/main/java/org/tron/common/crypto/jce/ECKeyAgreement.java similarity index 100% rename from framework/src/main/java/org/tron/common/crypto/jce/ECKeyAgreement.java rename to chainbase/src/main/java/org/tron/common/crypto/jce/ECKeyAgreement.java diff --git a/framework/src/main/java/org/tron/common/crypto/jce/ECKeyFactory.java b/chainbase/src/main/java/org/tron/common/crypto/jce/ECKeyFactory.java similarity index 100% rename from framework/src/main/java/org/tron/common/crypto/jce/ECKeyFactory.java rename to chainbase/src/main/java/org/tron/common/crypto/jce/ECKeyFactory.java diff --git a/framework/src/main/java/org/tron/common/crypto/jce/ECKeyPairGenerator.java b/chainbase/src/main/java/org/tron/common/crypto/jce/ECKeyPairGenerator.java similarity index 100% rename from framework/src/main/java/org/tron/common/crypto/jce/ECKeyPairGenerator.java rename to chainbase/src/main/java/org/tron/common/crypto/jce/ECKeyPairGenerator.java diff --git a/framework/src/main/java/org/tron/common/crypto/jce/ECSignatureFactory.java b/chainbase/src/main/java/org/tron/common/crypto/jce/ECSignatureFactory.java similarity index 100% rename from framework/src/main/java/org/tron/common/crypto/jce/ECSignatureFactory.java rename to chainbase/src/main/java/org/tron/common/crypto/jce/ECSignatureFactory.java diff --git a/chainbase/src/main/java/org/tron/common/utils/BIUtil.java b/chainbase/src/main/java/org/tron/common/utils/BIUtil.java new file mode 100644 index 00000000000..89d978d76a1 --- /dev/null +++ b/chainbase/src/main/java/org/tron/common/utils/BIUtil.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ + +package org.tron.common.utils; + +import java.math.BigInteger; + +public class BIUtil { + + /** + * @param valueA - not null + * @param valueB - not null + * @return true - if the valueA is less than valueB is zero + */ + public static boolean isLessThan(BigInteger valueA, BigInteger valueB) { + return valueA.compareTo(valueB) < 0; + } + + /** + * @param value - not null + * @return true - if the param is zero + */ + public static boolean isZero(BigInteger value) { + return value.compareTo(BigInteger.ZERO) == 0; + } + + /** + * @param valueA - not null + * @param valueB - not null + * @return true - if the valueA is equal to valueB is zero + */ + public static boolean isEqual(BigInteger valueA, BigInteger valueB) { + return valueA.compareTo(valueB) == 0; + } + + /** + * @param valueA - not null + * @param valueB - not null + * @return true - if the valueA is not equal to valueB is zero + */ + public static boolean isNotEqual(BigInteger valueA, BigInteger valueB) { + return !isEqual(valueA, valueB); + } + + /** + * @param valueA - not null + * @param valueB - not null + * @return true - if the valueA is more than valueB is zero + */ + public static boolean isMoreThan(BigInteger valueA, BigInteger valueB) { + return valueA.compareTo(valueB) > 0; + } + + + /** + * @param valueA - not null + * @param valueB - not null + * @return sum - valueA + valueB + */ + public static BigInteger sum(BigInteger valueA, BigInteger valueB) { + return valueA.add(valueB); + } + + + /** + * @param data = not null + * @return new positive BigInteger + */ + public static BigInteger toBI(byte[] data) { + return new BigInteger(1, data); + } + + /** + * @param data = not null + * @return new positive BigInteger + */ + public static BigInteger toBI(long data) { + return BigInteger.valueOf(data); + } + + + public static boolean isPositive(BigInteger value) { + return value.signum() > 0; + } + + public static boolean isNotCovers(BigInteger covers, BigInteger value) { + return covers.compareTo(value) < 0; + } + + public static BigInteger max(BigInteger first, BigInteger second) { + return first.compareTo(second) < 0 ? second : first; + } + + /** + * Returns a result of safe addition of two {@code int} values {@code Integer.MAX_VALUE} is + * returned if overflow occurs + */ + public static int addSafely(int a, int b) { + long res = (long) a + (long) b; + return res > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) res; + } +} diff --git a/chainbase/src/main/java/org/tron/core/store/WitnessScheduleStore.java b/chainbase/src/main/java/org/tron/core/store/WitnessScheduleStore.java new file mode 100644 index 00000000000..227b65b6c98 --- /dev/null +++ b/chainbase/src/main/java/org/tron/core/store/WitnessScheduleStore.java @@ -0,0 +1,74 @@ +package org.tron.core.store; + +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.tron.common.utils.ByteArray; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.db.TronStoreWithRevoking; + +@Slf4j(topic = "DB") +@Component +public class WitnessScheduleStore extends TronStoreWithRevoking { + + private static final byte[] ACTIVE_WITNESSES = "active_witnesses".getBytes(); + private static final byte[] CURRENT_SHUFFLED_WITNESSES = "current_shuffled_witnesses".getBytes(); + + private static final int ADDRESS_BYTE_ARRAY_LENGTH = 21; + + @Autowired + private WitnessScheduleStore(@Value("witness_schedule") String dbName) { + super(dbName); + } + + private void saveData(byte[] species, List witnessesAddressList) { + byte[] ba = new byte[witnessesAddressList.size() * ADDRESS_BYTE_ARRAY_LENGTH]; + int i = 0; + for (ByteString address : witnessesAddressList) { + System.arraycopy(address.toByteArray(), 0, + ba, i * ADDRESS_BYTE_ARRAY_LENGTH, ADDRESS_BYTE_ARRAY_LENGTH); + i++; + } + + this.put(species, new BytesCapsule(ba)); + } + + private List getData(byte[] species) { + List witnessesAddressList = new ArrayList<>(); + return Optional.ofNullable(getUnchecked(species)) + .map(BytesCapsule::getData) + .map(ba -> { + int len = ba.length / ADDRESS_BYTE_ARRAY_LENGTH; + for (int i = 0; i < len; ++i) { + byte[] b = new byte[ADDRESS_BYTE_ARRAY_LENGTH]; + System.arraycopy(ba, i * ADDRESS_BYTE_ARRAY_LENGTH, b, 0, ADDRESS_BYTE_ARRAY_LENGTH); + witnessesAddressList.add(ByteString.copyFrom(b)); + } + logger.debug("getWitnesses:" + ByteArray.toStr(species) + witnessesAddressList); + return witnessesAddressList; + }).orElseThrow( + () -> new IllegalArgumentException( + "not found " + ByteArray.toStr(species) + "Witnesses")); + } + + public void saveActiveWitnesses(List witnessesAddressList) { + saveData(ACTIVE_WITNESSES, witnessesAddressList); + } + + public List getActiveWitnesses() { + return getData(ACTIVE_WITNESSES); + } + + public void saveCurrentShuffledWitnesses(List witnessesAddressList) { + saveData(CURRENT_SHUFFLED_WITNESSES, witnessesAddressList); + } + + public List getCurrentShuffledWitnesses() { + return getData(CURRENT_SHUFFLED_WITNESSES); + } +} diff --git a/consensus/build.gradle b/consensus/build.gradle new file mode 100644 index 00000000000..a26b8f2a21b --- /dev/null +++ b/consensus/build.gradle @@ -0,0 +1,197 @@ +buildscript { + repositories { + mavenCentral() + jcenter() + maven { url 'https://jitpack.io' } + } + dependencies { + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3' + classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2' + } +} + +group = "com.github.tronprotocol" +ext.githubProjectName = "consensus" + +version = project.properties["release.version"] + +apply plugin: "java-library" +//apply plugin: "checkstyle" +apply plugin: "jacoco" +apply plugin: "maven" +apply plugin: "maven-publish" +//apply plugin: "me.champeau.gradle.jmh" + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +// Dependency versions +// --------------------------------------- + +def junitVersion = "4.12" +def mockitoVersion = "2.1.0" +def jmhLibVersion = "1.20" +def testNgVersion = "6.11" +def guavaVersion = "24.1-jre" +def jacocoVersion = "0.8.0" +def leveldbVersion = "1.8" +def logbackVersion = "1.2.3" +def jansiVersion = "1.16" +def lombokVersion = "1.18.2" +def slf4jVersion = "1.7.25" +// -------------------------------------- + +repositories { + mavenCentral() + maven { url 'https://jitpack.io' } +} + +dependencies { + compile project(":chainbase") + compile project(":protocol") + testImplementation "junit:junit:$junitVersion" + testImplementation "org.mockito:mockito-core:$mockitoVersion" + + testImplementation "org.testng:testng:$testNgVersion" + + compile "com.google.guava:guava:$guavaVersion" + compile "org.fusesource.leveldbjni:leveldbjni-all:$leveldbVersion" + compile "org.fusesource.jansi:jansi:$jansiVersion" + compile "org.slf4j:slf4j-api:$slf4jVersion" + compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" + compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3' + compile "org.projectlombok:lombok:$lombokVersion" + compile group: 'org.rocksdb', name: 'rocksdbjni', version: '5.15.10' + compile "com.madgag.spongycastle:core:1.58.0.0" + compile "org.apache.commons:commons-lang3:3.4" + compile 'com.github.tronprotocol:zksnark-java-sdk:master-SNAPSHOT' +} + +//javadoc { +// failOnError = false +// exclude "**/test/**" +// options { +// windowTitle = "Chainbase Javadoc ${project.version}" +// } +// // Clear the following options to make the docs consistent with the old format +// options.addStringOption("top").value = "" +// options.addStringOption("doctitle").value = "" +// options.addStringOption("header").value = "" +// options.stylesheetFile = new File(projectDir, "gradle/stylesheet.css"); +// +// options.links( +// "https://docs.oracle.com/javase/7/docs/api/" +// ) +// +// if (JavaVersion.current().isJava7()) { +// // "./gradle/stylesheet.css" only supports Java 7 +// options.addStringOption("stylesheetfile", rootProject.file("./gradle/stylesheet.css").toString()) +// } +//} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = "sources" + from sourceSets.main.allSource +} + +//task javadocJar(type: Jar, dependsOn: javadoc) { +// classifier = "javadoc" +// from javadoc.destinationDir +//} + +artifacts { + archives jar + archives sourcesJar +// archives javadocJar +} + + +//jmh { +// jmhVersion = jmhLibVersion +// humanOutputFile = null +// includeTests = false +// jvmArgs = ["-Djmh.ignoreLock=true"] +// jvmArgsAppend = ["-Djmh.separateClasspathJAR=true"] +// +// if (project.hasProperty("jmh")) { +// include = ".*" + project.jmh + ".*" +// println("JMH: " + include); +// } +// +//} + +//plugins.withType(EclipsePlugin) { +// project.eclipse.classpath.plusConfigurations += [ configurations.jmh ] +//} + +test { + + testLogging { + // showing skipped occasionally should prevent CI timeout due to lack of standard output + events=["skipped", "failed"] // "started", "passed" + // showStandardStreams = true + exceptionFormat="full" + + debug.events = ["skipped", "failed"] + debug.exceptionFormat="full" + + info.events = ["failed", "skipped"] + info.exceptionFormat="full" + + warn.events = ["failed", "skipped"] + warn.exceptionFormat="full" + } + + maxHeapSize = "1200m" + + if (System.getenv("CI") == null) { + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 + } +} + +task testng(type: Test) { + useTestNG() + testLogging { + events=["skipped", "failed"] + exceptionFormat="full" + + debug.events = ["skipped", "failed"] + debug.exceptionFormat="full" + + info.events = ["failed", "skipped"] + info.exceptionFormat="full" + + warn.events = ["failed", "skipped"] + warn.exceptionFormat="full" + } +} + +check.dependsOn testng + +jacoco { + toolVersion = jacocoVersion // See http://www.eclemma.org/jacoco/. +} + +jacocoTestReport { + reports { + xml.enabled = true + html.enabled = true + } + + afterEvaluate { + classDirectories = files(classDirectories.files.collect { + fileTree(dir: it, + exclude: ["io/reactivex/tck/**"]) + }) + } +} + +build.dependsOn jacocoTestReport + +//checkstyle { +// configFile file("checkstyle.xml") +// ignoreFailures = true +// toolVersion ="6.19" +//} + +//apply from: file("gradle/javadoc_cleanup.gradle") diff --git a/consensus/src/main/java/org/tron/consensus/Consensus.java b/consensus/src/main/java/org/tron/consensus/Consensus.java new file mode 100644 index 00000000000..e89311dcfb2 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/Consensus.java @@ -0,0 +1,37 @@ +package org.tron.consensus; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.consensus.base.ConsensusInterface; +import org.tron.consensus.base.Param; +import org.tron.consensus.dpos.DposService; +import org.tron.protos.Protocol.Block; + +@Slf4j(topic = "consensus") +@Component +public class Consensus { + + @Autowired + private DposService dposService; + + private ConsensusInterface consensusInterface; + + public void start(Param param) { + consensusInterface = dposService; + consensusInterface.start(param); + } + + public void stop() { + consensusInterface.stop(); + } + + public boolean validBlock(Block block){ + return consensusInterface.validBlock(block); + } + + public boolean applyBlock(Block block) { + return consensusInterface.applyBlock(block); + } + +} \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java new file mode 100644 index 00000000000..1a60df6ad51 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/ConsensusDelegate.java @@ -0,0 +1,155 @@ +package org.tron.consensus; + +import com.google.protobuf.ByteString; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.utils.Sha256Hash; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.core.store.VotesStore; +import org.tron.core.store.WitnessScheduleStore; +import org.tron.core.store.WitnessStore; + +@Slf4j(topic = "consensus") +@Component +public class ConsensusDelegate { + + @Autowired + private DynamicPropertiesStore dynamicPropertiesStore; + + @Autowired + private AccountStore accountStore; + + @Autowired + private WitnessStore witnessStore; + + @Autowired + private WitnessScheduleStore witnessScheduleStore; + + @Autowired + private VotesStore votesStore; + + public int calculateFilledSlotsCount() { + return dynamicPropertiesStore.calculateFilledSlotsCount(); + } + + public void saveRemoveThePowerOfTheGr(long rate) { + dynamicPropertiesStore.saveRemoveThePowerOfTheGr(rate); + } + + public long getRemoveThePowerOfTheGr() { + return dynamicPropertiesStore.getRemoveThePowerOfTheGr(); + } + + public long getWitnessStandbyAllowance() { + return dynamicPropertiesStore.getWitnessStandbyAllowance(); + } + + public long getLatestBlockHeaderTimestamp() { + return dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); + } + + public long getLatestBlockHeaderNumber() { + return dynamicPropertiesStore.getLatestBlockHeaderNumber(); + } + + public boolean lastHeadBlockIsMaintenance() { + return dynamicPropertiesStore.getStateFlag() == 1; + } + + public long getMaintenanceSkipSlots() { + return dynamicPropertiesStore.getMaintenanceSkipSlots(); + } + + public WitnessCapsule getWitnesseByAddress(ByteString address) { + return witnessStore.get(address.toByteArray()); + } + + public void saveActiveWitnesses(List addresses) { + witnessScheduleStore.saveActiveWitnesses(addresses); + } + + public List getActiveWitnesses() { + return witnessScheduleStore.getActiveWitnesses(); + } + + public WitnessStore getWitnessStore() { + return witnessStore; + } + + public VotesStore getVotesStore() { + return votesStore; + } + + public AccountStore getAccountStore() { + return accountStore; + } + + public void saveStateFlag(int flag) { + dynamicPropertiesStore.saveStateFlag(flag); + } + + public int saveStateFlag() { + return dynamicPropertiesStore.getStateFlag(); + } + + public long getMaintenanceTimeInterval() { + return dynamicPropertiesStore.getMaintenanceTimeInterval(); + } + + public void saveMaintenanceTimeInterval(long time) { + dynamicPropertiesStore.saveMaintenanceTimeInterval(time); + } + + public long getNextMaintenanceTime() { + return dynamicPropertiesStore.getNextMaintenanceTime(); + } + + public void saveNextMaintenanceTime(long time) { + dynamicPropertiesStore.saveNextMaintenanceTime(time); + } + + public long getWitnessPayPerBlock() { + return dynamicPropertiesStore.getWitnessPayPerBlock(); + } + + public long getLatestSolidifiedBlockNum() { + return dynamicPropertiesStore.getLatestSolidifiedBlockNum(); + } + + public void saveLatestSolidifiedBlockNum(long num) { + dynamicPropertiesStore.saveLatestSolidifiedBlockNum(num); + } + + public int[] getBlockFilledSlots() { + return dynamicPropertiesStore.getBlockFilledSlots(); + } + + public void saveBlockFilledSlots(int[] slots) { + dynamicPropertiesStore.saveBlockFilledSlots(slots); + } + + public int getBlockFilledSlotsIndex() { + return dynamicPropertiesStore.getBlockFilledSlotsIndex(); + } + + public void saveBlockFilledSlotsIndex(int index) { + dynamicPropertiesStore.saveBlockFilledSlotsIndex(index); + } + + public int getBlockFilledSlotsNumber() { + return dynamicPropertiesStore.getBlockFilledSlotsNumber(); + } + + public Sha256Hash getLatestBlockHeaderHash() { + return dynamicPropertiesStore.getLatestBlockHeaderHash(); + } + + public long getAllowMultiSign() { + return dynamicPropertiesStore.getAllowMultiSign(); + } + +} \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/base/BlockHandle.java b/consensus/src/main/java/org/tron/consensus/base/BlockHandle.java new file mode 100644 index 00000000000..50c8e93d4c2 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/base/BlockHandle.java @@ -0,0 +1,17 @@ + +package org.tron.consensus.base; + +import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.BlockHeader; + +public interface BlockHandle { + + State getState(); + + Object getLock(); + + Block produce(); + + void complete(Block block); + +} \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/base/ConsensusInterface.java b/consensus/src/main/java/org/tron/consensus/base/ConsensusInterface.java new file mode 100644 index 00000000000..20055a2c757 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/base/ConsensusInterface.java @@ -0,0 +1,15 @@ +package org.tron.consensus.base; + +import org.tron.protos.Protocol.Block; + +public interface ConsensusInterface { + + void start(Param param); + + void stop(); + + boolean validBlock(Block block); + + boolean applyBlock(Block block); + +} \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/base/Constant.java b/consensus/src/main/java/org/tron/consensus/base/Constant.java new file mode 100644 index 00000000000..a152dd167cc --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/base/Constant.java @@ -0,0 +1,17 @@ +package org.tron.consensus.base; + +public class Constant { + + public static final int MAX_ACTIVE_WITNESS_NUM = 27; + + public static final int BLOCK_PRODUCED_INTERVAL = 3000; + + public static final int SOLIDIFIED_THRESHOLD = 70; + + public static final int WITNESS_STANDBY_LENGTH = 127; + + public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; + + public static final int SINGLE_REPEAT = 1; + +} \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/base/Param.java b/consensus/src/main/java/org/tron/consensus/base/Param.java new file mode 100644 index 00000000000..0b74202a151 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/base/Param.java @@ -0,0 +1,40 @@ +package org.tron.consensus.base; + +import com.google.protobuf.ByteString; +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import org.tron.core.config.args.GenesisBlock; + +public class Param { + @Getter + @Setter + private boolean needSyncCheck; + @Getter + @Setter + private int minParticipationRate; + @Getter + @Setter + private List miners; + @Getter + @Setter + private GenesisBlock genesisBlock; + @Getter + @Setter + private BlockHandle blockHandle; + + public class Miner { + @Getter + @Setter + private byte[] privateKey; + + @Getter + @Setter + private ByteString privateKeyAddress; + + @Getter + @Setter + private ByteString witnessAddress; + } + +} \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/base/State.java b/consensus/src/main/java/org/tron/consensus/base/State.java new file mode 100644 index 00000000000..5aba4bb6c09 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/base/State.java @@ -0,0 +1,15 @@ +package org.tron.consensus.base; + +public enum State { + OK, + NOT_SYNCED, + DUP_WITNESS, + CLOCK_ERROR, + SLAVE_STATUS, + NOT_MY_TURN, + NOT_TIME_YET, + PERMISSION_ERROR, + LOW_PARTICIPATION, + PRODUCE_BLOCK_FAILED, + OTHER +} \ No newline at end of file diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposService.java b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java new file mode 100644 index 00000000000..b5c9d94a334 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposService.java @@ -0,0 +1,144 @@ +package org.tron.consensus.dpos; + + +import static org.tron.consensus.base.Constant.SOLIDIFIED_THRESHOLD; + +import com.google.protobuf.ByteString; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Sha256Hash; +import org.tron.consensus.ConsensusDelegate; +import org.tron.consensus.base.BlockHandle; +import org.tron.consensus.base.ConsensusInterface; +import org.tron.consensus.base.Param; +import org.tron.consensus.base.Param.Miner; +import org.tron.core.config.args.GenesisBlock; +import org.tron.protos.Protocol.Block; + +@Slf4j(topic = "consensus") +@Component +public class DposService implements ConsensusInterface { + + @Autowired + private ConsensusDelegate consensusDelegate; + + @Autowired + private DposTask dposTask; + + @Autowired + private DposSlot dposSlot; + + @Autowired + private IncentiveManager incentiveManager; + + @Autowired + private StateManager stateManager; + + @Autowired + private StatisticManager statisticManager; + + @Autowired + private MaintenanceManager maintenanceManager; + + @Getter + @Setter + private volatile boolean needSyncCheck; + @Getter + private int minParticipationRate; + @Getter + private GenesisBlock genesisBlock; + @Getter + private long genesisBlockTime; + @Getter + private BlockHandle blockHandle; + + @Getter + protected Map miners = new HashMap<>(); + + @Override + public void start(Param param) { + this.needSyncCheck = param.isNeedSyncCheck(); + this.minParticipationRate = param.getMinParticipationRate(); + this.blockHandle = param.getBlockHandle(); + this.genesisBlock = param.getGenesisBlock(); + this.genesisBlockTime = Long.parseLong(param.getGenesisBlock().getTimestamp()); + param.getMiners().forEach(miner -> miners.put(miner.getWitnessAddress(), miner)); + stateManager.setDposService(this); + dposTask.setDposService(this); + maintenanceManager.setDposService(this); + dposTask.init(); + } + + @Override + public void stop() { + + } + + @Override + public boolean validBlock(Block block) { + if (consensusDelegate.getLatestBlockHeaderNumber() == 0) { + return true; + } + ByteString witnessAddress = block.getBlockHeader().getRawData().getWitnessAddress(); + long timeStamp = block.getBlockHeader().getRawData().getTimestamp(); + long bSlot = dposSlot.getAbSlot(timeStamp); + long hSlot = dposSlot.getAbSlot(consensusDelegate.getLatestBlockHeaderTimestamp()); + if (bSlot <= hSlot) { + logger.warn("blockAbSlot is equals with headBlockAbSlot[" + bSlot + "]"); + return false; + } + + long slot = dposSlot.getSlot(timeStamp); + final ByteString scheduledWitness = dposSlot.getScheduledWitness(slot); + if (!scheduledWitness.equals(witnessAddress)) { + logger.warn( + "Witness out of order, scheduledWitness[{}],blockWitness[{}],blockTimeStamp[{}],slot[{}]", + ByteArray.toHexString(scheduledWitness.toByteArray()), + ByteArray.toHexString(witnessAddress.toByteArray()), new DateTime(timeStamp), slot); + return false; + } + return true; + } + + @Override + public boolean applyBlock(Block block) { + stateManager.applyBlock(block); + statisticManager.applyBlock(block); + incentiveManager.applyBlock(block); + maintenanceManager.applyBlock(block); + updateSolidBlock(); + return true; + } + + + private void updateSolidBlock() { + List numbers = consensusDelegate.getActiveWitnesses().stream() + .map(address -> consensusDelegate.getWitnesseByAddress(address).getLatestBlockNum()) + .sorted() + .collect(Collectors.toList()); + long size = consensusDelegate.getActiveWitnesses().size(); + int position = (int) (size * (1 - SOLIDIFIED_THRESHOLD * 1.0 / 100)); + long newSolidNum = numbers.get(position); + long oldSolidNum = consensusDelegate.getLatestSolidifiedBlockNum(); + if (newSolidNum < oldSolidNum) { + logger.warn("Update solid block number failed, new:{} < old:{}", newSolidNum, newSolidNum); + return; + } + consensusDelegate.saveLatestSolidifiedBlockNum(newSolidNum); + logger.info("Update solid block number to {}", newSolidNum); + } + + public static Sha256Hash getBlockHash(Block block) { + return Sha256Hash.of(block.getBlockHeader().getRawData().toByteArray()); + } +} diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposSlot.java b/consensus/src/main/java/org/tron/consensus/dpos/DposSlot.java new file mode 100644 index 00000000000..aef126191e1 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposSlot.java @@ -0,0 +1,65 @@ +package org.tron.consensus.dpos; + + +import static org.tron.consensus.base.Constant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.consensus.base.Constant.SINGLE_REPEAT; + +import com.google.protobuf.ByteString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.consensus.ConsensusDelegate; + +@Slf4j(topic = "consensus") +@Component +public class DposSlot { + + @Autowired + private ConsensusDelegate consensusDelegate; + + @Autowired + private DposService dposService; + + public long getAbSlot(long time) { + return (time - dposService.getGenesisBlockTime()) / BLOCK_PRODUCED_INTERVAL; + } + + public long getSlot(long time) { + long firstSlotTime = getTime(1); + if (time < firstSlotTime) { + return 0; + } + return (time - firstSlotTime) / BLOCK_PRODUCED_INTERVAL + 1; + } + + public long getTime(long slot) { + if (slot == 0) { + return System.currentTimeMillis(); + } + long interval = BLOCK_PRODUCED_INTERVAL; + if (consensusDelegate.getLatestBlockHeaderNumber() == 0) { + return dposService.getGenesisBlockTime() + slot * interval; + } + if (consensusDelegate.lastHeadBlockIsMaintenance()) { + slot += consensusDelegate.getMaintenanceSkipSlots(); + } + long time = consensusDelegate.getLatestBlockHeaderTimestamp(); + time = time - ((time - dposService.getGenesisBlockTime()) % interval); + return time + interval * slot; + } + + public ByteString getScheduledWitness(long slot) { + final long currentSlot = getAbSlot(consensusDelegate.getLatestBlockHeaderTimestamp()) + slot; + if (currentSlot < 0) { + throw new RuntimeException("current slot should be positive."); + } + int size = consensusDelegate.getActiveWitnesses().size(); + if (size <= 0) { + throw new RuntimeException("active witnesses is null."); + } + int witnessIndex = (int) currentSlot % (size * SINGLE_REPEAT); + witnessIndex /= SINGLE_REPEAT; + return consensusDelegate.getActiveWitnesses().get(witnessIndex); + } + +} diff --git a/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java new file mode 100644 index 00000000000..35df48cef2a --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/dpos/DposTask.java @@ -0,0 +1,141 @@ +package org.tron.consensus.dpos; + +import static org.tron.consensus.base.Constant.BLOCK_PRODUCED_INTERVAL; + +import com.google.protobuf.ByteString; +import java.util.Arrays; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.crypto.ECKey; +import org.tron.common.crypto.ECKey.ECDSASignature; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Sha256Hash; +import org.tron.consensus.ConsensusDelegate; +import org.tron.consensus.base.Param.Miner; +import org.tron.consensus.base.State; +import org.tron.core.capsule.AccountCapsule; +import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.BlockHeader; + +@Slf4j(topic = "consensus") +@Component +public class DposTask { + + @Autowired + private ConsensusDelegate consensusDelegate; + + @Autowired + private DposSlot dposSlot; + + @Autowired + private StateManager stateManager; + + @Setter + private DposService dposService; + + private Thread produceThread; + + private volatile boolean isRunning = true; + + public void init() { + + Runnable runnable = () -> { + while (isRunning) { + try { + if (dposService.isNeedSyncCheck()) { + Thread.sleep(1000); + dposService.setNeedSyncCheck(dposSlot.getTime(1) < System.currentTimeMillis()); + } else { + long time = + BLOCK_PRODUCED_INTERVAL - System.currentTimeMillis() % BLOCK_PRODUCED_INTERVAL; + Thread.sleep(time); + State state = produceBlock(); + if (!State.OK.equals(state)) { + logger.info("Produce block failed: {}", state); + } + } + } catch (Throwable throwable) { + logger.error("Produce block error.", throwable); + } + } + }; + produceThread = new Thread(runnable, "DPosMiner"); + produceThread.start(); + logger.info("DPoS service stared."); + } + + public void stop() { + isRunning = false; + produceThread.interrupt(); + logger.info("DPoS service stopped."); + } + + private State produceBlock() { + + State state = stateManager.getState(); + if (!State.OK.equals(state)) { + return state; + } + + synchronized (dposService.getBlockHandle().getLock()) { + + long slot = dposSlot.getSlot(System.currentTimeMillis() + 50); + if (slot == 0) { + return State.NOT_TIME_YET; + } + + final ByteString scheduledWitness = dposSlot.getScheduledWitness(slot); + state = stateManager.getState(scheduledWitness); + if (!State.OK.equals(state)) { + return state; + } + + Block block = dposService.getBlockHandle().produce(); + if (block == null) { + return State.PRODUCE_BLOCK_FAILED; + } + + Block sBlock = getSignedBlock(block, scheduledWitness, slot); + + stateManager.setCurrentBlock(sBlock); + + dposService.getBlockHandle().complete(sBlock); + + BlockHeader.raw raw = sBlock.getBlockHeader().getRawData(); + logger.info("Produce block successfully, num:{}, time:{}, witness:{}, hash:{} parentHash:{}", + raw.getNumber(), + new DateTime(raw.getTimestamp()), + raw.getWitnessAddress(), + DposService.getBlockHash(sBlock), + ByteArray.toHexString(raw.getParentHash().toByteArray())); + } + + return State.OK; + } + + public Block getSignedBlock(Block block, ByteString witness, long slot) { + BlockHeader.raw raw = block.getBlockHeader().getRawData().toBuilder() + .setParentHash(ByteString.copyFrom(consensusDelegate.getLatestBlockHeaderHash().getBytes())) + .setNumber(consensusDelegate.getLatestBlockHeaderNumber() + 1) + .setTimestamp(dposSlot.getTime(slot)) + .setWitnessAddress(witness) + .build(); + + ECKey ecKey = ECKey.fromPrivate(dposService.getMiners().get(witness).getPrivateKey()); + ECDSASignature signature = ecKey.sign(Sha256Hash.of(raw.toByteArray()).getBytes()); + ByteString sign = ByteString.copyFrom(signature.toByteArray()); + + BlockHeader blockHeader = block.getBlockHeader().toBuilder() + .setRawData(raw) + .setWitnessSignature(sign) + .build(); + + Block signedBlock = block.toBuilder().setBlockHeader(blockHeader).build(); + + return signedBlock; + } + +} diff --git a/consensus/src/main/java/org/tron/consensus/dpos/IncentiveManager.java b/consensus/src/main/java/org/tron/consensus/dpos/IncentiveManager.java new file mode 100644 index 00000000000..87f893a2dc8 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/dpos/IncentiveManager.java @@ -0,0 +1,47 @@ +package org.tron.consensus.dpos; + +import static org.tron.consensus.base.Constant.WITNESS_STANDBY_LENGTH; + +import com.google.protobuf.ByteString; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.consensus.ConsensusDelegate; +import org.tron.core.capsule.AccountCapsule; +import org.tron.protos.Protocol.Block; + +@Slf4j(topic = "consensus") +@Component +public class IncentiveManager { + + @Autowired + private ConsensusDelegate consensusDelegate; + + public void applyBlock(Block block) { + ByteString witness = block.getBlockHeader().getRawData().getWitnessAddress(); + AccountCapsule account = consensusDelegate.getAccountStore().getUnchecked(witness.toByteArray()); + account.setAllowance(account.getAllowance() + consensusDelegate.getWitnessPayPerBlock()); + consensusDelegate.getAccountStore().put(account.createDbKey(), account); + } + + public void reward(List witnesses) { + if (witnesses.size() > WITNESS_STANDBY_LENGTH) { + witnesses = witnesses.subList(0, WITNESS_STANDBY_LENGTH); + } + long voteSum = 0; + for (ByteString witness : witnesses) { + voteSum += consensusDelegate.getWitnesseByAddress(witness).getVoteCount(); + } + if (voteSum <= 0) { + return; + } + long totalPay = consensusDelegate.getWitnessStandbyAllowance(); + for (ByteString witness : witnesses) { + long pay = (long) (consensusDelegate.getWitnesseByAddress(witness).getVoteCount() * ((double) totalPay / voteSum)); + AccountCapsule accountCapsule = consensusDelegate.getAccountStore().get(witness.toByteArray()); + accountCapsule.setAllowance(accountCapsule.getAllowance() + pay); + consensusDelegate.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + } + } +} diff --git a/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java new file mode 100644 index 00000000000..b3b5bf0821d --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/dpos/MaintenanceManager.java @@ -0,0 +1,191 @@ +package org.tron.consensus.dpos; + + +import static org.tron.consensus.base.Constant.MAX_ACTIVE_WITNESS_NUM; + +import com.google.common.collect.Maps; +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.utils.StringUtil; +import org.tron.consensus.ConsensusDelegate; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.VotesCapsule; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.store.AccountStore; +import org.tron.core.store.VotesStore; +import org.tron.core.store.WitnessStore; +import org.tron.protos.Protocol.Block; + +@Slf4j(topic = "consensus") +@Component +public class MaintenanceManager { + + @Autowired + private ConsensusDelegate consensusDelegate; + + @Autowired + private IncentiveManager incentiveManager; + + @Setter + private DposService dposService; + + public void applyBlock(Block block) { + long blockNum = block.getBlockHeader().getRawData().getNumber(); + long blockTime = block.getBlockHeader().getRawData().getTimestamp(); + boolean flag = consensusDelegate.getNextMaintenanceTime() <= blockTime; + if (flag && blockNum != 1) { + doMaintenance(); + } + updateNextMaintenanceTime(block); + consensusDelegate.saveStateFlag(flag ? 1 : 0); + } + + private void updateNextMaintenanceTime(Block block) { + long blockNum = block.getBlockHeader().getRawData().getNumber(); + long blockTime = block.getBlockHeader().getRawData().getTimestamp(); + long maintenanceTimeInterval = consensusDelegate.getMaintenanceTimeInterval(); + long currentMaintenanceTime = consensusDelegate.getNextMaintenanceTime(); + long round = (blockTime - currentMaintenanceTime) / maintenanceTimeInterval; + long nextMaintenanceTime = currentMaintenanceTime + (round + 1) * maintenanceTimeInterval; + consensusDelegate.saveNextMaintenanceTime(nextMaintenanceTime); + logger.info("Update next maintenance time, blockNum:{}, blockTime:{}, currentMTime:{}, nextMTime:{}", + blockNum, + new DateTime(currentMaintenanceTime), + new DateTime(blockTime), + new DateTime(nextMaintenanceTime)); + } + + private void doMaintenance() { + WitnessStore witnessStore = consensusDelegate.getWitnessStore(); + VotesStore votesStore = consensusDelegate.getVotesStore(); + AccountStore accountStore = consensusDelegate.getAccountStore(); + + tryRemoveThePowerOfTheGr(); + + Map countWitness = countVote(votesStore); + if (countWitness.isEmpty()) { + logger.warn("No vote, no change to witness."); + return; + } + + List currentWits = consensusDelegate.getActiveWitnesses(); + + List newWitnessAddressList = new ArrayList<>(); + witnessStore.getAllWitnesses() + .forEach(witnessCapsule -> newWitnessAddressList.add(witnessCapsule.getAddress())); + + countWitness.forEach((address, voteCount) -> { + WitnessCapsule witnessCapsule = witnessStore.get(StringUtil.createDbKey(address)); + if (witnessCapsule == null) { + logger.warn("Witness capsule is null. address is {}", + StringUtil.createReadableString(address)); + return; + } + AccountCapsule account = accountStore.get(StringUtil.createDbKey(address)); + if (account == null) { + logger.warn("Witness account is null. address is {}", + StringUtil.createReadableString(address)); + return; + } + witnessCapsule.setVoteCount(witnessCapsule.getVoteCount() + voteCount); + witnessStore.put(witnessCapsule.createDbKey(), witnessCapsule); + logger.info("address is {} ,countVote is {}", witnessCapsule.createReadableString(), + witnessCapsule.getVoteCount()); + }); + + sortWitness(newWitnessAddressList); + + if (newWitnessAddressList.size() > MAX_ACTIVE_WITNESS_NUM) { + consensusDelegate + .saveActiveWitnesses(newWitnessAddressList.subList(0, MAX_ACTIVE_WITNESS_NUM)); + } else { + consensusDelegate.saveActiveWitnesses(newWitnessAddressList); + } + + incentiveManager.reward(newWitnessAddressList); + + List newWits = consensusDelegate.getActiveWitnesses(); + if (!CollectionUtils.isEqualCollection(currentWits, newWits)) { + currentWits.forEach(address -> { + WitnessCapsule witnessCapsule = consensusDelegate.getWitnesseByAddress(address); + witnessCapsule.setIsJobs(false); + witnessStore.put(witnessCapsule.createDbKey(), witnessCapsule); + }); + newWits.forEach(address -> { + WitnessCapsule witnessCapsule = consensusDelegate.getWitnesseByAddress(address); + witnessCapsule.setIsJobs(true); + witnessStore.put(witnessCapsule.createDbKey(), witnessCapsule); + }); + } + + logger.info("Update witness success. \nbefore: {} \nafter: {}", + StringUtil.getAddressStringList(currentWits), + StringUtil.getAddressStringList(newWits)); + } + + private Map countVote(VotesStore votesStore) { + final Map countWitness = Maps.newHashMap(); + Iterator> dbIterator = votesStore.iterator(); + long sizeCount = 0; + while (dbIterator.hasNext()) { + Entry next = dbIterator.next(); + VotesCapsule votes = next.getValue(); + votes.getOldVotes().forEach(vote -> { + //TODO validate witness //active_witness + ByteString voteAddress = vote.getVoteAddress(); + long voteCount = vote.getVoteCount(); + if (countWitness.containsKey(voteAddress)) { + countWitness.put(voteAddress, countWitness.get(voteAddress) - voteCount); + } else { + countWitness.put(voteAddress, -voteCount); + } + }); + votes.getNewVotes().forEach(vote -> { + //TODO validate witness //active_witness + ByteString voteAddress = vote.getVoteAddress(); + long voteCount = vote.getVoteCount(); + if (countWitness.containsKey(voteAddress)) { + countWitness.put(voteAddress, countWitness.get(voteAddress) + voteCount); + } else { + countWitness.put(voteAddress, voteCount); + } + }); + sizeCount++; + votesStore.delete(next.getKey()); + } + logger.info("there is {} new votes in this epoch", sizeCount); + return countWitness; + } + + private void tryRemoveThePowerOfTheGr() { + if (consensusDelegate.getRemoveThePowerOfTheGr() != 1) { + return; + } + WitnessStore witnessStore = consensusDelegate.getWitnessStore(); + dposService.getGenesisBlock().getWitnesses().forEach(witness -> { + WitnessCapsule witnessCapsule = witnessStore.get(witness.getAddress()); + witnessCapsule.setVoteCount(witnessCapsule.getVoteCount() - witness.getVoteCount()); + witnessStore.put(witnessCapsule.createDbKey(), witnessCapsule); + }); + consensusDelegate.saveRemoveThePowerOfTheGr(-1); + } + + private void sortWitness(List list) { + list.sort(Comparator.comparingLong((ByteString b) -> + consensusDelegate.getWitnesseByAddress(b).getVoteCount()) + .reversed() + .thenComparing(Comparator.comparingInt(ByteString::hashCode).reversed())); + } + +} diff --git a/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java b/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java new file mode 100644 index 00000000000..f0765c28a16 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/dpos/StateManager.java @@ -0,0 +1,123 @@ +package org.tron.consensus.dpos; + + +import static org.tron.consensus.base.Constant.BLOCK_PRODUCED_INTERVAL; +import static org.tron.consensus.base.Constant.MAX_ACTIVE_WITNESS_NUM; + +import com.google.protobuf.ByteString; +import java.util.Arrays; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.consensus.ConsensusDelegate; +import org.tron.consensus.base.Param.Miner; +import org.tron.consensus.base.State; +import org.tron.core.capsule.AccountCapsule; +import org.tron.protos.Protocol.Block; + +@Slf4j(topic = "consensus") +@Component +public class StateManager { + + @Autowired + private ConsensusDelegate consensusDelegate; + + @Setter + private DposService dposService; + + @Setter + private volatile Block currentBlock; + + private AtomicInteger dupBlockCount = new AtomicInteger(0); + + private AtomicLong dupBlockTime = new AtomicLong(0); + + private long blockCycle = BLOCK_PRODUCED_INTERVAL * MAX_ACTIVE_WITNESS_NUM; + + + public State getState() { + + if (System.currentTimeMillis() < consensusDelegate.getLatestBlockHeaderTimestamp()) { + return State.CLOCK_ERROR; + } + + State status = dposService.getBlockHandle().getState(); + if (!State.OK.equals(status)) { + return status; + } + + if (dupWitnessCheck()) { + return State.DUP_WITNESS; + } + + int participation = consensusDelegate.calculateFilledSlotsCount(); + int minParticipationRate = dposService.getMinParticipationRate(); + if (participation < minParticipationRate) { + logger.warn("Participation:{} < minParticipationRate:{}", participation, minParticipationRate); + return State.LOW_PARTICIPATION; + } + + return State.OK; + } + + public State getState(ByteString scheduledWitness) { + if (!dposService.getMiners().containsKey(scheduledWitness)) { + return State.NOT_MY_TURN; + } + if (consensusDelegate.getAllowMultiSign() == 1) { + Miner miner = dposService.getMiners().get(scheduledWitness); + byte[] privateKeyAddress = miner.getPrivateKeyAddress().toByteArray(); + AccountCapsule account = consensusDelegate.getAccountStore().get(scheduledWitness.toByteArray()); + if (!Arrays.equals(privateKeyAddress, account.getWitnessPermissionAddress())) { + return State.PERMISSION_ERROR; + } + } + return State.OK; + } + + public void applyBlock(Block block) { + if (block.equals(currentBlock)) { + return; + } + + if (dposService.isNeedSyncCheck()) { + return; + } + + long blockTime = block.getBlockHeader().getRawData().getTimestamp(); + if (System.currentTimeMillis() - blockTime > BLOCK_PRODUCED_INTERVAL) { + return; + } + + ByteString witness = block.getBlockHeader().getRawData().getWitnessAddress(); + if (!dposService.getMiners().containsKey(witness)) { + return; + } + + if (dupBlockCount.get() == 0) { + dupBlockCount.set(new Random().nextInt(10)); + } else { + dupBlockCount.set(10); + } + + dupBlockTime.set(System.currentTimeMillis()); + + logger.warn("Dup block produced: {}", block); + } + + private boolean dupWitnessCheck() { + if (dupBlockCount.get() == 0) { + return false; + } + if (System.currentTimeMillis() - dupBlockTime.get() > dupBlockCount.get() * blockCycle) { + dupBlockCount.set(0); + return false; + } + return true; + } + +} diff --git a/consensus/src/main/java/org/tron/consensus/dpos/StatisticManager.java b/consensus/src/main/java/org/tron/consensus/dpos/StatisticManager.java new file mode 100644 index 00000000000..0ed7fd87c36 --- /dev/null +++ b/consensus/src/main/java/org/tron/consensus/dpos/StatisticManager.java @@ -0,0 +1,58 @@ +package org.tron.consensus.dpos; + +import static org.tron.consensus.base.Constant.BLOCK_FILLED_SLOTS_NUMBER; + +import com.google.protobuf.ByteString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.consensus.ConsensusDelegate; +import org.tron.core.capsule.WitnessCapsule; +import org.tron.protos.Protocol.Block; + +@Slf4j(topic = "consensus") +@Component +public class StatisticManager { + + @Autowired + private ConsensusDelegate consensusDelegate; + + @Autowired + private DposSlot dposSlot; + + public void applyBlock(Block block) { + long blockNum = block.getBlockHeader().getRawData().getNumber(); + long blockTime = block.getBlockHeader().getRawData().getTimestamp(); + ByteString witness = block.getBlockHeader().getRawData().getWitnessAddress(); + WitnessCapsule witnessCapsule = consensusDelegate.getWitnessStore().getUnchecked(witness.toByteArray()); + witnessCapsule.setTotalProduced(witnessCapsule.getTotalProduced() + 1); + witnessCapsule.setLatestBlockNum(blockNum); + witnessCapsule.setLatestSlotNum(dposSlot.getAbSlot(blockTime)); + consensusDelegate.getWitnessStore().put(witnessCapsule.getAddress().toByteArray(), witnessCapsule); + + long slot = 1; + if (blockTime != 1) { + slot = dposSlot.getSlot(blockTime); + } + for (int i = 1; i < slot; ++i) { + ByteString scheduledWitness = dposSlot.getScheduledWitness(i); + if (!scheduledWitness.equals(witness)) { + WitnessCapsule w = consensusDelegate.getWitnessStore().getUnchecked(scheduledWitness.toByteArray()); + w.setTotalMissed(w.getTotalMissed() + 1); + consensusDelegate.getWitnessStore().put(scheduledWitness.toByteArray(), w); + logger.info("{} miss a block. totalMissed = {}", w.createReadableString(), w.getTotalMissed()); + } + applyBlock(false); + } + applyBlock(true); + } + + public void applyBlock(boolean fillBlock) { + int[] blockFilledSlots = consensusDelegate.getBlockFilledSlots(); + int blockFilledSlotsIndex = consensusDelegate.getBlockFilledSlotsIndex(); + blockFilledSlots[blockFilledSlotsIndex] = fillBlock ? 1 : 0; + consensusDelegate.saveBlockFilledSlotsIndex((blockFilledSlotsIndex + 1) % BLOCK_FILLED_SLOTS_NUMBER); + consensusDelegate.saveBlockFilledSlots(blockFilledSlots); + } + +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/common/utils/SlidingWindowCounter.java b/framework/src/main/java/org/tron/common/utils/SlidingWindowCounter.java index eb53a847056..b00b3340235 100644 --- a/framework/src/main/java/org/tron/common/utils/SlidingWindowCounter.java +++ b/framework/src/main/java/org/tron/common/utils/SlidingWindowCounter.java @@ -3,41 +3,6 @@ import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; -/** - * Created by olivier on 2018/06/01 - */ -class SlotBaseCounter { - - private int slotSize; - private AtomicInteger[] slotCounter; - - public SlotBaseCounter(int slotSize) { - slotSize = slotSize < 1 ? 1 : slotSize; - this.slotSize = slotSize; - this.slotCounter = new AtomicInteger[slotSize]; - for (int i = 0; i < this.slotSize; i++) { - slotCounter[i] = new AtomicInteger(0); - } - } - - public void increaseSlot(int slotSize) { - slotCounter[slotSize].incrementAndGet(); - } - - public void wipeSlot(int slotSize) { - slotCounter[slotSize].set(0); - } - - public int totalCount() { - return Arrays.stream(slotCounter).mapToInt(slotCounter -> slotCounter.get()).sum(); - } - - @Override - public String toString() { - return Arrays.toString(slotCounter); - } -} - /** * Created by olivier on 2018/06/01 */ diff --git a/framework/src/main/java/org/tron/common/utils/SlotBaseCounter.java b/framework/src/main/java/org/tron/common/utils/SlotBaseCounter.java new file mode 100644 index 00000000000..85d3b4bf655 --- /dev/null +++ b/framework/src/main/java/org/tron/common/utils/SlotBaseCounter.java @@ -0,0 +1,39 @@ +package org.tron.common.utils; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by olivier on 2018/06/01 + */ +class SlotBaseCounter { + + private int slotSize; + private AtomicInteger[] slotCounter; + + public SlotBaseCounter(int slotSize) { + slotSize = slotSize < 1 ? 1 : slotSize; + this.slotSize = slotSize; + this.slotCounter = new AtomicInteger[slotSize]; + for (int i = 0; i < this.slotSize; i++) { + slotCounter[i] = new AtomicInteger(0); + } + } + + public void increaseSlot(int slotSize) { + slotCounter[slotSize].incrementAndGet(); + } + + public void wipeSlot(int slotSize) { + slotCounter[slotSize].set(0); + } + + public int totalCount() { + return Arrays.stream(slotCounter).mapToInt(slotCounter -> slotCounter.get()).sum(); + } + + @Override + public String toString() { + return Arrays.toString(slotCounter); + } +} diff --git a/framework/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/framework/src/main/java/org/tron/core/capsule/TransactionCapsule.java index 63755cce3e8..6f7e600ca48 100755 --- a/framework/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/framework/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -63,7 +63,6 @@ import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.BadItemException; -import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.P2pException; import org.tron.core.exception.PermissionException; import org.tron.core.exception.SignatureFormatException; @@ -86,7 +85,6 @@ import org.tron.protos.Contract.ProposalDeleteContract; import org.tron.protos.Contract.SetAccountIdContract; import org.tron.protos.Contract.ShieldedTransferContract; -import org.tron.protos.Contract.SpendDescription; import org.tron.protos.Contract.TransferAssetContract; import org.tron.protos.Contract.TransferContract; import org.tron.protos.Contract.TriggerSmartContract; diff --git a/framework/src/main/java/org/tron/core/services/RpcApiService.java b/framework/src/main/java/org/tron/core/services/RpcApiService.java index d49e6bb70a8..33466c1f67a 100755 --- a/framework/src/main/java/org/tron/core/services/RpcApiService.java +++ b/framework/src/main/java/org/tron/core/services/RpcApiService.java @@ -24,7 +24,6 @@ import org.tron.api.DatabaseGrpc.DatabaseImplBase; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.AccountNetMessage; -import org.tron.api.GrpcAPI.AccountPaginated; import org.tron.api.GrpcAPI.AccountResourceMessage; import org.tron.api.GrpcAPI.Address; import org.tron.api.GrpcAPI.AddressPrKeyPairMessage; @@ -50,7 +49,6 @@ import org.tron.api.GrpcAPI.ExpandedSpendingKeyMessage; import org.tron.api.GrpcAPI.IncomingViewingKeyDiversifierMessage; import org.tron.api.GrpcAPI.IncomingViewingKeyMessage; -import org.tron.api.GrpcAPI.IvkDecryptAndMarkParameters; import org.tron.api.GrpcAPI.Node; import org.tron.api.GrpcAPI.NodeList; import org.tron.api.GrpcAPI.NoteParameters; diff --git a/framework/src/test/java/org/tron/core/db/ManagerTest.java b/framework/src/test/java/org/tron/core/db/ManagerTest.java index edcc9da7d88..f4299ca3b1a 100755 --- a/framework/src/test/java/org/tron/core/db/ManagerTest.java +++ b/framework/src/test/java/org/tron/core/db/ManagerTest.java @@ -48,9 +48,6 @@ import org.tron.core.witness.WitnessController; import org.tron.protos.Contract.TransferContract; import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.BlockHeader; -import org.tron.protos.Protocol.BlockHeader.raw; import org.tron.protos.Protocol.Transaction.Contract.ContractType; @Slf4j diff --git a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java index 33d3f24c335..138d2311a10 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionStoreTest.java @@ -2,7 +2,6 @@ import com.google.protobuf.ByteString; import java.io.File; -import java.util.List; import java.util.Random; import org.junit.AfterClass; import org.junit.Assert; diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index 2de147f0dee..d7d9f2c232b 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -53,7 +53,6 @@ import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; import org.tron.core.config.DefaultConfig; -import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.args.Args; import org.tron.core.db.Manager; import org.tron.core.exception.AccountResourceInsufficientException; diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java index 315e0123543..655dd6d82c1 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount001.java @@ -1,11 +1,9 @@ package stest.tron.wallet.account; import com.google.protobuf.ByteString; -import com.googlecode.cqengine.query.simple.In; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.math.BigInteger; -import java.util.Random; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java index 5c27bb462ac..13dbd9b3db1 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java @@ -9,8 +9,6 @@ import java.util.Random; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.spongycastle.util.encoders.Hex; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -30,7 +28,6 @@ import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; import stest.tron.wallet.common.client.utils.TransactionUtils; diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java index b0e6724cf48..502809d1427 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount004.java @@ -28,7 +28,6 @@ import org.tron.protos.Protocol.Transaction; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; import stest.tron.wallet.common.client.utils.TransactionUtils; diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java index 39c738c59ba..92801a7c207 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount005.java @@ -26,7 +26,6 @@ import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; import stest.tron.wallet.common.client.utils.TransactionUtils; diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java index d24ddee2c18..7276c362c38 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount006.java @@ -1,7 +1,6 @@ package stest.tron.wallet.account; import com.google.protobuf.ByteString; -import com.googlecode.cqengine.query.simple.In; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.Optional; @@ -22,7 +21,6 @@ import org.tron.protos.Protocol.Account; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; @Slf4j diff --git a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java index 33a43ae1140..bb96ea02e74 100644 --- a/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java +++ b/framework/src/test/java/stest/tron/wallet/account/WalletTestAccount007.java @@ -1,10 +1,7 @@ package stest.tron.wallet.account; -import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.testng.Assert; @@ -12,16 +9,13 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.AccountNetMessage; import org.tron.api.WalletGrpc; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.Wallet; -import org.tron.protos.Contract; import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Transaction; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java index be673c111c6..d56a3d343c2 100644 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java +++ b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock003.java @@ -23,7 +23,6 @@ import org.tron.protos.Protocol.Transaction; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.TransactionUtils; @Slf4j diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java index 97d12ac7e73..bd3480c488e 100644 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java +++ b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock004.java @@ -4,7 +4,6 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.math.BigInteger; -import java.util.ArrayList; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -24,7 +23,6 @@ import org.tron.protos.Protocol.Block; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; //import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion; diff --git a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java index f95ee2425dc..e963a81abb9 100644 --- a/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java +++ b/framework/src/test/java/stest/tron/wallet/block/WalletTestBlock005.java @@ -23,7 +23,6 @@ import org.tron.protos.Protocol.Block; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; //import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion; diff --git a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java index 414441ac1b3..b7ce4b58052 100644 --- a/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java +++ b/framework/src/test/java/stest/tron/wallet/committee/WalletTestCommittee001.java @@ -1,32 +1,22 @@ package stest.tron.wallet.committee; -import com.google.protobuf.ByteString; -import com.sun.media.jfxmedia.logging.Logger; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.spongycastle.util.encoders.Hex; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import org.tron.api.GrpcAPI.EmptyMessage; -import org.tron.api.GrpcAPI.NumberMessage; import org.tron.api.GrpcAPI.PaginatedMessage; import org.tron.api.GrpcAPI.ProposalList; import org.tron.api.WalletGrpc; import org.tron.api.WalletSolidityGrpc; -import org.tron.common.crypto.ECKey; -import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethedForMutiSign.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethedForMutiSign.java index 8a930922df5..4cd845d980f 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethedForMutiSign.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/PublicMethedForMutiSign.java @@ -42,7 +42,6 @@ import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Commons; import org.tron.common.utils.Hash; -import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.core.exception.CancelException; import org.tron.core.zen.address.ExpandedSpendingKey; diff --git a/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java b/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java index c927682e5b9..c045fa12b4b 100644 --- a/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java +++ b/framework/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java @@ -21,7 +21,6 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tron.api.GrpcAPI; import org.tron.common.crypto.ECKey; import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.common.utils.Sha256Hash; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction001.java index dd960b90ab8..f59c7cfe149 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction001.java @@ -1,40 +1,26 @@ package stest.tron.wallet.dailybuild.delaytransaction; -import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.math.BigInteger; -import java.util.Objects; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.spongycastle.util.encoders.Hex; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.BytesMessage; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; import org.tron.api.WalletGrpc; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.Wallet; -import org.tron.protos.Contract; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; //import org.tron.protos.Protocol.DeferredTransaction; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; -import stest.tron.wallet.common.client.utils.TransactionUtils; @Slf4j public class DelayTransaction001 { diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction002.java index 00195a0c031..e53861f5008 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction002.java @@ -20,9 +20,7 @@ import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; @Slf4j public class DelayTransaction002 { diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction003.java b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction003.java index 8211095360e..8dc75699e82 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction003.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction003.java @@ -23,7 +23,6 @@ import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; @Slf4j public class DelayTransaction003 { diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction004.java index 5134a548d9a..dd4fdb7210e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction004.java @@ -3,7 +3,6 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.testng.Assert; @@ -19,8 +18,6 @@ import org.tron.protos.Protocol.Account; //import org.tron.protos.Protocol.DeferredTransaction; import org.tron.protos.Protocol.SmartContract; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction007.java b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction007.java index a045d8f106a..980891fe4f7 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction007.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction007.java @@ -15,7 +15,6 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.SmartContract; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction010.java index 93bd0094b45..837ec3baedc 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction010.java @@ -2,7 +2,6 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.testng.Assert; @@ -16,13 +15,9 @@ import org.tron.common.utils.Utils; import org.tron.core.Wallet; //import org.tron.protos.Protocol.DeferredTransaction; -import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; @Slf4j public class DelayTransaction010 { diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction011.java b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction011.java index 2bcbefc9ece..01dec4de37e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction011.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction011.java @@ -2,7 +2,6 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.testng.Assert; @@ -19,7 +18,6 @@ import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; @Slf4j public class DelayTransaction011 { diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java index 1ed4428fc13..c11f00b5121 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestEasyAccount001.java @@ -10,7 +10,6 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.Commons; import org.tron.common.utils.Utils; -import org.tron.core.Wallet; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.utils.HttpMethed; import stest.tron.wallet.common.client.utils.PublicMethed; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java index a8a4fcfe35b..8b2f84cbe72 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java @@ -15,7 +15,6 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java index 1b6760f3669..c9fe0f31d77 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test004.java @@ -15,7 +15,6 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.AccountResourceMessage; import org.tron.api.WalletGrpc; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java index 65259f1bc09..416f6f3e987 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test015.java @@ -1,6 +1,5 @@ package stest.tron.wallet.dailybuild.tvmnewcommand.create2; -import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.HashMap; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java index 99f313b910d..1977e93c09e 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test023.java @@ -1,12 +1,9 @@ package stest.tron.wallet.dailybuild.tvmnewcommand.create2; -import static org.hamcrest.core.StringContains.containsString; - import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.HashMap; -import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -25,7 +22,6 @@ import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java index e63db5de9ef..ed58ed17dba 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/create2/Create2Test025.java @@ -1,8 +1,5 @@ package stest.tron.wallet.dailybuild.tvmnewcommand.create2; -import static org.hamcrest.core.StringContains.containsString; - -import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.HashMap; @@ -22,14 +19,12 @@ import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.protos.Protocol.SmartContract; -import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.WalletClient; import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; -import zmq.socket.pubsub.Pub; @Slf4j public class Create2Test025 { diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java index eb3c733a7f1..08280ed0b4a 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest002.java @@ -9,7 +9,6 @@ import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; -import org.junit.runners.AllTests; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java index 15edc1d6140..cce3cc2b161 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest005.java @@ -26,7 +26,6 @@ import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; @Slf4j diff --git a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java index dc32ba60c46..446ccd6bfdd 100644 --- a/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java +++ b/framework/src/test/java/stest/tron/wallet/dailybuild/tvmnewcommand/extCodeHash/ExtCodeHashTest010.java @@ -1,6 +1,5 @@ package stest.tron.wallet.dailybuild.tvmnewcommand.extCodeHash; -import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.HashMap; @@ -23,7 +22,6 @@ import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.WalletClient; import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; diff --git a/framework/src/test/java/stest/tron/wallet/exchangeandtoken/WalletExchange001.java b/framework/src/test/java/stest/tron/wallet/exchangeandtoken/WalletExchange001.java index 5bdb6689b47..2328fe4e781 100644 --- a/framework/src/test/java/stest/tron/wallet/exchangeandtoken/WalletExchange001.java +++ b/framework/src/test/java/stest/tron/wallet/exchangeandtoken/WalletExchange001.java @@ -11,7 +11,6 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.ExchangeList; import org.tron.api.GrpcAPI.PaginatedMessage; import org.tron.api.WalletGrpc; diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java b/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java index 84b42f8d9c5..a6b05ca496e 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/AttackSendcoin.java @@ -7,19 +7,15 @@ import java.math.BigInteger; import java.util.Random; import lombok.extern.slf4j.Slf4j; -import org.junit.Assert; -import org.slf4j.Logger; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.NumberMessage; import org.tron.api.GrpcAPI.Return; import org.tron.api.WalletGrpc; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.protos.Contract; import org.tron.protos.Contract.TransferContract; diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java b/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java index 6a81878535c..0c158664c6b 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/Fuzzytest.java @@ -4,9 +4,6 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.math.BigInteger; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -14,10 +11,7 @@ import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import org.tron.api.GrpcAPI; -import org.tron.api.GrpcAPI.AccountPaginated; import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.PaginatedMessage; import org.tron.api.WalletExtensionGrpc; import org.tron.api.WalletGrpc; import org.tron.api.WalletSolidityGrpc; @@ -28,8 +22,6 @@ import org.tron.core.db.Manager; import org.tron.protos.Contract; import org.tron.protos.Protocol; -import org.tron.protos.Protocol.Account; -import org.tron.protos.Protocol.Block; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java b/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java index 05a45dcf08d..f256372160d 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/ParticipateAssetIssue.java @@ -1,13 +1,11 @@ package stest.tron.wallet.fulltest; import com.google.protobuf.ByteString; -import com.google.protobuf.InvalidProtocolBufferException; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.math.BigInteger; import java.util.HashMap; import java.util.Map; -import java.util.Random; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -22,7 +20,6 @@ import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.protos.Contract; -import org.tron.protos.Contract.TransferContract; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; diff --git a/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java b/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java index 3791021ba6a..fd829700729 100644 --- a/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java +++ b/framework/src/test/java/stest/tron/wallet/fulltest/TronDice.java @@ -17,12 +17,10 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.Wallet; -import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.SmartContract; import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; @Slf4j diff --git a/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java b/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java index 69f53a745b7..ed58c6977cc 100644 --- a/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java +++ b/framework/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java @@ -20,9 +20,7 @@ import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; -import stest.tron.wallet.common.client.utils.Sha256Hash; @Slf4j public class DelayTransactionStress { diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java index 53cd1080f1a..c55e45f92a7 100644 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java +++ b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer001.java @@ -28,7 +28,6 @@ import org.tron.protos.Protocol.Transaction; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; import stest.tron.wallet.common.client.utils.TransactionUtils; diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java index a440e05c6b3..b2b8ea80a68 100644 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java +++ b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer003.java @@ -12,8 +12,6 @@ import org.spongycastle.util.encoders.Hex; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.BytesMessage; @@ -33,7 +31,6 @@ import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; import stest.tron.wallet.common.client.utils.Sha256Hash; import stest.tron.wallet.common.client.utils.TransactionUtils; diff --git a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java index fe406dfd4dd..477b5bc51c1 100644 --- a/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java +++ b/framework/src/test/java/stest/tron/wallet/transfer/WalletTestTransfer004.java @@ -3,33 +3,24 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.spongycastle.util.encoders.Hex; -import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Test; -import org.tron.api.GrpcAPI; import org.tron.api.GrpcAPI.NumberMessage; -import org.tron.api.GrpcAPI.Return; -import org.tron.api.GrpcAPI.TimePaginatedMessage; -import org.tron.api.GrpcAPI.TransactionList; import org.tron.api.WalletExtensionGrpc; import org.tron.api.WalletGrpc; import org.tron.api.WalletSolidityGrpc; import org.tron.common.crypto.ECKey; import org.tron.core.Wallet; -import org.tron.protos.Contract; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; import stest.tron.wallet.common.client.utils.TransactionUtils; diff --git a/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java b/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java index bd69b9d1398..a96f0c50f7a 100644 --- a/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java +++ b/framework/src/test/java/stest/tron/wallet/updateCompatibility/MutisignOperationerGodicTest.java @@ -14,7 +14,6 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import org.tron.api.GrpcAPI.DecryptNotes; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.ExchangeList; import org.tron.api.GrpcAPI.Note; diff --git a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java b/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java index 28d5cd313ae..6a845c75bdc 100644 --- a/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java +++ b/framework/src/test/java/stest/tron/wallet/witness/WalletTestWitness002.java @@ -29,7 +29,6 @@ import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.WalletClient; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.TransactionUtils; //import stest.tron.wallet.common.client.WitnessComparator; diff --git a/settings.gradle b/settings.gradle index 50ca42f3c3a..5b041ebfa83 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,4 +3,4 @@ include 'framework' include 'chainbase' include 'protocol' include 'actuator' - +include 'consensus'