Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -657,20 +657,20 @@ public boolean validatePubSignature(AccountStore accountStore,
DynamicPropertiesStore dynamicPropertiesStore)
throws ValidateSignatureException {
if (!isVerified) {
int legacyCount = this.transaction.getSignatureCount();
int signatureCount = this.transaction.getSignatureCount();
int pqCount = this.transaction.getPqAuthSigCount();

if (pqCount > 0 && !dynamicPropertiesStore.isAnyPqSchemeAllowed()) {
if (dynamicPropertiesStore.isAnyPqSchemeAllowed()) {
signatureCount += pqCount;
} else if (pqCount > 0) {
throw new ValidateSignatureException(
"pq_auth_sig not allowed: no post-quantum scheme is activated");
}
if (legacyCount == 0 && pqCount == 0) {
throw new ValidateSignatureException("miss sig");
}
if (this.transaction.getRawData().getContractCount() <= 0) {
throw new ValidateSignatureException("miss contract");

if (signatureCount == 0 || this.transaction.getRawData().getContractCount() <= 0) {
throw new ValidateSignatureException("miss sig or contract");
}
if (legacyCount + pqCount > dynamicPropertiesStore.getTotalSignNum()) {
if (signatureCount > dynamicPropertiesStore.getTotalSignNum()) {
throw new ValidateSignatureException("too many signatures");
}

Expand Down Expand Up @@ -800,7 +800,7 @@ public boolean validateSignature(AccountStore accountStore,
validatePubSignature(accountStore, dynamicPropertiesStore);
} else { //transfer from shielded address
if (this.transaction.getSignatureCount() > 0
|| this.transaction.getPqAuthSigCount() > 0) {
|| (this.transaction.getPqAuthSigCount() > 0)) {
throw new ValidateSignatureException("there should be no signatures signed by "
+ "transparent address when transfer from shielded address");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.tron.core.exception.ContractValidateException;
import org.tron.core.exception.TooBigTransactionException;
import org.tron.core.exception.TooBigTransactionResultException;
import org.tron.protos.Protocol.PQAuthSig;
import org.tron.protos.Protocol.Transaction.Contract;
import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract;
import org.tron.protos.contract.BalanceContract.TransferContract;
Expand Down Expand Up @@ -141,11 +142,12 @@ public void consume(TransactionCapsule trx, TransactionTrace trace)
long maxCreateAccountTxSize = dynamicPropertiesStore.getMaxCreateAccountTxSize();
int signatureCount = trx.getInstance().getSignatureCount();
long sigOverhead = signatureCount * PER_SIGN_LENGTH;

// PQAuthSig bytes are subtracted as signature overhead regardless of open or not
if (trx.getInstance().getPqAuthSigCount() > 0) {
long pqAuthSigBytes = 0L;
for (org.tron.protos.Protocol.PQAuthSig aw
: trx.getInstance().getPqAuthSigList()) {
pqAuthSigBytes += aw.getSerializedSize();
for (PQAuthSig pqAuthSig : trx.getInstance().getPqAuthSigList()) {
pqAuthSigBytes += pqAuthSig.getSerializedSize();
}
sigOverhead += pqAuthSigBytes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.tron.common.crypto.pqc.PQSchemeRegistry;
import org.tron.common.parameter.CommonParameter;
import org.tron.common.utils.ByteArray;
import org.tron.common.utils.Sha256Hash;
Expand Down Expand Up @@ -3101,9 +3102,20 @@ public boolean allowFnDsa512() {
return getAllowFnDsa512() == 1L;
}

/** Returns true iff at least one post-quantum signature scheme is currently activated. */
/**
* Returns true iff at least one post-quantum signature scheme is currently
* activated. Driven by {@link PQSchemeRegistry#registeredSchemes()} so that
* adding a new scheme to the registry (and its corresponding case in
* {@link #isPqSchemeAllowed}) automatically propagates here — no manual edit
* needed.
*/
public boolean isAnyPqSchemeAllowed() {
return allowFnDsa512();
for (PQScheme scheme : PQSchemeRegistry.registeredSchemes()) {
if (isPqSchemeAllowed(scheme)) {
return true;
}
}
return false;
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是否允许某个PQ 方案不应该是看提案是否开启了么

}

/**
Expand Down
13 changes: 5 additions & 8 deletions consensus/src/main/java/org/tron/consensus/base/Param.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,15 @@ public class Miner {

private byte[] pqPublicKey;

@Getter
@Setter
private PQScheme pqScheme;

/**
* Explicit signing-family marker so the block producer doesn't have to infer
* key type from {@code privateKey == null}. Defaults to {@link MinerType#ECDSA};
* PQ-only miners must call {@link #setType(MinerType)} with {@link MinerType#PQ}.
* Post-quantum signature scheme for this miner. When unset (null), the
* miner signs blocks with the legacy ECDSA path using {@link #privateKey};
* when set (e.g. {@code FN_DSA_512}), the PQ path is used with
* {@link #pqPrivateKey} / {@link #pqPublicKey}.
*/
@Getter
@Setter
private MinerType type = MinerType.ECDSA;
private PQScheme pqScheme;

public Miner(byte[] privateKey, ByteString privateKeyAddress, ByteString witnessAddress) {
this.privateKey = privateKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;
import org.tron.common.crypto.Hash;
import org.tron.protos.Protocol.PQScheme;

Expand Down Expand Up @@ -124,6 +125,17 @@ public static boolean contains(PQScheme scheme) {
return resolved != null && SCHEMES.containsKey(resolved);
}

/**
* Returns the set of post-quantum schemes that are registered (i.e. have an
* active {@link SignatureOps} entry). Lets governance / config layers
* enumerate "all PQ schemes" without hard-coding the list — adding a new
* scheme to the registry then auto-propagates to any caller iterating over
* this set.
*/
public static Set<PQScheme> registeredSchemes() {
return SCHEMES.keySet();
}

public static int getPrivateKeyLength(PQScheme scheme) {
return require(scheme).privateKeyLength;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ public void start() {
miner.setPQPrivateKey(sk);
miner.setPQPublicKey(pk);
miner.setPqScheme(scheme);
miner.setType(Param.MinerType.PQ);
miners.add(miner);
logger.info("Add {} witness (from configured keypair): {}, size: {}",
scheme, Hex.toHexString(pqAddress), miners.size());
Expand Down Expand Up @@ -145,7 +144,6 @@ private Miner buildPQOnlyMinerFromKeypair(Param param, PqKeypair pqKeypair) {
miner.setPQPrivateKey(sk);
miner.setPQPublicKey(pk);
miner.setPqScheme(scheme);
miner.setType(Param.MinerType.PQ);
logger.info("Add {} witness (from configured keypair): {}",
scheme, Hex.toHexString(witnessAddress));
return miner;
Expand Down
64 changes: 18 additions & 46 deletions framework/src/main/java/org/tron/core/db/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
import org.tron.common.utils.StringUtil;
import org.tron.common.zksnark.MerkleContainer;
import org.tron.consensus.Consensus;
import org.tron.consensus.base.Param;
import org.tron.consensus.base.Param.Miner;
import org.tron.core.ChainBaseManager;
import org.tron.core.Constant;
Expand Down Expand Up @@ -1746,7 +1747,12 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) {
session.reset();

blockCapsule.setMerkleRoot();
signBlockCapsule(blockCapsule, miner);
if (getDynamicPropertiesStore().isAnyPqSchemeAllowed() &&
miner.getPqScheme() != null) {
signBlockCapsuleWithPQ(blockCapsule, miner);
} else {
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里也不应该用else, 若是 pq 方案不允许,minerType 为PQ, 走ecdsa 签名就有问题。

blockCapsule.sign(miner.getPrivateKey());
}

BlockCapsule capsule = new BlockCapsule(blockCapsule.getInstance());
capsule.generatedByMyself = true;
Expand All @@ -1762,57 +1768,23 @@ public BlockCapsule generateBlock(Miner miner, long blockTime, long timeout) {
return capsule;
}

private void signBlockCapsule(BlockCapsule blockCapsule, Miner miner) {
switch (miner.getType()) {
case PQ:
PQScheme scheme = resolveWitnessScheme(miner);
if (scheme == null) {
// PQ-only miner whose configured scheme is not currently usable
// (proposal not activated, scheme allow flag flipped, witness
// permission missing, etc.). Surface a clear cause; DposTask's
// Throwable handler will log and the witness will miss this slot,
// but the producer thread keeps running.
throw new IllegalStateException(
"PQ-only miner " + Hex.toHexString(miner.getWitnessAddress().toByteArray())
+ " has scheme " + miner.getPqScheme()
+ " configured but it is not currently usable "
+ "(scheme not allowed by dynamic properties, "
+ "or witness permission is missing/empty)");
}
signWitnessAuth(blockCapsule, miner, scheme);
break;
case ECDSA:
blockCapsule.sign(miner.getPrivateKey());
break;
default:
throw new IllegalStateException("unknown miner type: " + miner.getType());
}
}

private PQScheme resolveWitnessScheme(Miner miner) {
if (!chainBaseManager.getDynamicPropertiesStore().isAnyPqSchemeAllowed()) {
return null;
}
private void signBlockCapsuleWithPQ(BlockCapsule blockCapsule, Miner miner) {
PQScheme scheme = miner.getPqScheme();
if (scheme == null || !PQSchemeRegistry.contains(scheme)) {
return null;
throw new IllegalStateException(
"PQ-only miner " + Hex.toHexString(miner.getWitnessAddress().toByteArray())
+ " has scheme " + miner.getPqScheme()
+ " configured but it is not currently usable "
+ "or witness permission is missing/empty)");
}
if (!chainBaseManager.getDynamicPropertiesStore().isPqSchemeAllowed(scheme)) {
return null;
}
byte[] witnessAddress = miner.getWitnessAddress().toByteArray();
AccountCapsule accountCapsule = chainBaseManager.getAccountStore().get(witnessAddress);
if (accountCapsule == null || !accountCapsule.getInstance().hasWitnessPermission()) {
return null;
}
Permission witnessPermission = accountCapsule.getInstance().getWitnessPermission();
if (witnessPermission.getKeysCount() == 0) {
return null;
throw new IllegalStateException(
"PQ-only miner " + Hex.toHexString(miner.getWitnessAddress().toByteArray())
+ " has scheme " + miner.getPqScheme()
+ " but it is not allowed by dynamic properties");
}
return scheme;
}

private void signWitnessAuth(BlockCapsule blockCapsule, Miner miner, PQScheme scheme) {

byte[] pqPrivateKey = miner.getPQPrivateKey();
byte[] pqPublicKey = miner.getPQPublicKey();
if (pqPrivateKey == null || pqPublicKey == null) {
Expand Down