forked from Qortal/qortal
Performance improvement when checking block's online accounts signatures.
If the timestamp-pubkey-sig is still 'current' then it'll be in Controller's list of current online accounts, so we can quickly scan that list before falling back to the more expensive Ed25519 verify. Added equals() and hashCode() to OnlineAccountData to support above.
This commit is contained in:
parent
c2a3c1271c
commit
8dbd8c4e65
@ -916,26 +916,34 @@ public class Block {
|
||||
expandedAccounts.add(rewardShareData);
|
||||
}
|
||||
|
||||
// Possibly check signatures if block is recent
|
||||
// If block is past a certain age then we simply assume the signatures were correct
|
||||
long signatureRequirementThreshold = NTP.getTime() - BlockChain.getInstance().getOnlineAccountSignaturesMinLifetime();
|
||||
if (this.blockData.getTimestamp() >= signatureRequirementThreshold) {
|
||||
if (this.blockData.getOnlineAccountsSignatures() == null || this.blockData.getOnlineAccountsSignatures().length == 0)
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURES_MISSING;
|
||||
if (this.blockData.getTimestamp() < signatureRequirementThreshold)
|
||||
return ValidationResult.OK;
|
||||
|
||||
if (this.blockData.getOnlineAccountsSignatures().length != expandedAccounts.size() * Transformer.SIGNATURE_LENGTH)
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURES_MALFORMED;
|
||||
if (this.blockData.getOnlineAccountsSignatures() == null || this.blockData.getOnlineAccountsSignatures().length == 0)
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURES_MISSING;
|
||||
|
||||
// Check signatures
|
||||
List<byte[]> onlineAccountsSignatures = BlockTransformer.decodeTimestampSignatures(this.blockData.getOnlineAccountsSignatures());
|
||||
byte[] message = Longs.toByteArray(this.blockData.getOnlineAccountsTimestamp());
|
||||
if (this.blockData.getOnlineAccountsSignatures().length != expandedAccounts.size() * Transformer.SIGNATURE_LENGTH)
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURES_MALFORMED;
|
||||
|
||||
for (int i = 0; i < onlineAccountsSignatures.size(); ++i) {
|
||||
PublicKeyAccount account = new PublicKeyAccount(null, expandedAccounts.get(i).getRewardSharePublicKey());
|
||||
byte[] signature = onlineAccountsSignatures.get(i);
|
||||
// Check signatures
|
||||
List<byte[]> onlineAccountsSignatures = BlockTransformer.decodeTimestampSignatures(this.blockData.getOnlineAccountsSignatures());
|
||||
long onlineTimestamp = this.blockData.getOnlineAccountsTimestamp();
|
||||
byte[] onlineTimestampBytes = Longs.toByteArray(onlineTimestamp);
|
||||
List<OnlineAccountData> onlineAccounts = Controller.getInstance().getOnlineAccounts();
|
||||
|
||||
if (!account.verify(signature, message))
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURE_INCORRECT;
|
||||
}
|
||||
for (int i = 0; i < onlineAccountsSignatures.size(); ++i) {
|
||||
byte[] signature = onlineAccountsSignatures.get(i);
|
||||
byte[] publicKey = expandedAccounts.get(i).getRewardSharePublicKey();
|
||||
|
||||
// If signature is still current then no need to perform Ed25519 verify
|
||||
OnlineAccountData onlineAccountData = new OnlineAccountData(onlineTimestamp, signature, publicKey);
|
||||
if (onlineAccounts.remove(onlineAccountData)) // remove() is like contains() but also reduces the number to check next time
|
||||
continue;
|
||||
|
||||
if (!PublicKeyAccount.verify(publicKey, signature, onlineTimestampBytes))
|
||||
return ValidationResult.ONLINE_ACCOUNT_SIGNATURE_INCORRECT;
|
||||
}
|
||||
|
||||
return ValidationResult.OK;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.qortal.data.network;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@ -44,4 +46,36 @@ public class OnlineAccountData {
|
||||
return new PublicKeyAccount(null, this.publicKey).getAddress();
|
||||
}
|
||||
|
||||
// Comparison
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this)
|
||||
return true;
|
||||
|
||||
if (!(other instanceof OnlineAccountData))
|
||||
return false;
|
||||
|
||||
OnlineAccountData otherOnlineAccountData = (OnlineAccountData) other;
|
||||
|
||||
// Very quick comparison
|
||||
if (otherOnlineAccountData.timestamp != this.timestamp)
|
||||
return false;
|
||||
|
||||
// Signature more likely to be unique than public key
|
||||
if (!Arrays.equals(otherOnlineAccountData.signature, this.signature))
|
||||
return false;
|
||||
|
||||
if (!Arrays.equals(otherOnlineAccountData.publicKey, this.publicKey))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Pretty lazy implementation
|
||||
return (int) this.timestamp;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user