Skip to content

Commit

Permalink
Merge pull request #2423 from rsksmart/fee-per-kb-refactor-integration
Browse files Browse the repository at this point in the history
Fee per kb refactor integration
  • Loading branch information
Vovchyk committed Jun 10, 2024
2 parents abf22ed + f1edb96 commit 14cae37
Show file tree
Hide file tree
Showing 50 changed files with 2,314 additions and 1,584 deletions.
3 changes: 2 additions & 1 deletion rskj-core/src/main/java/co/rsk/peg/Bridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import co.rsk.crypto.Keccak256;
import co.rsk.panic.PanicProcessor;
import co.rsk.peg.BridgeMethods.BridgeMethodExecutor;
import co.rsk.peg.feeperkb.FeePerKbResponseCode;
import co.rsk.peg.vote.ABICallSpec;
import co.rsk.peg.bitcoin.MerkleBranch;
import co.rsk.peg.federation.Federation;
Expand Down Expand Up @@ -1128,7 +1129,7 @@ public Integer voteFeePerKbChange(Object[] args) {
feePerKb = Coin.valueOf(((BigInteger) args[0]).longValueExact());
} catch (Exception e) {
logger.warn("Exception in voteFeePerKbChange", e);
return -10;
return FeePerKbResponseCode.GENERIC_ERROR.getCode();
}

