diff --git a/src/brs/Appendix.java b/src/brs/Appendix.java index a90b97739..29a04730d 100644 --- a/src/brs/Appendix.java +++ b/src/brs/Appendix.java @@ -2,6 +2,7 @@ import brs.crypto.EncryptedData; import brs.fluxcapacitor.FluxValues; +import brs.props.Props; import brs.util.Convert; import brs.util.JSON; import com.google.gson.JsonObject; @@ -399,6 +400,10 @@ public void validate(Transaction transaction) throws BurstException.ValidationEx if (recipientAccount != null && recipientAccount.getPublicKey() != null && ! Arrays.equals(publicKey, recipientAccount.getPublicKey())) { throw new BurstException.NotCurrentlyValidException("A different public key for this account has already been announced"); } + if(Burst.getFluxCapacitor().getValue(FluxValues.PK_FREEZE) + && Burst.getBlockchain().getHeight() - recipientAccount.getCreationHeight() > Burst.getPropertyService().getInt(Props.PK_BLOCKS_PAST)) { + throw new BurstException.NotCurrentlyValidException("Setting a new key for and old inactivated account"); + } } @Override diff --git a/src/brs/BlockchainProcessorImpl.java b/src/brs/BlockchainProcessorImpl.java index d08378384..1f0c7f040 100644 --- a/src/brs/BlockchainProcessorImpl.java +++ b/src/brs/BlockchainProcessorImpl.java @@ -823,6 +823,9 @@ private int checkDatabaseState() { long totalMined = blockchain.getTotalMined(); long totalEffectiveBalance = accountService.getAllAccountsBalance(); + for (Escrow escrow : escrowService.getAllEscrowTransactions()) { + totalEffectiveBalance += escrow.getAmountNQT(); + } if(totalMined != totalEffectiveBalance) { logger.warn("Block height {}, total mined {}, total effective+burnt {}", blockchain.getHeight(), totalMined, totalEffectiveBalance); @@ -1134,7 +1137,7 @@ private List popOffTo(Block commonBlock, List forkBlocks) { logger.debug("Rolling back derived tables..."); for(DerivedTable table : derivedTableManager.getDerivedTables()) { logger.debug("Rolling back {}", table.getTable()); - table.rollback(commonBlock.getHeight()); + table.rollback(commonBlock.getHeight()); } dbCacheManager.flushCache(); stores.commitTransaction(); diff --git a/src/brs/Burst.java b/src/brs/Burst.java index c3b0063bf..c8575fa01 100644 --- a/src/brs/Burst.java +++ b/src/brs/Burst.java @@ -47,7 +47,7 @@ public final class Burst { - public static final Version VERSION = Version.parse("v3.5.3"); + public static final Version VERSION = Version.parse("v3.6.0"); public static final String APPLICATION = "BRS"; public static final String CONF_FOLDER = "./conf"; diff --git a/src/brs/db/sql/SqlAccountStore.java b/src/brs/db/sql/SqlAccountStore.java index 14f9ee4f7..d63946bce 100644 --- a/src/brs/db/sql/SqlAccountStore.java +++ b/src/brs/db/sql/SqlAccountStore.java @@ -11,7 +11,10 @@ import brs.db.cache.DBCacheManagerImpl; import brs.db.store.AccountStore; import brs.db.store.DerivedTableManager; +import brs.fluxcapacitor.FluxValues; +import brs.props.Props; import brs.util.Convert; +import burst.kit.crypto.BurstCrypto; import org.jooq.*; import org.jooq.impl.DSL; @@ -52,6 +55,9 @@ public DbKey newKey(Account.AccountAsset accountAsset) { } }; + private static final Set PK_CHECKS = Collections + .unmodifiableSet(new HashSet<>(Burst.getPropertyService().getStringList(Props.BRS_PK_CHECKS))); + public SqlAccountStore(DerivedTableManager derivedTableManager, DBCacheManagerImpl dbCacheManager) { rewardRecipientAssignmentTable = new VersionedEntitySqlTable("reward_recip_assign", brs.schema.Tables.REWARD_RECIP_ASSIGN, rewardRecipientAssignmentDbKeyFactory, derivedTableManager) { @@ -306,26 +312,36 @@ public Collection getAssetAccounts(Asset asset, boolean ig condition = condition.and(ACCOUNT_ASSET.ACCOUNT_ID.notIn(treasuryAccounts)); } Collection accounts = getAccountAssetTable().getManyBy(condition, from, to, sort); - + // flag treasury accounts for(AccountAsset account : accounts) { if(treasuryAccounts.contains(account.getAccountId())) { account.setTreasury(true); } } - + return accounts; } @Override public boolean setOrVerify(Account acc, byte[] key, int height) { if (acc.getPublicKey() == null) { + if(Burst.getFluxCapacitor().getValue(FluxValues.PK_FREEZE) + && Burst.getBlockchain().getHeight() - acc.getCreationHeight() > Burst.getPropertyService().getInt(Props.PK_BLOCKS_PAST)) { + logger.info("Setting a new key for and old account {} is not allowed, created at height {}", Convert.toUnsignedLong(acc.id), acc.getCreationHeight()); + return false; + } + if (Db.isInTransaction()) { acc.setPublicKey(key); acc.setKeyHeight(-1); getAccountTable().insert(acc); } return true; + } else if(Burst.getFluxCapacitor().getValue(FluxValues.PK_FREEZE) + && PK_CHECKS.contains(Convert.toHexString(BurstCrypto.getInstance().longToBytesLE(acc.getId())))){ + logger.info("Using the key for account {}", Convert.toUnsignedLong(acc.id)); + return false; } else if (Arrays.equals(acc.getPublicKey(), key)) { return true; } else if (acc.getKeyHeight() == -1) { diff --git a/src/brs/fluxcapacitor/FluxValues.java b/src/brs/fluxcapacitor/FluxValues.java index 2ad540f70..516895443 100644 --- a/src/brs/fluxcapacitor/FluxValues.java +++ b/src/brs/fluxcapacitor/FluxValues.java @@ -1,7 +1,9 @@ package brs.fluxcapacitor; +import brs.Burst; import brs.Constants; import brs.Version; +import brs.props.Props; public class FluxValues { private FluxValues() { @@ -24,6 +26,7 @@ private FluxValues() { public static final FluxEnable SMART_FEES = new FluxEnable(HistoricalMoments.SMART_FEES); public static final FluxEnable SMART_ATS = new FluxEnable(HistoricalMoments.SMART_ATS); public static final FluxEnable DISTRIBUTION_FIX = new FluxEnable(HistoricalMoments.DISTRIBUTION_FIX); + public static final FluxEnable PK_FREEZE = new FluxEnable(HistoricalMoments.PK_FREEZE); public static final FluxEnable NEXT_FORK = new FluxEnable(HistoricalMoments.NEXT_FORK); public static final FluxValue BLOCK_TIME = new FluxValue<>(240); @@ -56,7 +59,7 @@ private FluxValues() { new FluxValue.ValueChange<>(HistoricalMoments.SPEEDWAY, 96L)); public static final FluxValue MIN_PEER_VERSION = new FluxValue<>( - Version.parse("3.4.0"), - new FluxValue.ValueChange<>(HistoricalMoments.DISTRIBUTION_FIX, Version.parse("3.4.9")) + Version.parse("3.5.0"), + new FluxValue.ValueChange<>(HistoricalMoments.PK_FREEZE, Version.parse("3.5.9")) ); } diff --git a/src/brs/fluxcapacitor/HistoricalMoments.java b/src/brs/fluxcapacitor/HistoricalMoments.java index 8e28d3f65..1aa3cba03 100644 --- a/src/brs/fluxcapacitor/HistoricalMoments.java +++ b/src/brs/fluxcapacitor/HistoricalMoments.java @@ -22,6 +22,7 @@ public class HistoricalMoments { public static HistoricalMoments SMART_ATS = new HistoricalMoments(1_029_000, Props.SMART_ATS_HEIGHT); public static HistoricalMoments AT_FIX_BLOCK_5 = new HistoricalMoments(1_051_900, Props.AT_FIX_BLOCK_5_BLOCK_HEIGHT); public static HistoricalMoments DISTRIBUTION_FIX = new HistoricalMoments(1_051_900, Props.DISTRIBUTION_FIX_BLOCK_HEIGHT); + public static HistoricalMoments PK_FREEZE = new HistoricalMoments(1_099_400, Props.PK_BLOCK_HEIGHT); public static HistoricalMoments NEXT_FORK = new HistoricalMoments(Integer.MAX_VALUE, Props.DEV_NEXT_FORK_BLOCK_HEIGHT); private final int mainnetHeight; diff --git a/src/brs/http/APITransactionManagerImpl.java b/src/brs/http/APITransactionManagerImpl.java index 25b014f07..337852b3c 100644 --- a/src/brs/http/APITransactionManagerImpl.java +++ b/src/brs/http/APITransactionManagerImpl.java @@ -135,6 +135,12 @@ public JsonElement createTransaction(HttpServletRequest req, Account senderAccou try { Builder builder = transactionProcessor.newTransactionBuilder(publicKey, amountNQT, feeNQT, deadline, attachment).referencedTransactionFullHash(referencedTransactionFullHash); if (attachment.getTransactionType().hasRecipient()) { + if(Burst.getFluxCapacitor().getValue(FluxValues.PK_FREEZE)) { + Account recipientAccount = accountService.getAccount(recipientId); + if((recipientAccount == null || recipientAccount.getPublicKey() == null) && publicKeyAnnouncement == null) { + return incorrect(RECIPIENT_PARAMETER); + } + } builder.recipientId(recipientId); } if (encryptedMessage != null) { diff --git a/src/brs/props/Props.java b/src/brs/props/Props.java index 6b6868857..f85841d93 100644 --- a/src/brs/props/Props.java +++ b/src/brs/props/Props.java @@ -59,7 +59,10 @@ public class Props { public static final Prop SMART_ATS_HEIGHT = new Prop<>("brs.smartAts.startBlock", -1); public static final Prop DISTRIBUTION_FIX_BLOCK_HEIGHT = new Prop<>("brs.distributionFix.startBlock", -1); public static final Prop AT_FIX_BLOCK_5_BLOCK_HEIGHT = new Prop<>("brs.atFixBlock5.startBlock", -1); - + + public static final Prop PK_BLOCK_HEIGHT = new Prop<>("brs.pkBlock.startBlock", -1); + public static final Prop PK_BLOCKS_PAST = new Prop<>("brs.pkBlocksPast", 131400); + public static final Prop DEV_NEXT_FORK_BLOCK_HEIGHT = new Prop<>("DEV.nextFork.startBlock", -1); public static final Prop BRS_DEBUG_TRACE_ENABLED = new Prop<>("brs.debugTraceEnable", false); @@ -80,6 +83,7 @@ public class Props { // Checkpoint block for faster sync from empty database public static final Prop BRS_CHECKPOINT_HEIGHT = new Prop<>("node.checkPointHeight", 970_000); public static final Prop BRS_CHECKPOINT_HASH = new Prop<>("node.checkPointPrevHash", "c0bb65a25e6fb5f6c4672b5ced900bdf9eb8247187467fd504f42e050fe2ad36"); + public static final Prop BRS_PK_CHECKS = new Prop<>("node.pkChecks", "dba639ec3450e0b1;169b3b99ce28a350;a83c47e772a35586;6db77a51a7def19d;c4823aa7028f6735;fb0e32a5bc032257;15a35aa0515e3584;27fcf52c3bc40fba;c4823aa7028f6735;981454e22b5ac976;0cb15471ad76fcd1;"); // GPU options public static final Prop GPU_ACCELERATION = new Prop<>("GPU.Acceleration", false); diff --git a/src/signum/net/TestnetNetwork.java b/src/signum/net/TestnetNetwork.java index fdcf9adb0..a6731d447 100644 --- a/src/signum/net/TestnetNetwork.java +++ b/src/signum/net/TestnetNetwork.java @@ -40,6 +40,10 @@ public TestnetNetwork() { setProperty(Props.BRS_CHECKPOINT_HEIGHT, "381300"); setProperty(Props.BRS_CHECKPOINT_HASH, "f0846a5d9f43801498316011601dd7c90fa7a20bd95295f2a5fba032bcdeb495"); + setProperty(Props.BRS_PK_CHECKS, "900bb3db35adb8a8;c7e083683bbbc831;"); + + setProperty(Props.PK_BLOCK_HEIGHT, "500080"); + setProperty(Props.PK_BLOCKS_PAST, "120"); setProperty(Props.ADDRESS_PREFIX, "TS"); setProperty(Props.VALUE_SUFIX, "TSIGNA");