Skip to content

Commit 4aa1268

Browse files
committed
Merge branch 'develop'
2 parents ad1907b + 8b31ea9 commit 4aa1268

File tree

8 files changed

+157
-42
lines changed

8 files changed

+157
-42
lines changed

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@
88
"editor.detectIndentation": false,
99
"java.import.projectSelection": "automatic",
1010
"workbench.colorTheme": "Default Dark Modern",
11-
"java.server.launchMode": "Standard"
11+
"java.server.launchMode": "Standard",
12+
"[java]": {
13+
"editor.formatOnSave": true
14+
}
1215
}

conf/node-default.properties

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@
8989
# DB.LockTimeout = 60
9090

9191
## Maximum number of rows to be inserted in a single SQL statement.
92-
## Defaults to 10000, should be ok in most situations.
92+
## Defaults to 1000, should be ok in most situations.
9393
## May be fine-tuned according to your DBMS or your machine's performance.
9494
## Warning: a high value (> 15000 rows) is known to generate queries too big for an SQLite backend
95-
# DB.InsertBatchMaxSize = 10000
95+
# DB.InsertBatchMaxSize = 1000
9696

97-
## Enable the indirect incoming tracker service.
97+
## Enable the indirect incoming tracker service.
9898
## This allows you to see transactions where you are paid but are not the direct recipient, eg, Multi-Outs.
9999
# node.indirectIncomingService.enable = true
100100

@@ -107,7 +107,7 @@
107107
### CPU Settings ###
108108
#####################
109109

110-
## Uncomment this to limit the number of CPU cores the wallet sees.
110+
## Uncomment this to limit the number of CPU cores the wallet sees.
111111
## Default is half available by setting to -1
112112
# CPU.NumCores = 4
113113

@@ -193,7 +193,7 @@
193193
# P2P.getMorePeers = yes
194194

195195
## If the database of peers exceeds this value, more peers will not be downloaded.
196-
## This value will never be below MaxConnections.
196+
## This value will never be below MaxConnections.
197197
# P2P.getMorePeersThreshold = 400
198198

199199
## Peer networking connect timeout for outgoing connections.
@@ -357,7 +357,7 @@
357357
## Your reward recipient is the one you provide the passphrase here.
358358
# RewardRecipientPassphrases=id1:passphrase1;id2:passphrase2;id3:passphrase3;
359359

360-
## Allow anyone to use the "submitNonce" API call. This call can be abused to force your node to perform lots of work to effectively mine for others.
360+
## Allow anyone to use the "submitNonce" API call. This call can be abused to force your node to perform lots of work to effectively mine for others.
361361
## Enabling this option will only allow accounts whose passphrases are in SoloMiningPassphrases to mine through this node.
362362
# AllowOtherSoloMiners=false
363363

