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

Aggregate sig #1362

Open
wants to merge 14 commits into
base: sprint-1.12
Choose a base branch
from
24 changes: 20 additions & 4 deletions code/go/0chain.net/blobbercore/challenge/challenge.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"
"time"

"github.com/0chain/blobber/code/go/0chain.net/core/encryption"
"github.com/0chain/blobber/code/go/0chain.net/core/node"

"github.com/0chain/blobber/code/go/0chain.net/blobbercore/config"
Expand Down Expand Up @@ -195,12 +196,27 @@ func (c *ChallengeEntity) getCommitTransaction(ctx context.Context) (*transactio

sn := &ChallengeResponse{}
sn.ChallengeID = c.ChallengeID
for _, vt := range c.ValidationTickets {
if vt != nil {
sn.ValidationTickets = append(sn.ValidationTickets, vt)
if c.RoundCreatedAt >= hardForkRound {
signatures := make([]string, 0, len(c.ValidationTickets))
for _, vt := range c.ValidationTickets {
if vt != nil && vt.Result {
sn.ValidationTickets = append(sn.ValidationTickets, vt)
signatures = append(signatures, vt.Signature)
}
}
sn.AggregatedSignature, err = encryption.AggregateSig(signatures)
if err != nil {
logging.Logger.Error("[challenge]aggregateSig", zap.Error(err))
c.CancelChallenge(ctx, err)
return nil, nil
}
} else {
for _, vt := range c.ValidationTickets {
if vt != nil {
sn.ValidationTickets = append(sn.ValidationTickets, vt)
}
}
}

err = txn.ExecuteSmartContract(transaction.STORAGE_CONTRACT_ADDRESS, transaction.CHALLENGE_RESPONSE, sn, 0)
if err != nil {
logging.Logger.Info("Failed submitting challenge to the mining network", zap.String("err:", err.Error()))
Expand Down
9 changes: 7 additions & 2 deletions code/go/0chain.net/blobbercore/challenge/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,13 @@ type ValidationTicket struct {
Signature string `json:"signature"`
}

func (vt *ValidationTicket) VerifySign() (bool, error) {
hashData := fmt.Sprintf("%v:%v:%v:%v:%v:%v", vt.ChallengeID, vt.BlobberID, vt.ValidatorID, vt.ValidatorKey, vt.Result, vt.Timestamp)
func (vt *ValidationTicket) VerifySign(round int64) (bool, error) {
var hashData string
if round >= hardForkRound {
hashData = fmt.Sprintf("%v:%v:%v:%v", vt.ChallengeID, vt.BlobberID, vt.Result, vt.Timestamp)
} else {
hashData = fmt.Sprintf("%v:%v:%v:%v:%v:%v", vt.ChallengeID, vt.BlobberID, vt.ValidatorID, vt.ValidatorKey, vt.Result, vt.Timestamp)
}
hash := encryption.Hash(hashData)
verified, err := encryption.Verify(vt.ValidatorKey, vt.Signature, hash)
return verified, err
Expand Down
15 changes: 8 additions & 7 deletions code/go/0chain.net/blobbercore/challenge/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ var (
)

type ChallengeResponse struct {
ChallengeID string `json:"challenge_id"`
ValidationTickets []*ValidationTicket `json:"validation_tickets"`
ChallengeID string `json:"challenge_id"`
ValidationTickets []*ValidationTicket `json:"validation_tickets"`
AggregatedSignature string `json:"aggregated_signature"`
}

func (cr *ChallengeEntity) CancelChallenge(ctx context.Context, errReason error) {
Expand Down Expand Up @@ -291,18 +292,18 @@ func (cr *ChallengeEntity) LoadValidationTickets(ctx context.Context) error {
zap.Any("numFailed", numFailed),
)

verified, err := validationTicket.VerifySign()
if err != nil || !verified {
verified, err := validationTicket.VerifySign(cr.RoundCreatedAt)
if err != nil || !verified || !validationTicket.Result {
numFailed++
logging.Logger.Error(
"[challenge]ticket: Validation ticket from validator could not be verified.",
zap.String("validator", validatorID),
zap.String("validator_response", validationTicket.Message),
)
updateMapAndSlice(validatorID, i, nil)
return
}
updateMapAndSlice(validatorID, i, &validationTicket)

numSuccess++
}(url, validator.ID, i)
}
Expand Down Expand Up @@ -373,7 +374,7 @@ func (cr *ChallengeEntity) VerifyChallengeTransaction(ctx context.Context, txn *
_ = cr.Save(ctx)
return err
}
logging.Logger.Info("Success response from BC for challenge response transaction", zap.String("txn", txn.TransactionOutput), zap.String("challenge_id", cr.ChallengeID))
logging.Logger.Info("Success response from BC for challenge response transaction", zap.String("txn", txn.Hash), zap.String("challenge_id", cr.ChallengeID))
cr.SaveChallengeResult(ctx, t, true)
return nil
}
Expand All @@ -383,7 +384,7 @@ func IsValueNotPresentError(err error) bool {
}

func IsEntityNotFoundError(err error) bool {
return strings.Contains(err.Error(), EntityNotFound)
return strings.Contains(err.Error(), EntityNotFound) || strings.Contains(err.Error(), "not present") || strings.Contains(err.Error(), "invalid challenge response")
}

func (cr *ChallengeEntity) SaveChallengeResult(ctx context.Context, t *transaction.Transaction, toAdd bool) {
Expand Down
22 changes: 19 additions & 3 deletions code/go/0chain.net/blobbercore/challenge/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package challenge

import (
"context"
"math"
"sync"
"time"

Expand All @@ -17,6 +18,9 @@ import (
)

const GetRoundInterval = 3 * time.Minute
const HARDFORK_NAME = "hard_fork_2"

var hardForkRound int64 = math.MaxInt64

type TodoChallenge struct {
Id string
Expand Down Expand Up @@ -72,6 +76,7 @@ func startPullWorker(ctx context.Context) {

func startWorkers(ctx context.Context) {
setRound()
setHardFork()
go getRoundWorker(ctx)

// start challenge listeners
Expand All @@ -82,18 +87,25 @@ func startWorkers(ctx context.Context) {

func getRoundWorker(ctx context.Context) {
ticker := time.NewTicker(GetRoundInterval)

for {
select {
case <-ctx.Done():
ticker.Stop()
return
case <-ticker.C:
setRound()
setHardFork()
}
}
}

func setHardFork() {
if hardForkRound == math.MaxInt64 {
hardForkRound, _ = zcncore.GetHardForkRound(HARDFORK_NAME)
logging.Logger.Info("hard_fork_round", zap.Any("round", hardForkRound))
}
}

func setRound() {
currentRound, _ := zcncore.GetRoundFromSharders()

Expand Down Expand Up @@ -178,8 +190,8 @@ func commitOnChainWorker(ctx context.Context) {
continue
}

logging.Logger.Info("committing_challenge_tickets", zap.Any("num", len(challenges)), zap.Any("challenges", challenges))

logging.Logger.Info("committing_challenge_tickets", zap.Any("num", len(challenges)))
now := time.Now()
for _, challenge := range challenges {
chall := challenge
var (
Expand All @@ -204,13 +216,17 @@ func commitOnChainWorker(ctx context.Context) {
err := challenge.VerifyChallengeTransaction(ctx, txn)
if err == nil || err != ErrEntityNotFound {
deleteChallenge(challenge.RoundCreatedAt)
if err != nil {
logging.Logger.Error("verifyChallengeTransaction", zap.Any("challenge", *challenge))
}
}
return nil
})
}(&chall)
}
}
wg.Wait()
logging.Logger.Info("committing_tickets_timing", zap.Any("num", len(challenges)), zap.Duration("elapsed", time.Since(now)))
}
}

Expand Down
28 changes: 26 additions & 2 deletions code/go/0chain.net/core/common/handler/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,32 @@ package handler

import (
"context"
"math"
"time"

blobConfig "github.com/0chain/blobber/code/go/0chain.net/blobbercore/config"
"github.com/0chain/blobber/code/go/0chain.net/blobbercore/handler"
valConfig "github.com/0chain/blobber/code/go/0chain.net/validatorcore/config"
"github.com/0chain/gosdk/zcncore"

"github.com/0chain/blobber/code/go/0chain.net/core/common"
"github.com/0chain/blobber/code/go/0chain.net/core/logging"
"go.uber.org/zap"
)

func StartHealthCheck(ctx context.Context, provider common.ProviderType) {
const HARDFORK_NAME = "hard_fork_2"

var HardForkRound int64 = math.MaxInt64

func StartHealthCheck(ctx context.Context, provider common.ProviderType) {
var t time.Duration

switch provider {
case common.ProviderTypeBlobber:
t = blobConfig.Configuration.HealthCheckWorkerFreq
case common.ProviderTypeValidator:
t = valConfig.Configuration.HealthCheckWorkerFreq

go setHardForkRound(ctx)
}

for {
Expand All @@ -44,3 +49,22 @@ func StartHealthCheck(ctx context.Context, provider common.ProviderType) {
}
}
}

func setHardForkRound(ctx context.Context) {
HardForkRound, _ = zcncore.GetHardForkRound(HARDFORK_NAME)
logging.Logger.Info("hard_fork_round", zap.Any("round", HardForkRound))
if HardForkRound == math.MaxInt64 {
for {
select {
case <-ctx.Done():
return
case <-time.After(5 * time.Minute):
HardForkRound, _ = zcncore.GetHardForkRound(HARDFORK_NAME)
if HardForkRound != math.MaxInt64 {
logging.Logger.Info("hard_fork_round", zap.Any("round", HardForkRound))
return
}
}
}
}
}
32 changes: 28 additions & 4 deletions code/go/0chain.net/core/encryption/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,17 @@ import (
"github.com/herumi/bls-go-binary/bls"
)

/*ReadKeys - reads a publicKey and a privateKey from a Reader.
They are assumed to be in two separate lines one followed by the other*/
func init() {
err := bls.Init(bls.CurveFp254BNb)
if err != nil {
panic(err)
}
}

/*
ReadKeys - reads a publicKey and a privateKey from a Reader.
They are assumed to be in two separate lines one followed by the other
*/
func ReadKeys(reader io.Reader) (publicKey, privateKey, publicIp, port string) {
scanner := bufio.NewScanner(reader)
scanner.Scan()
Expand Down Expand Up @@ -45,13 +54,14 @@ func Verify(publicKey, signature, hash string) (bool, error) {
}

// If input is normal herumi/bls public key, it returns it immmediately.
// So this is completely backward compatible with herumi/bls.
//
// So this is completely backward compatible with herumi/bls.
//
// If input is MIRACL public key, convert it to herumi/bls public key.
//
// This is an example of the raw public key we expect from MIRACL
var miraclExamplePK = `0418a02c6bd223ae0dfda1d2f9a3c81726ab436ce5e9d17c531ff0a385a13a0b491bdfed3a85690775ee35c61678957aaba7b1a1899438829f1dc94248d87ed36817f6dfafec19bfa87bf791a4d694f43fec227ae6f5a867490e30328cac05eaff039ac7dfc3364e851ebd2631ea6f1685609fc66d50223cc696cb59ff2fee47ac`

//
// This is an example of the same MIRACL public key serialized with ToString().
// pk ([1bdfed3a85690775ee35c61678957aaba7b1a1899438829f1dc94248d87ed368,18a02c6bd223ae0dfda1d2f9a3c81726ab436ce5e9d17c531ff0a385a13a0b49],[039ac7dfc3364e851ebd2631ea6f1685609fc66d50223cc696cb59ff2fee47ac,17f6dfafec19bfa87bf791a4d694f43fec227ae6f5a867490e30328cac05eaff])
func MiraclToHerumiPK(pk string) string {
Expand Down Expand Up @@ -99,3 +109,17 @@ func MiraclToHerumiSig(sig string) string {
}
return sign.SerializeToHexStr()
}

func AggregateSig(signatures []string) (string, error) {
var sig bls.Sign
sigVec := make([]bls.Sign, len(signatures))
for i := 0; i < len(signatures); i++ {
err := sigVec[i].DeserializeHexStr(signatures[i])
if err != nil {
Logger.Error("AggregateSig: " + err.Error())
return "", err
}
}
sig.Aggregate(sigVec)
return sig.SerializeToHexStr(), nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ func ValidValidationTicket(challengeObj *Challenge, challengeID string, challeng
validationTicket.Message = "Challenge passed"
validationTicket.ValidatorID = node.Self.ID
validationTicket.ValidatorKey = node.Self.PublicKey
validationTicket.Timestamp = common.Now()
if err := validationTicket.Sign(); err != nil {
validationTicket.Timestamp = challengeObj.Timestamp
if err := validationTicket.Sign(challengeObj.RoundCreatedAt); err != nil {
return nil, common.NewError("invalid_parameters", err.Error())
}
logging.Logger.Info("Validation passed.", zap.String("challenge_id", challengeID))
Expand Down Expand Up @@ -135,7 +135,7 @@ func InvalidValidationTicket(challengeObj *Challenge, err error) (interface{}, e
validationTicket.ValidatorKey = node.Self.PublicKey
validationTicket.Timestamp = common.Now()

if err := validationTicket.Sign(); err != nil {
if err := validationTicket.Sign(challengeObj.RoundCreatedAt); err != nil {
return nil, common.NewError("invalid_parameters", err.Error())
}
return &validationTicket, nil
Expand Down
12 changes: 10 additions & 2 deletions code/go/0chain.net/validatorcore/storage/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"

"github.com/0chain/blobber/code/go/0chain.net/core/common"
"github.com/0chain/blobber/code/go/0chain.net/core/common/handler"
"github.com/0chain/blobber/code/go/0chain.net/core/encryption"
"github.com/0chain/blobber/code/go/0chain.net/core/node"
"github.com/0chain/blobber/code/go/0chain.net/validatorcore/storage/writemarker"
Expand Down Expand Up @@ -380,6 +381,7 @@ type Challenge struct {
AllocationRoot string `json:"allocation_root"`
BlobberID string `json:"blobber_id"`
Timestamp common.Timestamp `json:"timestamp"`
RoundCreatedAt int64 `json:"round_created_at"`
}

type ValidationTicket struct {
Expand All @@ -394,8 +396,14 @@ type ValidationTicket struct {
Signature string `json:"signature"`
}

func (vt *ValidationTicket) Sign() error {
hashData := fmt.Sprintf("%v:%v:%v:%v:%v:%v", vt.ChallengeID, vt.BlobberID, vt.ValidatorID, vt.ValidatorKey, vt.Result, vt.Timestamp)
func (vt *ValidationTicket) Sign(round int64) error {
var hashData string
logging.Logger.Info("signing_validation_ticket", zap.Int64("round", round), zap.Int64("hard_fork_round", handler.HardForkRound))
if round >= handler.HardForkRound {
hashData = fmt.Sprintf("%v:%v:%v:%v", vt.ChallengeID, vt.BlobberID, vt.Result, vt.Timestamp)
} else {
hashData = fmt.Sprintf("%v:%v:%v:%v:%v:%v", vt.ChallengeID, vt.BlobberID, vt.ValidatorID, vt.ValidatorKey, vt.Result, vt.Timestamp)
}
hash := encryption.Hash(hashData)
signature, err := node.Self.Sign(hash)
vt.Signature = signature
Expand Down
2 changes: 1 addition & 1 deletion code/go/0chain.net/validatorcore/storage/models_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ func TestValidationTicket_Sign(t *testing.T) {
Timestamp: common.Now(),
}

err = vt.Sign()
err = vt.Sign(0)
require.NoError(t, err)
}

Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.21

require (
github.com/0chain/errors v1.0.3
github.com/0chain/gosdk v1.11.8-0.20240121220047-6f48750d0df4
github.com/0chain/gosdk v1.12.0-RC5
github.com/DATA-DOG/go-sqlmock v1.5.0
github.com/didip/tollbooth/v6 v6.1.2
github.com/go-openapi/runtime v0.26.0
Expand All @@ -21,9 +21,9 @@ require (
github.com/spf13/viper v1.16.0
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.15.0
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.14.0
golang.org/x/crypto v0.16.0
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.15.0
golang.org/x/time v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect
google.golang.org/grpc v1.56.2
Expand All @@ -38,7 +38,7 @@ require (

require (
github.com/lithammer/shortuuid/v3 v3.0.7
golang.org/x/sync v0.3.0
golang.org/x/sync v0.5.0
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc
)

Expand Down