diff --git a/abciapp/block_challenge.go b/abciapp/block_challenge.go index 9ad5656..0de34e3 100644 --- a/abciapp/block_challenge.go +++ b/abciapp/block_challenge.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "embed" + "errors" "math/big" "time" @@ -199,41 +200,48 @@ func (c *blockChallengeCoordinator) computeBlockChallengeProof(tx transaction.Re return buf.Bytes(), nil } -func (c *blockChallengeCoordinator) verifyBlockChallengeProof(height int64, validatorAddress []byte, proofBytes []byte) (bool, error) { +var bn254IDScalarField = bn254.ID.ScalarField() + +var errInvalidBlockChallengeProof = errors.New("invalid block challenge proof") + +func (c *blockChallengeCoordinator) verifyBlockChallengeProof(height int64, validatorAddress []byte, proofBytes []byte) error { // timestamp shouldn't matter for this // it is however important that we read the tree exactly as it was on the height prior to the one where the proof was supposedly generated // this is because operations can change over time (nullification) and also the returned data for the highest operation indexes will be different tx, err := c.txFactory.ReadHeight(time.Time{}, height-1) if err != nil { - return false, stacktrace.Propagate(err) + return stacktrace.Propagate(err) } sharedPart, err := c.fetchOrBuildBlockChallengeCircuitAssignmentShared(tx, height) if err != nil { - return false, stacktrace.Propagate(err) + return stacktrace.Propagate(err) } assignment := buildBlockChallengeCircuitAssignmentFull(sharedPart, validatorAddress) - witness, err := frontend.NewWitness(assignment, bn254.ID.ScalarField()) + witness, err := frontend.NewWitness(assignment, bn254IDScalarField) if err != nil { - return false, stacktrace.Propagate(err) + return stacktrace.Propagate(err) } publicWitness, err := witness.Public() if err != nil { - return false, stacktrace.Propagate(err) + return stacktrace.Propagate(err) } proof := groth16.NewProof(bn254.ID) _, err = proof.ReadFrom(bytes.NewBuffer(proofBytes)) if err != nil { - return false, stacktrace.Propagate(err) + return stacktrace.Propagate(errors.Join(errInvalidBlockChallengeProof, err)) } err = groth16.Verify(proof, blockChallengeVerifyingKey, publicWitness) - return err == nil, nil + if err != nil { + return stacktrace.Propagate(errors.Join(errInvalidBlockChallengeProof, err)) + } + return nil } func (c *blockChallengeCoordinator) buildPrivateChallengeWitnessForHeight(tx transaction.Read, height int64) (witness.Witness, error) { @@ -244,7 +252,7 @@ func (c *blockChallengeCoordinator) buildPrivateChallengeWitnessForHeight(tx tra assignment := buildBlockChallengeCircuitAssignmentFull(sharedPart, c.validatorAddress) - witness, err := frontend.NewWitness(assignment, bn254.ID.ScalarField()) + witness, err := frontend.NewWitness(assignment, bn254IDScalarField) return witness, stacktrace.Propagate(err) } @@ -258,7 +266,7 @@ func (c *blockChallengeCoordinator) blockChallengeOperationDataForHeight(tx tran return nil, nil, stacktrace.Propagate(err) } lastCommitHash := blockHeader.LastCommitHash - lastCommitHashBigInt := big.NewInt(0).SetBytes(lastCommitHash) + lastCommitHashBigInt := new(big.Int).SetBytes(lastCommitHash) highestOp, err := tx.CountOperations() if err != nil { @@ -269,7 +277,7 @@ func (c *blockChallengeCoordinator) blockChallengeOperationDataForHeight(tx tran operationData := make([]byte, initialOpDataLen) operationDataCursor := 0 if highestOp > 0 { - startOpIdxBigInt := big.NewInt(0).Mod(lastCommitHashBigInt, big.NewInt(0).SetUint64(highestOp-1)) + startOpIdxBigInt := new(big.Int).Mod(lastCommitHashBigInt, new(big.Int).SetUint64(highestOp-1)) startOpIdx := startOpIdxBigInt.Uint64() // the starting operation sequence is startOpIdx+1 // because operations sequences start at 1 but the result of the modulus is (0, n( diff --git a/abciapp/execution.go b/abciapp/execution.go index 2e90d88..3d702e0 100644 --- a/abciapp/execution.go +++ b/abciapp/execution.go @@ -251,13 +251,17 @@ func (d *DIDPLCApplication) VerifyVoteExtension(_ context.Context, req *abcitype }, nil } - proofOK, err := d.blockChallengeCoordinator.verifyBlockChallengeProof(req.Height, req.ValidatorAddress, req.VoteExtension) - if err != nil { + err := d.blockChallengeCoordinator.verifyBlockChallengeProof(req.Height, req.ValidatorAddress, req.VoteExtension) + if errors.Is(err, errInvalidBlockChallengeProof) { + return &abcitypes.ResponseVerifyVoteExtension{ + Status: abcitypes.ResponseVerifyVoteExtension_REJECT, + }, nil + } else if err != nil { return nil, stacktrace.Propagate(err) } return &abcitypes.ResponseVerifyVoteExtension{ - Status: lo.Ternary(proofOK, abcitypes.ResponseVerifyVoteExtension_ACCEPT, abcitypes.ResponseVerifyVoteExtension_REJECT), + Status: abcitypes.ResponseVerifyVoteExtension_ACCEPT, }, nil } diff --git a/abciapp/tx_challenge.go b/abciapp/tx_challenge.go index 1822df3..c6d0a10 100644 --- a/abciapp/tx_challenge.go +++ b/abciapp/tx_challenge.go @@ -17,7 +17,7 @@ import ( var TransactionActionCommitToChallenge = registerTransactionAction[CommitToChallengeArguments]("CommitToChallenge", processCommitToChallengeTx) const CommitToChallengeMaxAgeInBlocks = 3 -const CommitToChallengeMinRange = 1000 +const CommitToChallengeMinRange = 1950 const CommitToChallengeMaxRange = 5000 const CommitToChallengeTargetInterval = 2000 @@ -159,15 +159,14 @@ func processCommitToChallengeTx(ctx context.Context, deps TransactionProcessorDe }, nil } - blockProofValid, err := deps.blockChallengeCoordinator.verifyBlockChallengeProof(int64(proofHeight), validatorPubKey.Address(), existenceProof.Value) - if err != nil { - return nil, stacktrace.Propagate(err) - } - if !blockProofValid { + err = deps.blockChallengeCoordinator.verifyBlockChallengeProof(int64(proofHeight), validatorPubKey.Address(), existenceProof.Value) + if errors.Is(err, errInvalidBlockChallengeProof) { return &processResult{ Code: 4211, Log: "invalid proof", }, nil + } else if err != nil { + return nil, stacktrace.Propagate(err) } if !ics23.VerifyMembership(ics23.IavlSpec, tx.Arguments.Root, proof, existenceProof.Key, existenceProof.Value) { @@ -298,15 +297,14 @@ func processCompleteChallengeTx(ctx context.Context, deps TransactionProcessorDe }, nil } - blockProofValid, err := deps.blockChallengeCoordinator.verifyBlockChallengeProof(int64(proofHeight), pubKey.Address(), existenceProof.Value) - if err != nil { - return nil, stacktrace.Propagate(err) - } - if !blockProofValid { + err = deps.blockChallengeCoordinator.verifyBlockChallengeProof(int64(proofHeight), pubKey.Address(), existenceProof.Value) + if errors.Is(err, errInvalidBlockChallengeProof) { return &processResult{ Code: 4307, Log: "invalid proof", }, nil + } else if err != nil { + return nil, stacktrace.Propagate(err) } if !ics23.VerifyMembership(ics23.IavlSpec, committedTreeRoot, proof, existenceProof.Key, existenceProof.Value) {