Skip to content

Commit

Permalink
Merge pull request #2247 from rsksmart/rsk-address-from-rsk-key-integ…
Browse files Browse the repository at this point in the history
…ration

RskAddress derives properly from rsk key
  • Loading branch information
josedahlquist authored Feb 16, 2024
2 parents d09648f + c8d41fe commit 6cb7531
Show file tree
Hide file tree
Showing 27 changed files with 708 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ public void setPegoutTxSigHash(Sha256Hash sigHash) {
pegoutTxSigHashes.add(sigHash);
}

private void savePegoutTxSigHashes() {
protected void savePegoutTxSigHashes() {
if (!activations.isActive(RSKIP379) || pegoutTxSigHashes == null) {
return;
}
Expand Down
34 changes: 23 additions & 11 deletions rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -1428,13 +1428,23 @@ public void addSignature(BtcECKey federatorPublicKey, List<byte[]> signatures, b
Optional<Federation> optionalFederation = getFederationFromPublicKey(federatorPublicKey);
if (!optionalFederation.isPresent()) {
logger.warn(
"Supplied federator public key {} does not belong to any of the federators.",
"[addSignature] Supplied federator btc public key {} does not belong to any of the federators.",
federatorPublicKey
);
return;
}

Federation federation = optionalFederation.get();
Optional<FederationMember> federationMember = federation.getMemberByBtcPublicKey(federatorPublicKey);
if (!federationMember.isPresent()){
logger.warn(
"[addSignature] Supplied federator btc public key {} doest not match any of the federator member btc public keys {}.",
federatorPublicKey, federation.getBtcPublicKeys()
);
return;
}
FederationMember signingFederationMember = federationMember.get();

BtcTransaction btcTx = provider.getPegoutsWaitingForSignatures().get(new Keccak256(rskTxHash));
if (btcTx == null) {
logger.warn(
Expand All @@ -1453,10 +1463,10 @@ public void addSignature(BtcECKey federatorPublicKey, List<byte[]> signatures, b
}

if (!activations.isActive(ConsensusRule.RSKIP326)) {
eventLogger.logAddSignature(federatorPublicKey, btcTx, rskTxHash);
eventLogger.logAddSignature(signingFederationMember, btcTx, rskTxHash);
}

processSigning(federatorPublicKey, signatures, rskTxHash, btcTx, federation);
processSigning(signingFederationMember, signatures, rskTxHash, btcTx, federation);
}

private Optional<Federation> getFederationFromPublicKey(BtcECKey federatorPublicKey) {
Expand All @@ -1474,11 +1484,13 @@ private Optional<Federation> getFederationFromPublicKey(BtcECKey federatorPublic
}

private void processSigning(
BtcECKey federatorPublicKey,
FederationMember federatorMember,
List<byte[]> signatures,
byte[] rskTxHash,
BtcTransaction btcTx,
Federation federation) throws IOException {

BtcECKey federatorBtcPublicKey = federatorMember.getBtcPublicKey();
// Build input hashes for signatures
int numInputs = btcTx.getInputs().size();

Expand Down Expand Up @@ -1510,13 +1522,13 @@ private void processSigning(

Sha256Hash sighash = sighashes.get(i);

if (!federatorPublicKey.verify(sighash, sig)) {
if (!federatorBtcPublicKey.verify(sighash, sig)) {
logger.warn(
"Signature {} {} is not valid for hash {} and public key {}",
i,
ByteUtil.toHexString(sig.encodeToDER()),
sighash,
federatorPublicKey
federatorBtcPublicKey
);
return;
}
Expand All @@ -1538,24 +1550,24 @@ private void processSigning(
Script inputScript = input.getScriptSig();

boolean alreadySignedByThisFederator = BridgeUtils.isInputSignedByThisFederator(
federatorPublicKey,
federatorBtcPublicKey,
sighash,
input);

// Sign the input if it wasn't already
if (!alreadySignedByThisFederator) {
try {
int sigIndex = inputScript.getSigInsertionIndex(sighash, federatorPublicKey);
int sigIndex = inputScript.getSigInsertionIndex(sighash, federatorBtcPublicKey);
inputScript = ScriptBuilder.updateScriptWithSignature(inputScript, txSigs.get(i).encodeToBitcoin(), sigIndex, 1, 1);
input.setScriptSig(inputScript);
logger.debug("Tx input {} for tx {} signed.", i, new Keccak256(rskTxHash));
signed = true;
} catch (IllegalStateException e) {
Federation retiringFederation = getRetiringFederation();
if (getActiveFederation().hasBtcPublicKey(federatorPublicKey)) {
if (getActiveFederation().hasBtcPublicKey(federatorBtcPublicKey)) {
logger.debug("A member of the active federation is trying to sign a tx of the retiring one");
return;
} else if (retiringFederation != null && retiringFederation.hasBtcPublicKey(federatorPublicKey)) {
} else if (retiringFederation != null && retiringFederation.hasBtcPublicKey(federatorBtcPublicKey)) {
logger.debug("A member of the retiring federation is trying to sign a tx of the active one");
return;
}
Expand All @@ -1568,7 +1580,7 @@ private void processSigning(
}

if(signed && activations.isActive(ConsensusRule.RSKIP326)) {
eventLogger.logAddSignature(federatorPublicKey, btcTx, rskTxHash);
eventLogger.logAddSignature(federatorMember, btcTx, rskTxHash);
}

if (BridgeUtils.hasEnoughSignatures(btcContext, btcTx)) {
Expand Down
8 changes: 8 additions & 0 deletions rskj-core/src/main/java/co/rsk/peg/Federation.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ public List<FederationMember> getMembers() {
return members;
}

public Optional<FederationMember> getMemberByBtcPublicKey(BtcECKey btcPublicKey) {
if (btcPublicKey == null){
return Optional.empty();
}
final BtcECKey btcPublicKeyOnly = BtcECKey.fromPublicOnly(btcPublicKey.getPubKey());
return members.stream().filter(federationMember -> federationMember.getBtcPublicKey().equals(btcPublicKeyOnly)).findAny();
}

public List<BtcECKey> getBtcPublicKeys() {
// Copy instances since we don't control
// immutability of BtcECKey instances
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import co.rsk.core.RskAddress;
import co.rsk.crypto.Keccak256;
import co.rsk.peg.Federation;
import co.rsk.peg.FederationMember;
import co.rsk.peg.pegin.RejectedPeginReason;
import org.ethereum.core.Block;
import org.ethereum.core.Transaction;
Expand All @@ -36,7 +37,7 @@ public interface BridgeEventLogger {

void logUpdateCollections(Transaction rskTx);

void logAddSignature(BtcECKey federatorPublicKey, BtcTransaction btcTx, byte[] rskTxHash);
void logAddSignature(FederationMember federationMember, BtcTransaction btcTx, byte[] rskTxHash);

void logReleaseBtc(BtcTransaction btcTx, byte[] rskTxHash);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import co.rsk.crypto.Keccak256;
import co.rsk.peg.BridgeEvents;
import co.rsk.peg.Federation;
import co.rsk.peg.FederationMember;
import co.rsk.peg.pegin.RejectedPeginReason;
import org.ethereum.config.blockchain.upgrades.ActivationConfig;
import org.ethereum.config.blockchain.upgrades.ConsensusRule;
Expand Down Expand Up @@ -75,10 +76,22 @@ public void logUpdateCollections(Transaction rskTx) {
}

@Override
public void logAddSignature(BtcECKey federatorPublicKey, BtcTransaction btcTx, byte[] rskTxHash) {
ECKey key = ECKey.fromPublicOnly(federatorPublicKey.getPubKey());
String federatorRskAddress = ByteUtil.toHexString(key.getAddress());
logAddSignatureInSolidityFormat(rskTxHash, federatorRskAddress, federatorPublicKey);
public void logAddSignature(FederationMember federationMember, BtcTransaction btcTx, byte[] rskTxHash) {
ECKey federatorPublicKey = getFederatorPublicKey(federationMember);
String federatorRskAddress = ByteUtil.toHexString(federatorPublicKey.getAddress());
logAddSignatureInSolidityFormat(rskTxHash, federatorRskAddress, federationMember.getBtcPublicKey());
}

private ECKey getFederatorPublicKey(FederationMember federationMember) {
if (!shouldUseRskPublicKey()) {
return ECKey.fromPublicOnly(federationMember.getBtcPublicKey().getPubKey());
}

return federationMember.getRskPublicKey();
}

private boolean shouldUseRskPublicKey() {
return activations.isActive(ConsensusRule.RSKIP415);
}

private void logAddSignatureInSolidityFormat(byte[] rskTxHash, String federatorRskAddress, BtcECKey federatorPublicKey) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import co.rsk.peg.Bridge;
import co.rsk.peg.DeprecatedMethodCallException;
import co.rsk.peg.Federation;
import co.rsk.peg.FederationMember;
import org.ethereum.config.blockchain.upgrades.ActivationConfig;
import org.ethereum.config.blockchain.upgrades.ConsensusRule;
import org.ethereum.core.Block;
Expand Down Expand Up @@ -77,15 +78,15 @@ public void logUpdateCollections(Transaction rskTx) {
}

@Override
public void logAddSignature(BtcECKey federatorPublicKey, BtcTransaction btcTx, byte[] rskTxHash) {
public void logAddSignature(FederationMember federationMember, BtcTransaction btcTx, byte[] rskTxHash) {
if (activations.isActive(ConsensusRule.RSKIP146)) {
throw new DeprecatedMethodCallException(
"Calling BrigeEventLoggerLegacyImpl.logAddSignature method after RSKIP146 activation"
);
}
List<DataWord> topics = Collections.singletonList(Bridge.ADD_SIGNATURE_TOPIC);
byte[] data = RLP.encodeList(RLP.encodeString(btcTx.getHashAsString()),
RLP.encodeElement(federatorPublicKey.getPubKeyHash()),
RLP.encodeElement(federationMember.getBtcPublicKey().getPubKeyHash()),
RLP.encodeElement(rskTxHash));

this.logs.add(new LogInfo(BRIDGE_CONTRACT_ADDRESS, topics, data));
Expand Down
51 changes: 35 additions & 16 deletions rskj-core/src/main/java/co/rsk/remasc/Remasc.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@

package co.rsk.remasc;

import co.rsk.config.BridgeConstants;
import co.rsk.config.RemascConfig;
import co.rsk.core.Coin;
import co.rsk.core.RskAddress;
import co.rsk.core.bc.SelectionRule;
import co.rsk.peg.BridgeStorageProvider;
import co.rsk.peg.FederationSupport;
import co.rsk.rpc.modules.trace.ProgramSubtrace;
import org.ethereum.config.Constants;
import org.ethereum.config.blockchain.upgrades.ActivationConfig;
Expand All @@ -32,6 +35,7 @@
import org.ethereum.core.Transaction;
import org.ethereum.db.BlockStore;
import org.ethereum.vm.LogInfo;
import org.ethereum.vm.PrecompiledContracts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -47,7 +51,7 @@ public class Remasc {
private static final Logger logger = LoggerFactory.getLogger(Remasc.class);

private final Constants constants;
private final ActivationConfig activationConfig;
private final ActivationConfig.ForBlock activations;
private final Repository repository;
private final BlockStore blockStore;
private final RemascConfig remascConstants;
Expand Down Expand Up @@ -78,7 +82,7 @@ public Remasc(
this.provider = new RemascStorageProvider(repository, contractAddress);
this.feesPayer = new RemascFeesPayer(repository, contractAddress);
this.constants = constants;
this.activationConfig = activationConfig;
this.activations = activationConfig.forBlock(executionBlock.getNumber());
}

public void save() {
Expand Down Expand Up @@ -109,11 +113,11 @@ void processMinersFees() {
throw new RemascInvalidInvocationException("Invoked Remasc outside last tx of the block");
}

long blockNbr = executionBlock.getNumber();
long executionBlockNumber = executionBlock.getNumber();

long processingBlockNumber = blockNbr - remascConstants.getMaturity();
if (processingBlockNumber < 1 ) {
logger.debug("First block has not reached maturity yet, current block is {}", blockNbr);
long candidateBlockNumberToReward = executionBlockNumber - remascConstants.getMaturity();
if (candidateBlockNumberToReward < 1 ) {
logger.debug("First block has not reached maturity yet, current block is {}", executionBlockNumber);
return;
}

Expand Down Expand Up @@ -145,20 +149,20 @@ void processMinersFees() {
rewardBalance = rewardBalance.add(processingBlockReward);
provider.setRewardBalance(rewardBalance);

if (processingBlockNumber - remascConstants.getSyntheticSpan() < 0 ) {
if (candidateBlockNumberToReward - remascConstants.getSyntheticSpan() < 0 ) {
logger.debug("First block has not reached maturity+syntheticSpan yet, current block is {}", executionBlock.getNumber());
return;
}

List<Sibling> siblings = getSiblingsToReward(descendantsBlocks, processingBlockNumber);
List<Sibling> siblings = getSiblingsToReward(descendantsBlocks, candidateBlockNumberToReward);
boolean previousBrokenSelectionRule = provider.getBrokenSelectionRule();
boolean brokenSelectionRule = SelectionRule.isBrokenSelectionRule(processingBlockHeader, siblings);
provider.setBrokenSelectionRule(!siblings.isEmpty() && brokenSelectionRule);

// Takes from rewardBalance this block's height reward.
Coin syntheticReward = rewardBalance.divide(BigInteger.valueOf(remascConstants.getSyntheticSpan()));
boolean isRskip85Enabled = activationConfig.isActive(ConsensusRule.RSKIP85, blockNbr);
if (isRskip85Enabled) {

if (shouldRewardBeAboveMinimumPayableGas()) {
BigInteger minimumPayableGas = constants.getMinimumPayableGas();
Coin minPayableFees = executionBlock.getMinimumGasPrice().multiply(minimumPayableGas);
if (syntheticReward.compareTo(minPayableFees) < 0) {
Expand All @@ -176,7 +180,7 @@ void processMinersFees() {
Coin payToRskLabs = syntheticReward.divide(BigInteger.valueOf(remascConstants.getRskLabsDivisor()));
feesPayer.payMiningFees(processingBlockHeader.getHash().getBytes(), payToRskLabs, rskLabsAddress, logs);
syntheticReward = syntheticReward.subtract(payToRskLabs);
Coin payToFederation = payToFederation(constants, isRskip85Enabled, processingBlock, processingBlockHeader, syntheticReward);
Coin payToFederation = payToFederation(constants, processingBlock, syntheticReward);
syntheticReward = syntheticReward.subtract(payToFederation);

if (!siblings.isEmpty()) {
Expand All @@ -193,23 +197,38 @@ void processMinersFees() {
}
}

private boolean shouldRewardBeAboveMinimumPayableGas() {
return activations.isActive(ConsensusRule.RSKIP85);
}

RskAddress getRskLabsAddress() {
boolean isRskip218Enabled = activationConfig.isActive(ConsensusRule.RSKIP218, executionBlock.getNumber());
boolean isRskip218Enabled = activations.isActive(ConsensusRule.RSKIP218);
return isRskip218Enabled ? remascConstants.getRskLabsAddressRskip218() : remascConstants.getRskLabsAddress();
}

private Coin payToFederation(Constants constants, boolean isRskip85Enabled, Block processingBlock, BlockHeader processingBlockHeader, Coin syntheticReward) {
RemascFederationProvider federationProvider = new RemascFederationProvider(activationConfig, constants.getBridgeConstants(), repository, processingBlock);
private Coin payToFederation(Constants constants, Block processingBlock, Coin syntheticReward) {
BridgeConstants bridgeConstants = constants.getBridgeConstants();

BridgeStorageProvider bridgeStorageProvider = new BridgeStorageProvider(
repository,
PrecompiledContracts.BRIDGE_ADDR,
bridgeConstants,
activations
);

FederationSupport federationSupport = new FederationSupport(bridgeConstants, bridgeStorageProvider, processingBlock, activations);

RemascFederationProvider federationProvider = new RemascFederationProvider(activations, federationSupport);
Coin federationReward = syntheticReward.divide(BigInteger.valueOf(remascConstants.getFederationDivisor()));

Coin payToFederation = provider.getFederationBalance().add(federationReward);
byte[] processingBlockHash = processingBlockHeader.getHash().getBytes();
byte[] processingBlockHash = processingBlock.getHeader().getHash().getBytes();
int nfederators = federationProvider.getFederationSize();
Coin[] payAndRemainderToFederator = payToFederation.divideAndRemainder(BigInteger.valueOf(nfederators));
Coin payToFederator = payAndRemainderToFederator[0];
Coin restToLastFederator = payAndRemainderToFederator[1];

if (isRskip85Enabled) {
if (shouldRewardBeAboveMinimumPayableGas()) {
BigInteger minimumFederatorPayableGas = constants.getFederatorMinimumPayableGas();
Coin minPayableFederatorFees = executionBlock.getMinimumGasPrice().multiply(minimumFederatorPayableGas);
if (payToFederator.compareTo(minPayableFederatorFees) < 0) {
Expand Down
Loading

0 comments on commit 6cb7531

Please sign in to comment.