src/brs/at/AtApiPlatformImpl.java

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,22 +523,36 @@ public long getPreviousBalance(AtMachineState state) {
523523

524524
@Override
525525
public void sendToAddressInB(long val, AtMachineState state) {
526-
if (val < 1)
526+
if (val < 1) {
527+
logger.debug("sendToAddressInB aborted: val {} < 1", val);
527528
return;
529+
}
530+
531+
logger.debug(
532+
"sendToAddressInB start - val: {}, version: {}",
533+
val,
534+
state.getVersion()
535+
);
528536

529537
if (state.getVersion() > 2) {
530538
long assetId = AtApiHelper.getLong(state.getB2());
539+
logger.debug("sendToAddressInB asset path - assetId: {}", assetId);
531540
if (assetId != 0L) {
532541
long assetBalance = state.getgBalance(assetId);
542+
logger.debug("asset balance: {}", assetBalance);
533543
if (val > assetBalance) {
544+
logger.debug("adjusting val from {} to asset balance {}", val, assetBalance);
534545
val = assetBalance;
535546
}
536547

537548
// optional coin amount besides the asset
538549
long amount = AtApiHelper.getLong(state.getB3());
550+
logger.debug("coin amount in B3 before adjustment: {}", amount);
539551
if (amount > 0L) {
540552
long balance = state.getgBalance();
553+
logger.debug("available coin balance: {}", balance);
541554
if (amount > balance) {
555+
logger.debug("adjusting coin amount from {} to balance {}", amount, balance);
542556
amount = balance;
543557
}
544558
state.setgBalance(balance - amount);
@@ -548,35 +562,72 @@ public void sendToAddressInB(long val, AtMachineState state) {
548562

549563
AtTransaction tx = new AtTransaction(TransactionType.ColoredCoins.ASSET_TRANSFER,
550564
state.getId(), state.getB1().clone(), amount, assetId, val, null);
565+
logger.debug(
566+
"asset transfer tx created - sender: {}, assetId: {}, amount: {}, quantity: {}",
567+
AtApiHelper.getLong(state.getId()),
568+
assetId,
569+
amount,
570+
val
571+
);
551572
state.addTransaction(tx);
552573

553574
state.setgBalance(assetId, assetBalance - val);
575+
logger.debug(
576+
"sendToAddressInB asset path end - new asset gBalance: {}",
577+
state.getgBalance(assetId)
578+
);
554579
return;
555580
}
556581
}
557582

558583
if (val > state.getgBalance()) {
584+
logger.debug(
585+
"adjusting val from {} to current gBalance {}",
586+
val,
587+
state.getgBalance()
588+
);
559589
val = state.getgBalance();
560590
}
561591
AtTransaction tx = new AtTransaction(TransactionType.Payment.ORDINARY, state.getId(), state.getB1().clone(), val, null);
592+
logger.debug(
593+
"ordinary payment tx created - sender: {}, amount: {}",
594+
AtApiHelper.getLong(state.getId()),
595+
val
596+
);
562597
state.addTransaction(tx);
563598

564599
state.setgBalance(state.getgBalance() - val);
600+
logger.debug("sendToAddressInB end - new gBalance: {}", state.getgBalance());
565601
}
566602

567603
@Override
568604
public void mintAsset(AtMachineState state) {
569605
if (state.getVersion() < 3) {
606+
logger.debug("mintAsset aborted: AT version {} < 3", state.getVersion());
570607
return;
571608
}
572609

573610
long assetId = AtApiHelper.getLong(state.getB2());
574611
long accountId = AtApiHelper.getLong(state.getId());
575612
long quantity = AtApiHelper.getLong(state.getB1());
576613

614+
logger.debug(
615+
"mintAsset input - assetId: {}, accountId: {}, quantity: {}, current gBalance: {}",
616+
assetId,
617+
accountId,
618+
quantity,
619+
state.getgBalance(assetId)
620+
);
621+
577622
Asset asset = Signum.getStores().getAssetStore().getAsset(assetId);
578623
if (asset == null || asset.getAccountId() != accountId || quantity <= 0L) {
579624
// only assets that we have created internally and no burning by mint
625+
logger.debug(
626+
"mintAsset aborted: asset null={}, account check={}, quantity={} <= 0",
627+
asset == null,
628+
asset != null && asset.getAccountId() != accountId,
629+
quantity
630+
);
580631
return;
581632
}
582633

@@ -585,11 +636,28 @@ public void mintAsset(AtMachineState state) {
585636
long newSupply = circulatingSupply + quantity;
586637
if (newSupply > Constants.MAX_ASSET_QUANTITY_QNT) {
587638
// do not mint extra to keep the limit
639+
logger.debug(
640+
"mintAsset aborted: newSupply {} > MAX_ASSET_QUANTITY_QNT {}",
641+
newSupply,
642+
Constants.MAX_ASSET_QUANTITY_QNT
643+
);
588644
return;
589645
}
590646

647+
logger.debug(
648+
"mintAsset creating transaction - version: {}, newSupply: {}",
649+
state.getVersion(),
650+
newSupply
651+
);
652+
591653
AtTransaction tx = new AtTransaction(TransactionType.ColoredCoins.ASSET_MINT,
592654
state.getId(), null, 0L, assetId, quantity, null);
655+
logger.debug(
656+
"mintAsset tx created - sender: {}, assetId: {}, quantity: {}",
657+
AtApiHelper.getLong(state.getId()),
658+
assetId,
659+
quantity
660+
);
593661
state.addTransaction(tx);
594662

595663
state.setgBalance(assetId, state.getgBalance(assetId) + quantity);

src/brs/at/AtController.java

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import brs.fluxcapacitor.FluxValues;
77
import brs.props.Props;
88
import brs.util.Convert;
9+
import brs.TransactionType;
910
import org.slf4j.Logger;
1011
import org.slf4j.LoggerFactory;
1112
import org.slf4j.helpers.NOPLogger;
@@ -16,6 +17,7 @@
1617
import java.security.MessageDigest;
1718
import java.util.*;
1819

20+
1921
public abstract class AtController {
2022
private AtController() {
2123
}
@@ -515,37 +517,57 @@ private static int getCostOfOneAT() {
515517
return AtConstants.AT_ID_SIZE + 16;
516518
}
517519

518-
//platform based implementations
519-
//platform based
520-
private static long makeTransactions(AT at, int blockHeight, long generatorId) throws AtException {
521-
long totalAmount = 0;
522-
if (!Signum.getFluxCapacitor().getValue(FluxValues.AT_FIX_BLOCK_4, at.getHeight())) {
523-
for (AtTransaction tx : at.getTransactions()) {
524-
if (AT.findPendingTransaction(tx.getRecipientId(), blockHeight, generatorId)) {
525-
throw new AtException("Conflicting transaction found");
520+
private static long makeTransactions(AT at, int blockHeight, long generatorId) throws AtException {
521+
long totalAmount = 0;
522+
523+
// Start with the transactions as provided
524+
List<AtTransaction> ordered = new ArrayList<>(at.getTransactions());
525+
526+
ordered.sort((tx1, tx2) -> {
527+
if (tx1.getAssetId() == tx2.getAssetId()) {
528+
boolean tx1isMint = tx1.getType() == TransactionType.ColoredCoins.ASSET_MINT;
529+
boolean tx2isMint = tx2.getType() == TransactionType.ColoredCoins.ASSET_MINT;
530+
boolean tx1isTransfer = tx1.getType() == TransactionType.ColoredCoins.ASSET_TRANSFER;
531+
boolean tx2isTransfer = tx2.getType() == TransactionType.ColoredCoins.ASSET_TRANSFER;
532+
533+
if (tx1isMint && tx2isTransfer) return -1;
534+
if (tx1isTransfer && tx2isMint) return 1;
535+
}
536+
return 0;
537+
});
538+
539+
540+
if (!Signum.getFluxCapacitor().getValue(FluxValues.AT_FIX_BLOCK_4, at.getHeight())) {
541+
for (AtTransaction tx : ordered) {
542+
if (AT.findPendingTransaction(tx.getRecipientId(), blockHeight, generatorId)) {
543+
throw new AtException("Conflicting transaction found");
544+
}
545+
}
526546
}
527-
}
528-
}
529-
for (AtTransaction tx : at.getTransactions()) {
530-
totalAmount += tx.getAmount();
531-
AT.addPendingTransaction(tx, blockHeight, generatorId);
532-
if (logger.isDebugEnabled()) {
533-
logger.debug("Transaction to {}, amount {}", tx.getRecipientId() == null ? 0L : Convert.toUnsignedLong(AtApiHelper.getLong(tx.getRecipientId())), tx.getAmount());
534-
}
535-
}
536-
AT.addMapUpdates(at.getMapUpdates(), blockHeight, generatorId);
537547

538-
return totalAmount;
539-
}
548+
for (AtTransaction tx : ordered) {
549+
totalAmount += tx.getAmount();
550+
AT.addPendingTransaction(tx, blockHeight, generatorId);
551+
if (logger.isDebugEnabled()) {
552+
logger.debug(
553+
"Transaction to {}, amount {}",
554+
tx.getRecipientId() == null ? 0L : Convert.toUnsignedLong(AtApiHelper.getLong(tx.getRecipientId())),
555+
tx.getAmount()
556+
);
557+
}
558+
}
540559

541-
//platform based
542-
private static long getATAccountBalance(Long id) {
543-
Account.Balance atAccount = Account.getAccountBalance(id);
560+
AT.addMapUpdates(at.getMapUpdates(), blockHeight, generatorId);
544561

545-
if (atAccount != null) {
546-
return atAccount.getBalanceNqt();
562+
return totalAmount;
547563
}
548564

549-
return 0;
550-
}
551-
}
565+
private static long getATAccountBalance(Long id) {
566+
Account.Balance atAccount = Account.getAccountBalance(id);
567+
if (atAccount != null) {
568+
return atAccount.getBalanceNqt();
569+
}
570+
return 0;
571+
}
572+
573+
}

src/brs/at/AtMachineState.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,4 +691,4 @@ public long getSteps() {
691691
return steps;
692692
}
693693
}
694-
}
694+
}

src/brs/db/sql/SqlATStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public List<Long> getOrderedATs() {
175175
)
176176
).and(
177177
AT_STATE.FREEZE_WHEN_SAME_BALANCE.isFalse().or(
178-
"account_balance.balance - at_state.prev_balance >= at_state.min_activate_amount"
178+
ACCOUNT_BALANCE.BALANCE.minus(AT_STATE.PREV_BALANCE).ge(AT_STATE.MIN_ACTIVATE_AMOUNT)
179179
)
180180
).orderBy(
181181
AT_STATE.PREV_HEIGHT.asc(), AT_STATE.NEXT_HEIGHT.asc(), AT.ID.asc()

src/brs/db/sql/VersionedBatchEntitySqlTable.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ public void finish() {
8181
// As recommended for databases,
8282
// not more than 1000 items should be put in subqueries
8383
int UpdateMaxBatchSize = 1_000;
84+
85+
// As recommended for databases,
86+
// not more than 1000 items should be inserted in a single batch
87+
/**
88+
* The batch size is set to 1000, which is a common practice for bulk inserts.
89+
*/
90+
int InsertMaxBatchSize = 1_000;
91+
8492
Db.useDSLContext(ctx -> {
8593

8694
Field<Long> idField = tableClass.field(dbKeyFactory.getPKColumns()[0], Long.class);
@@ -100,7 +108,21 @@ public void finish() {
100108
.execute();
101109
}
102110

103-
bulkInsert(txContext, getBatch().values());
111+
/**
112+
* Bulk insert of new entities.
113+
* This is done in batches to avoid memory issues with large datasets.
114+
* The entities are collected from the batch and inserted in sublists of size InsertMaxBatchSize.
115+
* This allows us to insert a large number of entities without running into memory issues.
116+
* This is a mutation operation, so it must be inside the transactional scope.
117+
*/
118+
List<T> entitiesToInsert = new ArrayList<>(getBatch().values());
119+
120+
int entitiesListSize = entitiesToInsert.size();
121+
for (int from = 0; from < entitiesListSize; from += InsertMaxBatchSize) {
122+
int to = Math.min(from + InsertMaxBatchSize, entitiesListSize);
123+
bulkInsert(txContext, entitiesToInsert.subList(from, to));
124+
}
125+
104126
// mutation, so must be inside the transactional scope
105127
getBatch().clear();
106128
});

src/brs/props/Props.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public class Props {
104104
public static final Prop<String> BRS_CHECKPOINT_HASH = new Prop<>("node.checkPointPrevHash",
105105
"8f76beca852b41447ac59fbdf78750e43dde97f9fc09ec8f071eeb03c43420f0");
106106
public static final Prop<String> BRS_PK_CHECKS = new Prop<>("node.pkChecks",
107-
"dba639ec3450e0b1;169b3b99ce28a350;a83c47e772a35586;6db77a51a7def19d;c4823aa7028f6735;fb0e32a5bc032257;15a35aa0515e3584;27fcf52c3bc40fba;c4823aa7028f6735;981454e22b5ac976;0cb15471ad76fcd1;");
107+
"dba639ec3450e0b1;169b3b99ce28a350;a83c47e772a35586;6db77a51a7def19d;c4823aa7028f6735;fb0e32a5bc032257;15a35aa0515e3584;27fcf52c3bc40fba;981454e22b5ac976;0cb15471ad76fcd1;");
108108

109109
// GPU options
110110
public static final Prop<Boolean> GPU_ACCELERATION = new Prop<>("GPU.Acceleration", false);
@@ -114,7 +114,7 @@ public class Props {
114114
public static final Prop<Integer> GPU_UNVERIFIED_QUEUE = new Prop<>("GPU.UnverifiedQueue", 1000);
115115
public static final Prop<Integer> GPU_HASHES_PER_BATCH = new Prop<>("GPU.HashesPerBatch", 1000);
116116
public static final Prop<Integer> GPU_MEM_PERCENT = new Prop<>("GPU.MemPercent", 50);
117-
117+
118118
// CPU options
119119
public static final Prop<Integer> CPU_NUM_CORES = new Prop<>("CPU.NumCores", -1);
120120
public static final Prop<Integer> BLOCK_PROCESS_THREAD_DELAY = new Prop<>("CPU.BlockThreadDelay", 500);
@@ -140,7 +140,7 @@ public class Props {
140140
public static final Prop<Integer> BRS_BLOCK_CACHE_MB = new Prop<>("node.blockCacheMB", 40);
141141
public static final Prop<Integer> BRS_AT_PROCESSOR_CACHE_BLOCK_COUNT = new Prop<>("node.atProcessorCacheBlockCount",
142142
1000);
143-
public static final Prop<Integer> DB_INSERT_BATCH_MAX_SIZE = new Prop<>("DB.InsertBatchMaxSize", 10000);
143+
public static final Prop<Integer> DB_INSERT_BATCH_MAX_SIZE = new Prop<>("DB.InsertBatchMaxSize", 1000);
144144

145145
// P2P options
146146
public static final Prop<Integer> P2P_PORT = new Prop<>("P2P.Port", 8123);

0 commit comments

Comments
 (0)