From 00a01689e547f567a7aef1a4520bdb581ff840db Mon Sep 17 00:00:00 2001 From: Manoj Krishnan Date: Wed, 24 Jun 2026 10:19:43 +0530 Subject: [PATCH] Fix nil-pointer panic in VSCC when LAST_LIFECYCLE_BLOCK_NUMBER is absent GetState() returns (nil, nil) when a key does not exist, but InitializeTxValidator and getValidator dereferenced versionedValue.Version.BlockNum unconditionally after the err check, assuming the key was always present. On a fresh channel or after a DB wipe, LAST_LIFECYCLE_BLOCK_NUMBER has never been written, so this panicked the VSCC process and took down validation for every channel on that instance. Guard both call sites so a missing key (or missing Version) defaults the block number to 0 instead of dereferencing a nil pointer. --- .gitignore | 1 + core/vscc/validate.go | 16 ++++++++++++---- go.mod | 2 +- go.sum | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/core/vscc/validate.go b/core/vscc/validate.go index 7077026..d87e78e 100644 --- a/core/vscc/validate.go +++ b/core/vscc/validate.go @@ -1,6 +1,6 @@ /* Copyright National Payments Corporation of India. All Rights Reserved. - + SPDX-License-Identifier: Apache-2.0 */ @@ -82,7 +82,7 @@ func NewVsccValidateServer(ledgerConfig *ledger.Config, validationPluginsByName if vdbProvider, err = statecouchdb.NewVersionedDBProvider(ledgerConfig.StateDBConfig.CouchDB, metricsProvider, nil); err != nil { return nil, err } - } else if ledgerConfig.StateDBConfig.StateDatabase == ledger.SqlDB { + } else if ledgerConfig != nil && ledgerConfig.StateDBConfig.StateDatabase == ledger.SqlDB { vdbProvider, err = statesqldb.NewVersionedDBProvider(ledgerConfig.StateDBConfig.SqlDB, nil, nil) if err != nil { return nil, err @@ -179,8 +179,11 @@ func (v *VsccValidateServer) InitializeTxValidator(channelName string, blockNumb if blockNumber == 0 { versionedValue, err := versionDb.GetState("", "LAST_LIFECYCLE_BLOCK_NUMBER") if err != nil { - v.logger.Errorf("failed to initilialize txValidator : %v", err) - return nil, status.Errorf(codes.Internal, "failed to initilialize txValidator") + v.logger.Errorf("failed to initialize txValidator : %v", err) + return nil, status.Errorf(codes.Internal, "failed to initialize txValidator") + } + if versionedValue == nil || versionedValue.Version == nil { + return nil, fmt.Errorf("LAST_LIFECYCLE_BLOCK_NUMBER not found in state DB for channel %s", channelName) } blockNumber = versionedValue.Version.BlockNum } @@ -358,6 +361,11 @@ func (v *VsccValidateServer) getValidator(req *pb.VsccRequest) (*txvalidator.TxV v.logger.Errorf("failed to initilialize txValidator : %v", err) return nil, status.Errorf(codes.Internal, "failed to initilialize txValidator") } + + if versionedValue == nil || versionedValue.Version == nil { + return nil, fmt.Errorf("LAST_LIFECYCLE_BLOCK_NUMBER not found in state DB for channel %s", req.ChannelId) + } + lastLifecycleBlockNumberInDB := versionedValue.Version.BlockNum if channelValidator.lastLifecycleBlockNumber != lastLifecycleBlockNumberInDB { diff --git a/go.mod b/go.mod index 05ab5e6..d9e0cee 100644 --- a/go.mod +++ b/go.mod @@ -145,4 +145,4 @@ require ( gorm.io/driver/mysql v1.5.6 // indirect ) -replace github.com/hyperledger/fabric-protos-go => ./fabric-protos-go-0.2.0 +replace github.com/hyperledger/fabric-protos-go => ./fabric-protos-go-0.2.0 \ No newline at end of file diff --git a/go.sum b/go.sum index 4177def..bb604f6 100644 --- a/go.sum +++ b/go.sum @@ -5355,4 +5355,4 @@ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= \ No newline at end of file