public static Block getECBlock(int timestamp) { Block block = blockchain.getLastBlock(); if (timestamp < block.getTimestamp() - 15) { throw new IllegalArgumentException( "Timestamp cannot be more than 15 s earlier than last block timestamp: " + block.getTimestamp()); } int distance = 0; while (block.getTimestamp() > timestamp - Constants.EC_RULE_TERMINATOR && distance < Constants.EC_BLOCK_DISTANCE_LIMIT) { block = blockchain.getBlock(block.getPreviousBlockId()); distance += 1; } return block; }
public static boolean verifyFork(Transaction transaction) { if (blockchain.getHeight() < Constants.DIGITAL_GOODS_STORE_BLOCK) { return true; } if (transaction.getReferencedTransactionFullHash() != null) { return true; } if (blockchain.getHeight() < Constants.EC_CHANGE_BLOCK_1) { if (blockchain.getHeight() - transaction.getECBlockHeight() > Constants.EC_BLOCK_DISTANCE_LIMIT) { return false; } } Block ecBlock = blockchain.getBlock(transaction.getECBlockId()); return ecBlock != null && ecBlock.getHeight() == transaction.getECBlockHeight(); }
/** * Trim the account ledger table * * @param height Trim height */ @Override public void trim(int height) { if (trimKeep <= 0) return; try (Connection con = db.getConnection(); PreparedStatement pstmt = con.prepareStatement("DELETE FROM account_ledger WHERE height <= ?")) { int trimHeight = Math.max(blockchain.getHeight() - trimKeep, 0); pstmt.setInt(1, trimHeight); pstmt.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e.toString(), e); } }
static boolean mustLogEntry(long accountId, boolean isUnconfirmed) { // // Must be tracking this account // if (!ledgerEnabled || (!trackAllAccounts && !trackAccounts.contains(accountId))) { return false; } // confirmed changes only occur while processing block, and unconfirmed changes are // only logged while processing block if (!blockchainProcessor.isProcessingBlock()) { return false; } // // Log unconfirmed changes only when processing a block and logUnconfirmed does not equal 0 // Log confirmed changes unless logUnconfirmed equals 2 // if (isUnconfirmed && logUnconfirmed == 0) { return false; } if (!isUnconfirmed && logUnconfirmed == 2) { return false; } if (trimKeep > 0 && blockchain.getHeight() <= Constants.LAST_KNOWN_BLOCK - trimKeep) { return false; } // // Don't log account changes if we are scanning the blockchain and the current height // is less than the minimum account_ledger trim height // if (blockchainProcessor.isScanning() && trimKeep > 0 && blockchain.getHeight() <= blockchainProcessor.getInitialScanHeight() - trimKeep) { return false; } return true; }
/** * Create a ledger entry * * @param event Event * @param eventId Event identifier * @param accountId Account identifier * @param holding Holding or null * @param holdingId Holding identifier or null * @param change Change in balance * @param balance New balance */ public LedgerEntry( LedgerEvent event, long eventId, long accountId, LedgerHolding holding, Long holdingId, long change, long balance) { this.event = event; this.eventId = eventId; this.accountId = accountId; this.holding = holding; this.holdingId = holdingId; this.change = change; this.balance = balance; Block block = blockchain.getLastBlock(); this.blockId = block.getId(); this.height = block.getHeight(); this.timestamp = block.getTimestamp(); }
/** * Return the ledger entries sorted in descending insert order * * @param accountId Account identifier or zero if no account identifier * @param event Ledger event or null * @param eventId Ledger event identifier or zero if no event identifier * @param holding Ledger holding or null * @param holdingId Ledger holding identifier or zero if no holding identifier * @param firstIndex First matching entry index, inclusive * @param lastIndex Last matching entry index, inclusive * @return List of ledger entries */ public static List<LedgerEntry> getEntries( long accountId, LedgerEvent event, long eventId, LedgerHolding holding, long holdingId, int firstIndex, int lastIndex) { if (!ledgerEnabled) { return Collections.emptyList(); } List<LedgerEntry> entryList = new ArrayList<>(); // // Build the SELECT statement to search the entries StringBuilder sb = new StringBuilder(128); sb.append("SELECT * FROM account_ledger "); if (accountId != 0 || event != null || holding != null) { sb.append("WHERE "); } if (accountId != 0) { sb.append("account_id = ? "); } if (event != null) { if (accountId != 0) { sb.append("AND "); } sb.append("event_type = ? "); if (eventId != 0) sb.append("AND event_id = ? "); } if (holding != null) { if (accountId != 0 || event != null) { sb.append("AND "); } sb.append("holding_type = ? "); if (holdingId != 0) sb.append("AND holding_id = ? "); } sb.append("ORDER BY db_id DESC "); sb.append(DbUtils.limitsClause(firstIndex, lastIndex)); // // Get the ledger entries // blockchain.readLock(); try (Connection con = Db.db.getConnection(); PreparedStatement pstmt = con.prepareStatement(sb.toString())) { int i = 0; if (accountId != 0) { pstmt.setLong(++i, accountId); } if (event != null) { pstmt.setByte(++i, (byte) event.getCode()); if (eventId != 0) { pstmt.setLong(++i, eventId); } } if (holding != null) { pstmt.setByte(++i, (byte) holding.getCode()); if (holdingId != 0) { pstmt.setLong(++i, holdingId); } } DbUtils.setLimits(++i, pstmt, firstIndex, lastIndex); try (ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { entryList.add(new LedgerEntry(rs)); } } } catch (SQLException e) { throw new RuntimeException(e.toString(), e); } finally { blockchain.readUnlock(); } return entryList; }