return bridgeSupport.voteFeePerKbChange(rskTx, feePerKb);
Expand Down
2 changes: 0 additions & 2 deletions rskj-core/src/main/java/co/rsk/peg/BridgeStorageIndexKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ public enum BridgeStorageIndexKey {
FEDERATION_ELECTION_KEY("federationElection"),
LOCK_ONE_OFF_WHITELIST_KEY("lockWhitelist"),
LOCK_UNLIMITED_WHITELIST_KEY("unlimitedLockWhitelist"),
FEE_PER_KB_KEY("feePerKb"),
FEE_PER_KB_ELECTION_KEY("feePerKbElection"),
LOCKING_CAP_KEY("lockingCap"),
RELEASE_REQUEST_QUEUE_WITH_TXHASH("releaseRequestQueueWithTxHash"),
PEGOUTS_WAITING_FOR_CONFIRMATIONS_WITH_TXHASH_KEY("releaseTransactionSetWithTxHash"),
Expand Down
47 changes: 0 additions & 47 deletions rskj-core/src/main/java/co/rsk/peg/BridgeStorageProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ public class BridgeStorageProvider {

private LockWhitelist lockWhitelist;

private Coin feePerKb;
private ABICallElection feePerKbElection;

private Coin lockingCap;

private HashMap<DataWord, Optional<Integer>> storageVersionEntries;
Expand Down Expand Up @@ -547,47 +544,6 @@ public LockWhitelist getLockWhitelist() {
return lockWhitelist;
}

public Coin getFeePerKb() {
if (feePerKb != null) {
return feePerKb;
}

feePerKb = safeGetFromRepository(FEE_PER_KB_KEY, BridgeSerializationUtils::deserializeCoin);
return feePerKb;
}

public void setFeePerKb(Coin feePerKb) {
this.feePerKb = feePerKb;
}

public void saveFeePerKb() {
if (feePerKb == null) {
return;
}

safeSaveToRepository(FEE_PER_KB_KEY, feePerKb, BridgeSerializationUtils::serializeCoin);
}

/**
* Save the fee per kb election
*/
public void saveFeePerKbElection() {
if (feePerKbElection == null) {
return;
}

safeSaveToRepository(FEE_PER_KB_ELECTION_KEY, feePerKbElection, BridgeSerializationUtils::serializeElection);
}

public ABICallElection getFeePerKbElection(AddressBasedAuthorizer authorizer) {
if (feePerKbElection != null) {
return feePerKbElection;
}

feePerKbElection = safeGetFromRepository(FEE_PER_KB_ELECTION_KEY, data -> BridgeSerializationUtils.deserializeElection(data, authorizer));
return feePerKbElection;
}

public void saveLockingCap() {
if (activations.isActive(RSKIP134)) {
safeSaveToRepository(LOCKING_CAP_KEY, this.getLockingCap(), BridgeSerializationUtils::serializeCoin);
Expand Down Expand Up @@ -982,9 +938,6 @@ public void save() throws IOException {

saveLockWhitelist();

saveFeePerKb();
saveFeePerKbElection();

saveLockingCap();

saveHeightBtcTxHashAlreadyProcessed();
Expand Down
85 changes: 14 additions & 71 deletions rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@
import co.rsk.core.RskAddress;
import co.rsk.crypto.Keccak256;
import co.rsk.panic.PanicProcessor;
import co.rsk.peg.bitcoin.*;
import co.rsk.peg.bitcoin.BitcoinUtils;
import co.rsk.peg.bitcoin.CoinbaseInformation;
import co.rsk.peg.bitcoin.MerkleBranch;
import co.rsk.peg.bitcoin.RskAllowUnconfirmedCoinSelector;
import co.rsk.peg.btcLockSender.BtcLockSender.TxSenderAddressType;
import co.rsk.peg.btcLockSender.BtcLockSenderProvider;
import co.rsk.peg.federation.*;
import co.rsk.peg.feeperkb.FeePerKbSupport;
import co.rsk.peg.flyover.FlyoverFederationInformation;
import co.rsk.peg.flyover.FlyoverTxResponseCodes;
import co.rsk.peg.pegin.*;
Expand Down Expand Up @@ -88,9 +92,6 @@ public class BridgeSupport {
public static final Integer LOCK_WHITELIST_ALREADY_EXISTS_ERROR_CODE = -1;
public static final Integer LOCK_WHITELIST_UNKNOWN_ERROR_CODE = 0;
public static final Integer LOCK_WHITELIST_SUCCESS_CODE = 1;
public static final Integer FEE_PER_KB_GENERIC_ERROR_CODE = -10;
public static final Integer NEGATIVE_FEE_PER_KB_ERROR_CODE = -1;
public static final Integer EXCESSIVE_FEE_PER_KB_ERROR_CODE = -2;

public static final Integer BTC_TRANSACTION_CONFIRMATION_INEXISTENT_BLOCK_HASH_ERROR_CODE = -1;
public static final Integer BTC_TRANSACTION_CONFIRMATION_BLOCK_NOT_IN_BEST_CHAIN_ERROR_CODE = -2;
Expand Down Expand Up @@ -121,6 +122,7 @@ public class BridgeSupport {
"rollback"
));

private final FeePerKbSupport feePerKbSupport;
private final BridgeConstants bridgeConstants;
private final BridgeStorageProvider provider;
private final Repository rskRepository;
Expand Down Expand Up @@ -150,6 +152,7 @@ public BridgeSupport(
Block executionBlock,
Context btcContext,
FederationSupport federationSupport,
FeePerKbSupport feePerKbSupport,
BtcBlockStoreWithCache.Factory btcBlockStoreFactory,
ActivationConfig.ForBlock activations,
SignatureCache signatureCache) {
Expand All @@ -162,6 +165,7 @@ public BridgeSupport(
this.peginInstructionsProvider = peginInstructionsProvider;
this.btcContext = btcContext;
this.federationSupport = federationSupport;
this.feePerKbSupport = feePerKbSupport;
this.btcBlockStoreFactory = btcBlockStoreFactory;
this.activations = activations;
this.signatureCache = signatureCache;
Expand Down Expand Up @@ -190,6 +194,7 @@ ActivationConfig.ForBlock getActivations() {

public void save() throws IOException {
provider.save();
feePerKbSupport.save();
}

/**
Expand Down Expand Up @@ -916,19 +921,6 @@ private void requestRelease(Address destinationAddress, Coin value, Transaction
}
}

/**
* @return Current fee per kb in BTC.
*/
public Coin getFeePerKb() {
Coin currentFeePerKb = provider.getFeePerKb();

if (currentFeePerKb == null) {
currentFeePerKb = bridgeConstants.getGenesisFeePerKb();
}

return currentFeePerKb;
}

/**
* Executed every now and then.
* Performs a few tasks: processing of any pending btc funds
Expand Down Expand Up @@ -2548,61 +2540,12 @@ public Integer removeLockWhitelistAddress(Transaction tx, String addressBase58)
}
}

/**
* Votes for a fee per kb value.
*
* @return 1 upon successful vote, -1 when the vote was unsuccessful,
* FEE_PER_KB_GENERIC_ERROR_CODE when there was an un expected error.
*/
public Integer voteFeePerKbChange(Transaction tx, Coin feePerKb) {
AddressBasedAuthorizer authorizer = bridgeConstants.getFeePerKbChangeAuthorizer();
if (!authorizer.isAuthorized(tx, signatureCache)) {
return FEE_PER_KB_GENERIC_ERROR_CODE;
}

if(!feePerKb.isPositive()){
return NEGATIVE_FEE_PER_KB_ERROR_CODE;
}

if(feePerKb.isGreaterThan(bridgeConstants.getMaxFeePerKb())) {
return EXCESSIVE_FEE_PER_KB_ERROR_CODE;
}

ABICallElection feePerKbElection = provider.getFeePerKbElection(authorizer);
ABICallSpec feeVote = new ABICallSpec("setFeePerKb", new byte[][]{BridgeSerializationUtils.serializeCoin(feePerKb)});
boolean successfulVote = feePerKbElection.vote(feeVote, tx.getSender(signatureCache));
if (!successfulVote) {
return -1;
}

Optional<ABICallSpec> winnerOptional = feePerKbElection.getWinner();
if (!winnerOptional.isPresent()) {
logger.info("Successful fee per kb vote for {}", feePerKb);
return 1;
}

ABICallSpec winner = winnerOptional.get();
Coin winnerFee;
try {
winnerFee = BridgeSerializationUtils.deserializeCoin(winner.getArguments()[0]);
} catch (Exception e) {
logger.warn("Exception deserializing winner feePerKb", e);
return FEE_PER_KB_GENERIC_ERROR_CODE;
}

if (winnerFee == null) {
logger.warn("Invalid winner feePerKb: feePerKb can't be null");
return FEE_PER_KB_GENERIC_ERROR_CODE;
}

if (!winnerFee.equals(feePerKb)) {
logger.debug("Winner fee is different than the last vote: maybe you forgot to clear winners");
}
public Coin getFeePerKb() {
return feePerKbSupport.getFeePerKb();
}

logger.info("Fee per kb changed to {}", winnerFee);
provider.setFeePerKb(winnerFee);
feePerKbElection.clear();
return 1;
public Integer voteFeePerKbChange(Transaction tx, Coin feePerKb) {
return feePerKbSupport.voteFeePerKbChange(tx, feePerKb, signatureCache);
}

/**
Expand Down
17 changes: 17 additions & 0 deletions rskj-core/src/main/java/co/rsk/peg/BridgeSupportFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
import co.rsk.core.RskAddress;
import co.rsk.peg.BtcBlockStoreWithCache.Factory;
import co.rsk.peg.btcLockSender.BtcLockSenderProvider;
import co.rsk.peg.feeperkb.FeePerKbStorageProvider;
import co.rsk.peg.feeperkb.FeePerKbSupport;
import co.rsk.peg.feeperkb.constants.FeePerKbConstants;
import co.rsk.peg.storage.StorageAccessor;
import co.rsk.peg.storage.BridgeStorageAccessorImpl;
import co.rsk.peg.feeperkb.FeePerKbStorageProviderImpl;
import co.rsk.peg.feeperkb.FeePerKbSupportImpl;
import co.rsk.peg.pegininstructions.PeginInstructionsProvider;
import co.rsk.peg.utils.BridgeEventLogger;
import co.rsk.peg.utils.BridgeEventLoggerImpl;
Expand Down Expand Up @@ -59,6 +66,8 @@ public BridgeSupport newInstance(Repository repository, Block executionBlock,
ActivationConfig.ForBlock activations = activationConfig.forBlock(executionBlock.getNumber());
Context btcContext = new Context(bridgeConstants.getBtcParams());

StorageAccessor bridgeStorageAccessor = new BridgeStorageAccessorImpl(repository);

BridgeStorageProvider provider = new BridgeStorageProvider(
repository,
contractAddress,
Expand All @@ -67,6 +76,7 @@ public BridgeSupport newInstance(Repository repository, Block executionBlock,
);

FederationSupport federationSupport = new FederationSupport(bridgeConstants, provider, executionBlock, activations);
FeePerKbSupport feePerKbSupport = newFeePerKbSupportInstance(bridgeStorageAccessor, bridgeConstants);

BridgeEventLogger eventLogger;
if (logs == null) {
Expand All @@ -92,9 +102,16 @@ public BridgeSupport newInstance(Repository repository, Block executionBlock,
executionBlock,
btcContext,
federationSupport,
feePerKbSupport,
btcBlockStoreFactory,
activations,
signatureCache
);
}

private FeePerKbSupport newFeePerKbSupportInstance(StorageAccessor bridgeStorageAccessor, BridgeConstants bridgeConstants) {
FeePerKbConstants feePerKbConstants = bridgeConstants.getFeePerKbConstants();
FeePerKbStorageProvider feePerKbStorageProvider = new FeePerKbStorageProviderImpl(bridgeStorageAccessor);
return new FeePerKbSupportImpl(feePerKbConstants, feePerKbStorageProvider);
}
}
27 changes: 17 additions & 10 deletions rskj-core/src/main/java/co/rsk/peg/BridgeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import co.rsk.peg.bitcoin.RskAllowUnconfirmedCoinSelector;
import co.rsk.peg.btcLockSender.BtcLockSender.TxSenderAddressType;
import co.rsk.peg.federation.Federation;
import co.rsk.peg.feeperkb.constants.FeePerKbConstants;
import co.rsk.peg.flyover.FlyoverTxResponseCodes;
import co.rsk.peg.utils.BtcTransactionFormatUtils;
import co.rsk.peg.vote.AddressBasedAuthorizer;
Expand Down Expand Up @@ -402,14 +403,20 @@ public static boolean isFreeBridgeTx(Transaction rskTx, Constants constants, Act
// must be the genesis federation.
// Once the original federation changes, txs are always paid.
return PrecompiledContracts.BRIDGE_ADDR.equals(receiveAddress) &&
!activations.isActive(ConsensusRule.ARE_BRIDGE_TXS_PAID) &&
rskTx.acceptTransactionSignature(constants.getChainId()) &&
(
isFromGenesisFederation(senderAddress, bridgeConstants.getGenesisFederationPublicKeys()) ||
isFromFederationChangeAuthorizedSender(rskTx, bridgeConstants, signatureCache) ||
isFromLockWhitelistChangeAuthorizedSender(rskTx, bridgeConstants, signatureCache) ||
isFromFeePerKbChangeAuthorizedSender(rskTx, bridgeConstants, signatureCache)
);
!activations.isActive(ConsensusRule.ARE_BRIDGE_TXS_PAID) &&
rskTx.acceptTransactionSignature(constants.getChainId()) &&
(
isFromGenesisFederation(senderAddress, bridgeConstants.getGenesisFederationPublicKeys()) ||
isFromAuthorizedSender(rskTx, bridgeConstants, signatureCache)
);
}

private static boolean isFromAuthorizedSender(Transaction rskTx, BridgeConstants bridgeConstants, SignatureCache signatureCache) {
FeePerKbConstants feePerKbConstants = bridgeConstants.getFeePerKbConstants();

return isFromFederationChangeAuthorizedSender(rskTx, bridgeConstants, signatureCache) ||
isFromLockWhitelistChangeAuthorizedSender(rskTx, bridgeConstants, signatureCache) ||
isFromFeePerKbChangeAuthorizedSender(rskTx, feePerKbConstants, signatureCache);
}

/**
Expand Down Expand Up @@ -462,8 +469,8 @@ private static boolean isFromLockWhitelistChangeAuthorizedSender(Transaction rsk
return authorizer.isAuthorized(rskTx, signatureCache);
}

private static boolean isFromFeePerKbChangeAuthorizedSender(Transaction rskTx, BridgeConstants bridgeConfiguration, SignatureCache signatureCache) {
AddressBasedAuthorizer authorizer = bridgeConfiguration.getFeePerKbChangeAuthorizer();
private static boolean isFromFeePerKbChangeAuthorizedSender(org.ethereum.core.Transaction rskTx, FeePerKbConstants feePerKbConstants, SignatureCache signatureCache) {
AddressBasedAuthorizer authorizer = feePerKbConstants.getFeePerKbChangeAuthorizer();
return authorizer.isAuthorized(rskTx, signatureCache);
}

Expand Down
18 changes: 7 additions & 11 deletions rskj-core/src/main/java/co/rsk/peg/constants/BridgeConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,20 @@
import co.rsk.peg.vote.AddressBasedAuthorizer;
import java.util.List;

import co.rsk.peg.feeperkb.constants.FeePerKbConstants;
import org.ethereum.config.blockchain.upgrades.ActivationConfig;
import org.ethereum.config.blockchain.upgrades.ConsensusRule;

import java.time.Instant;

public abstract class BridgeConstants {
protected String btcParamsString;

protected FeePerKbConstants feePerKbConstants;

protected List<BtcECKey> genesisFederationPublicKeys;
protected Instant genesisFederationCreationTime;

protected int btc2RskMinimumAcceptableConfirmations;
protected int btc2RskMinimumAcceptableConfirmationsOnRsk;
protected int rsk2BtcMinimumAcceptableConfirmations;
Expand All @@ -57,11 +62,6 @@ public abstract class BridgeConstants {

protected AddressBasedAuthorizer lockWhitelistChangeAuthorizer;

protected AddressBasedAuthorizer feePerKbChangeAuthorizer;

protected Coin genesisFeePerKb;
protected Coin maxFeePerKb;

protected AddressBasedAuthorizer increaseLockingCapAuthorizer;

protected Coin initialLockingCap;
Expand Down Expand Up @@ -92,6 +92,8 @@ public NetworkParameters getBtcParams() {
return NetworkParameters.fromID(btcParamsString);
}

public FeePerKbConstants getFeePerKbConstants() { return feePerKbConstants; }

public String getBtcParamsString() {
return btcParamsString;
}
Expand Down Expand Up @@ -148,18 +150,12 @@ public long getFundsMigrationAgeSinceActivationEnd(ActivationConfig.ForBlock act

public AddressBasedAuthorizer getLockWhitelistChangeAuthorizer() { return lockWhitelistChangeAuthorizer; }

public AddressBasedAuthorizer getFeePerKbChangeAuthorizer() { return feePerKbChangeAuthorizer; }

public AddressBasedAuthorizer getIncreaseLockingCapAuthorizer() { return increaseLockingCapAuthorizer; }

public int getLockingCapIncrementsMultiplier() { return lockingCapIncrementsMultiplier; }

public Coin getInitialLockingCap() { return initialLockingCap; }

public Coin getGenesisFeePerKb() { return genesisFeePerKb; }

public Coin getMaxFeePerKb() { return maxFeePerKb; }

public Coin getMaxRbtc() { return Coin.valueOf(21_000_000, 0); }

public int getBtcHeightWhenBlockIndexActivates() { return btcHeightWhenBlockIndexActivates; }
Expand Down
Loading

0 comments on commit 14cae37

Please sign in to comment.