Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add svp spend tx signature #2804

Merged

Conversation

julia-zack
Copy link
Contributor

For the validation protocol to be successful, we need the spend transaction to be signed and broadcasted by the proposed pegnatories.

Requirements
-Create a new addSvpSpendTxSignature method that would add the signatures from the proposed pegnatories to the svp spend transaction.

This method should also remove the spend transaction from the map once is fully signed, and emit the release_btc event so the federators can proceed with the broadcast.

return;
}

addReleaseSignatures(federatorBtcPublicKey, signatures, rskTxHash, releaseTx);
}

private boolean hasEnoughSignatures(BtcTransaction releaseTx, List<byte[]> signatures) {
private boolean areSignaturesEnoughToSignAllTxInputs(BtcTransaction releaseTx, List<byte[]> signatures) {
Copy link
Contributor Author

@julia-zack julia-zack Oct 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method name was change to be distinguishable from BridgeUtils method thats also being used

@julia-zack julia-zack marked this pull request as ready for review October 14, 2024 20:25
@julia-zack julia-zack requested a review from a team as a code owner October 14, 2024 20:25
Copy link
Contributor

@marcos-iov marcos-iov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking nice and clean, well done!

rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java Outdated Show resolved Hide resolved
rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java Outdated Show resolved Hide resolved
rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java Outdated Show resolved Hide resolved
rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java Outdated Show resolved Hide resolved
rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java Outdated Show resolved Hide resolved
@@ -1578,19 +1578,32 @@ public void addSignature(BtcECKey federatorBtcPublicKey, List<byte[]> signatures

Context.propagate(btcContext);

if (svpIsOngoing()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could wrap everything in a single svp method?

if (svpIsOngoing()) {
    addSignatureForSvp();
   return;
} 
...
// Normal addSignature logic

To keep simple and focused, while at the same time re-using addSignature method. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @marcos-iov 's proposal. I think separating these two logic into two methods makes much sense.

Copy link
Contributor Author

@julia-zack julia-zack Oct 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that way you won't sign a normal pegout when svp is ongoing, right?

Copy link
Contributor Author

@julia-zack julia-zack Oct 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought about doing something like that with a continue instead of a return, but i discarded it since (correct me if im wrong) it will make the flow continue after signing the spend tx.
Anyways doing that is no big deal, because it will return early enough here

Comment on lines 1585 to 1603
logger.trace("Going to add federator public key {} to svp spend transaction", federatorBtcPublicKey);
BtcTransaction svpSpendTx = svpSpendTxWFS.getValue();
if (!areSignaturesEnoughToSignAllTxInputs(svpSpendTx, signatures)) {
return;
}
addSvpSpendTxSignatures(federatorBtcPublicKey, signatures, rskTxHash, svpSpendTx);
});
}

BtcTransaction releaseTx = provider.getPegoutsWaitingForSignatures().get(rskTxHash);
if (releaseTx == null) {
logger.warn("No tx waiting for signature for hash {}. Probably fully signed already.", rskTxHash);
return;
}
if (!hasEnoughSignatures(releaseTx, signatures)) {
if (!areSignaturesEnoughToSignAllTxInputs(releaseTx, signatures)) {
return;
}

addReleaseSignatures(federatorBtcPublicKey, signatures, rskTxHash, releaseTx);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this whole block can be moved into its own method. Wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure, i think it makes more sense this way. If we move this block, we wont be doing much in addSignature method right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is the method name expresses by itself what you doing in those lines of code and your functional code looks more elegant. See this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also , see this one:

return Stream.iterate(0, i -> i + 1)
            .limit(btcTx.getInputs().size())
            .map(i -> generateSigHashForP2SHTransactionInput(btcTx, i))
            .collect(Collectors.toList());
            

The method generateSigHashForP2SHTransactionInput abstracts the block of code on how to generate the sig hash. You can do the same thing by abstracting how the signatures are added.

rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java Outdated Show resolved Hide resolved
return sigHashes;
}

public static List<byte[]> generateSignerEncodedSignatures(BtcECKey signingKey, List<Sha256Hash> sigHashes) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static List<byte[]> generateSignerEncodedSignatures(BtcECKey signingKey, List<Sha256Hash> sigHashes) {
public static List<byte[]> signInputSigHashes(BtcECKey signingKey, List<Sha256Hash> sigHashes) {

I would prefer this name. Wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmmm

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This process(sign a transaction) is called and known as "signing" not generating.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but im not just signing, i want the list of the encoded signatures.

// act & assert
for (BtcECKey key : wrongKeys) {
List<byte[]> signerEncodedSignatures = generateSignerEncodedSignatures(key, svpSpendTxSigHashes);
assertThrows(IllegalStateException.class,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please assert the exception message as well.


BtcTransaction releaseTx = provider.getPegoutsWaitingForSignatures().get(releaseCreationRskTxHash);
if (releaseTx == null) {
logger.warn("No tx waiting for signature for hash {}. Probably fully signed already.", releaseCreationRskTxHash);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

method name missing in the log :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

return;
}
if (!areSignaturesEnoughToSignAllTxInputs(releaseTx, signatures)) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe log this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is being logged :)

logger.warn("Expected {} signatures but received {}.", inputsSize, signaturesSize);

BtcTransaction svpSpendTx = svpSpendTxWFS.getValue();

if (!areSignaturesEnoughToSignAllTxInputs(svpSpendTx, signatures)) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

}
if (!hasEnoughSignatures(releaseTx, signatures)) {
if (svpIsOngoing() && isSvpSpendTx(releaseCreationRskTxHash)) {
addSvpSpendTxSignatures(federatorBtcPublicKey, signatures);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we maybe log going to sign svp spend tx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my badddd, deleted it when refactored

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

) {
Federation proposedFederation = federationSupport.getProposedFederation()
// This flow should never be reached. There should always be a proposed federation if svpIsOngoing.
.orElseThrow(() -> new IllegalStateException("Proposed federation must exist when trying to sign the svp spend transaction."));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the one below could also be logged, but not sure. Maybe the Bridge catches this exception and logs it? If that's the case then we are probably good

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! It does

logger.warn("Exception in addSignature", e);

int signaturesSize = signatures.size();

if (inputsSize != signaturesSize) {
logger.warn("Expected {} signatures but received {}.", inputsSize, signaturesSize);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

method name :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@@ -1762,7 +1807,7 @@ private boolean sign(
BridgeUtils.isInputSignedByThisFederator(federatorBtcPublicKey, sigHash, input);

if (alreadySignedByThisFederator) {
logger.warn("Input {} of tx {} already signed by this federator.", i, rskTxHash);
logger.warn("Input {} of tx {} already signed by this federator.", i, releaseCreationRskTxHash);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@@ -1778,7 +1823,7 @@ private boolean sign(

Script inputScriptWithSignature = outputScript.getScriptSigWithSignature(inputScript, txSigs.get(i).encodeToBitcoin(), sigIndex);
input.setScriptSig(inputScriptWithSignature);
logger.debug("Tx input {} for tx {} signed.", i, rskTxHash);
logger.debug("Tx input {} for tx {} signed.", i, releaseCreationRskTxHash);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Copy link

@marcos-iov marcos-iov merged commit 4ab88bb into feature/powpeg_validation_protocol-phase3 Oct 16, 2024
7 checks passed
@marcos-iov marcos-iov deleted the add_spend_tx_signature branch October 16, 2024 18:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants