Skip to content

Commit

Permalink
Updating from weighted average to weighted percentile method and nami…
Browse files Browse the repository at this point in the history
…ng updates
  • Loading branch information
asoto-iov committed Jan 26, 2024
1 parent 098883d commit a74aa4f
Show file tree
Hide file tree
Showing 12 changed files with 465 additions and 214 deletions.
4 changes: 2 additions & 2 deletions rskj-core/src/main/java/co/rsk/RskContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
import org.ethereum.facade.Ethereum;
import org.ethereum.facade.EthereumImpl;
import org.ethereum.listener.CompositeEthereumListener;
import org.ethereum.listener.GasCalculator;
import org.ethereum.listener.GasPriceCalculator;
import org.ethereum.listener.GasPriceTracker;
import org.ethereum.net.EthereumChannelInitializerFactory;
import org.ethereum.net.NodeManager;
Expand Down Expand Up @@ -556,7 +556,7 @@ public synchronized Ethereum getRsk() {
public GasPriceTracker getGasPriceTracker() {
checkIfNotClosed();
if (this.gasPriceTracker == null) {
GasCalculator.GasCalculatorType calculatorType = getRskSystemProperties().getGasCalculatorType();
GasPriceCalculator.GasCalculatorType calculatorType = getRskSystemProperties().getGasCalculatorType();
this.gasPriceTracker = GasPriceTracker.create(getBlockStore(), calculatorType);
}
return this.gasPriceTracker;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.ethereum.core.Account;
import org.ethereum.crypto.ECKey;
import org.ethereum.crypto.HashUtil;
import org.ethereum.listener.GasCalculator;
import org.ethereum.listener.GasPriceCalculator;

import javax.annotation.Nullable;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -485,12 +485,12 @@ public double getTopBest() {
return value;
}

public GasCalculator.GasCalculatorType getGasCalculatorType() {
public GasPriceCalculator.GasCalculatorType getGasCalculatorType() {
String value = configFromFiles.getString(MINER_GAS_PRICE_CALCULATOR_TYPE);
if (value == null || value.isEmpty()) {
return GasCalculator.GasCalculatorType.LEGACY;
return GasPriceCalculator.GasCalculatorType.PLAIN_PERCENTILE;
}
GasCalculator.GasCalculatorType gasCalculatorType = GasCalculator.GasCalculatorType.fromString(value);
GasPriceCalculator.GasCalculatorType gasCalculatorType = GasPriceCalculator.GasCalculatorType.fromString(value);
if(gasCalculatorType == null) {
throw new RskConfigurationException("Invalid gasPriceCalculatorType: " + value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@
import java.util.List;
import java.util.Optional;

public interface GasCalculator {
public interface GasPriceCalculator {
public enum GasCalculatorType {
LEGACY,
WEIGHTED;
PLAIN_PERCENTILE,
WEIGHTED_PERCENTILE;

public static GasCalculatorType fromString(String type) {
if (type == null) {
return null;
}
switch (type.toLowerCase()) {
case "weighted":
return WEIGHTED;
case "legacy":
return LEGACY;
case "weighted_percentile":
return WEIGHTED_PERCENTILE;
case "plain_percentile":
return PLAIN_PERCENTILE;
default:
return null;
}
Expand All @@ -46,4 +46,6 @@ public static GasCalculatorType fromString(String type) {

Optional<Coin> getGasPrice();
void onBlock(Block block, List<TransactionReceipt> receipts);

GasCalculatorType getType();
}
34 changes: 18 additions & 16 deletions rskj-core/src/main/java/org/ethereum/listener/GasPriceTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,21 @@ public class GasPriceTracker extends EthereumListenerAdapter {
private Coin defaultPrice = Coin.valueOf(20_000_000_000L);
private int blockIdx = 0;

private final GasCalculator gasCalculator;
private final GasPriceCalculator gasPriceCalculator;

private GasPriceTracker(BlockStore blockStore, GasCalculator gasCalculator) {
private GasPriceTracker(BlockStore blockStore, GasPriceCalculator gasPriceCalculator) {
this.blockStore = blockStore;
this.gasCalculator = gasCalculator;
this.gasPriceCalculator = gasPriceCalculator;
}

public static GasPriceTracker create(BlockStore blockStore, GasCalculator.GasCalculatorType gasCalculatorType) {
GasCalculator gasCal;
public static GasPriceTracker create(BlockStore blockStore, GasPriceCalculator.GasCalculatorType gasCalculatorType) {
GasPriceCalculator gasCal;
switch (gasCalculatorType) {
case WEIGHTED:
gasCal = new GasWeightedCalc();
case WEIGHTED_PERCENTILE:
gasCal = new WeightedPercentileGasPriceCalculator();
break;
case LEGACY:
gasCal = new LegacyGasCalculator();
case PLAIN_PERCENTILE:
gasCal = new PercentileGasPriceCalculator();
break;
default:
throw new IllegalArgumentException("Unknown gas calculator type: " + gasCalculatorType);
Expand All @@ -87,14 +87,12 @@ public static GasPriceTracker create(BlockStore blockStore, GasCalculator.GasCal
}

/**
* @deprecated Use {@link #create(BlockStore, GasCalculator.GasCalculatorType)} instead.
* @deprecated Use {@link #create(BlockStore, GasPriceCalculator.GasCalculatorType)} instead.
*/
@Deprecated
public static GasPriceTracker create(BlockStore blockStore) {
//Will be using the legacy gas calculator as default option
GasPriceTracker gasPriceTracker = new GasPriceTracker(blockStore, new LegacyGasCalculator());
gasPriceTracker.initializeWindowsFromDB();
return gasPriceTracker;
return GasPriceTracker.create(blockStore, GasPriceCalculator.GasCalculatorType.PLAIN_PERCENTILE);
}

@Override
Expand All @@ -110,17 +108,17 @@ public synchronized void onBlock(Block block, List<TransactionReceipt> receipts)

trackBlockCompleteness(block);

gasCalculator.onBlock(block, receipts);
gasPriceCalculator.onBlock(block, receipts);
logger.trace("End onBlock");
}

public synchronized Coin getGasPrice() {
Optional<Coin> gasPriceResult = gasCalculator.getGasPrice();
Optional<Coin> gasPriceResult = gasPriceCalculator.getGasPrice();
if(!gasPriceResult.isPresent()) {
return defaultPrice;
}

logger.debug("Gas provided by GasWindowCalc: {}", gasCalculator.getGasPrice());
logger.debug("Gas provided by GasWindowCalc: {}", gasPriceCalculator.getGasPrice());

Coin bestBlockPrice = bestBlockPriceRef.get();
if (bestBlockPrice == null) {
Expand Down Expand Up @@ -191,4 +189,8 @@ private void trackBlockCompleteness(Block block) {
blockWindow[blockIdx++] = completeness;
}

public GasPriceCalculator.GasCalculatorType getGasCalculatorType() {
return gasPriceCalculator.getType();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import java.util.List;
import java.util.Optional;

public class LegacyGasCalculator implements GasCalculator {
public class PercentileGasPriceCalculator implements GasPriceCalculator {
private static final int TX_WINDOW_SIZE = 512;

private final Coin[] txWindow = new Coin[TX_WINDOW_SIZE];
Expand All @@ -53,6 +53,11 @@ public void onBlock(Block block, List<TransactionReceipt> receipts) {
onBlock(block.getTransactionsList());
}

@Override
public GasCalculatorType getType() {
return GasCalculatorType.PLAIN_PERCENTILE;
}

private void onBlock(List<Transaction> transactionList) {
for (Transaction tx : transactionList) {
if (!(tx instanceof RemascTransaction)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* This file is part of RskJ
* Copyright (C) 2024 RSK Labs Ltd.
* (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ethereum.listener;

import co.rsk.core.Coin;

import java.util.Collections;
import java.util.List;

public class WeightedPercentileCalc {

public Coin calculateWeightedPercentile(float percentile, List<WeightedPercentileGasPriceCalculator.GasEntry> gasEntries) {
if (gasEntries == null || gasEntries.isEmpty()) {
return null;
}

Collections.sort(gasEntries);

double totalWeight = gasEntries.stream().mapToLong(WeightedPercentileGasPriceCalculator.GasEntry::getGasUsed).sum();

double targetWeight = percentile / 100 * totalWeight;


double cumulativeWeight = 0;
for (WeightedPercentileGasPriceCalculator.GasEntry pair : gasEntries) {
cumulativeWeight += pair.getGasUsed();
if (cumulativeWeight >= targetWeight) {
return pair.getGasPrice();
}
}

return null;
}
}

0 comments on commit a74aa4f

Please sign in to comment.