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
@@ -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"
@@ -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()))
9 changes: 7 additions & 2 deletions code/go/0chain.net/blobbercore/challenge/entity.go
Original file line number Diff line number Diff line change
@@ -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
15 changes: 8 additions & 7 deletions code/go/0chain.net/blobbercore/challenge/protocol.go
Original file line number Diff line number Diff line change
@@ -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) {
@@ -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)
}
@@ -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
}
@@ -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) {
22 changes: 19 additions & 3 deletions code/go/0chain.net/blobbercore/challenge/worker.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package challenge

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

@@ -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
@@ -72,6 +76,7 @@ func startPullWorker(ctx context.Context) {

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

// start challenge listeners
@@ -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()

@@ -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 (
@@ -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)))
}
}

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
@@ -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 {
@@ -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
@@ -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()
@@ -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 {
@@ -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
@@ -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))
@@ -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
12 changes: 10 additions & 2 deletions code/go/0chain.net/validatorcore/storage/models.go
Original file line number Diff line number Diff line change
@@ -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"
@@ -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 {
@@ -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
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
@@ -642,7 +642,7 @@ func TestValidationTicket_Sign(t *testing.T) {
Timestamp: common.Now(),
}

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

10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -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
@@ -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
@@ -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
)

Loading