From 40e0e0a2d161415c85b56d13bd649ea7abf8b946 Mon Sep 17 00:00:00 2001 From: MayRosenbaum <113279625+MayRosenbaum@users.noreply.github.com> Date: Thu, 30 Nov 2023 19:22:06 +0200 Subject: [PATCH] Get last config block API (#180) Signed-off-by: May Rosenbaum --- pkg/bcdb/config_tx_context.go | 23 ++++++++ pkg/bcdb/config_tx_context_test.go | 94 ++++++++++++++++++++++++++++++ pkg/bcdb/tx_context.go | 2 + 3 files changed, 119 insertions(+) diff --git a/pkg/bcdb/config_tx_context.go b/pkg/bcdb/config_tx_context.go index 2afa312..7454c46 100644 --- a/pkg/bcdb/config_tx_context.go +++ b/pkg/bcdb/config_tx_context.go @@ -80,6 +80,9 @@ type ConfigTxContext interface { // pending config was set is permitted. Those methods are applied to the pending config (e.g. AddAdmin() will add // an admin, etc.). SetClusterConfig(newConfig *types.ClusterConfig) error + + // GetLastConfigBlock returns the last config block. + GetLastConfigBlock() ([]byte, error) } type configTxContext struct { @@ -347,6 +350,26 @@ func (c *configTxContext) SetClusterConfig(newConfig *types.ClusterConfig) error return nil } +func (c *configTxContext) GetLastConfigBlock() ([]byte, error) { + configResponseEnv := &types.GetConfigBlockResponseEnvelope{} + path := constants.GetLastConfigBlock + err := c.handleRequest( + path, + &types.GetConfigBlockQuery{ + UserId: c.userID, + }, + configResponseEnv, + ) + if err != nil { + c.logger.Errorf("failed to execute cluster config query path %s, due to %s", path, err) + return nil, err + } + + confResp := configResponseEnv.GetResponse() + + return confResp.GetBlock(), nil +} + func (c *configTxContext) queryClusterConfig() error { if c.oldConfig != nil { return nil diff --git a/pkg/bcdb/config_tx_context_test.go b/pkg/bcdb/config_tx_context_test.go index fcd17b2..c39e3c6 100644 --- a/pkg/bcdb/config_tx_context_test.go +++ b/pkg/bcdb/config_tx_context_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + "github.com/golang/protobuf/proto" + sdkConfig "github.com/hyperledger-labs/orion-sdk-go/pkg/config" "github.com/hyperledger-labs/orion-server/pkg/server/testutils" "github.com/hyperledger-labs/orion-server/pkg/types" @@ -762,3 +764,95 @@ func TestConfigTx_CommitAbortFinality(t *testing.T) { } } } + +func TestGetLastConfigBlock(t *testing.T) { + cryptoDir := testutils.GenerateTestCrypto(t, []string{"admin", "server"}) + testServer, _, _, err := SetupTestServer(t, cryptoDir) + defer func() { + if testServer != nil { + _ = testServer.Stop() + } + }() + require.NoError(t, err) + StartTestServer(t, testServer) + + serverPort, err := testServer.Port() + require.NoError(t, err) + + bcdb := createDBInstance(t, cryptoDir, serverPort) + session := openUserSession(t, bcdb, "admin", cryptoDir) + + t.Run("GetLastConfigBlock returns genesis config block", func(t *testing.T) { + tx, err := session.ConfigTx() + require.NoError(t, err) + + txBlk, err := tx.GetLastConfigBlock() + require.NoError(t, err) + require.NotNil(t, txBlk) + + var block = &types.Block{} + err = proto.Unmarshal(txBlk, block) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, uint64(1), block.GetHeader().GetBaseHeader().GetNumber()) + require.Equal(t, 1, len(block.GetConfigTxEnvelope().GetPayload().GetNewConfig().GetNodes())) + }) + + t.Run("GetLastConfigBlock returns the last config block", func(t *testing.T) { + // 1. tx1 - set raft config MaxInflightBlocks param + tx, err := session.ConfigTx() + require.NoError(t, err) + + clusterConfig, version, err := tx.GetClusterConfig() + require.NoError(t, err) + require.NotNil(t, version) + raftConf := clusterConfig.GetConsensusConfig().GetRaftConfig() + raftConf.MaxInflightBlocks++ + err = tx.UpdateRaftConfig(raftConf) + require.NoError(t, err) + + txID, receiptEnv, err := tx.Commit(true) + require.NoError(t, err) + require.True(t, txID != "") + require.NotNil(t, receiptEnv) + + txBlk, err := tx.GetLastConfigBlock() + require.NoError(t, err) + require.NotNil(t, txBlk) + + // check the last config block + var block = &types.Block{} + err = proto.Unmarshal(txBlk, block) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, uint64(2), block.GetHeader().GetBaseHeader().GetNumber()) + require.Equal(t, 1, len(block.GetConfigTxEnvelope().GetPayload().GetNewConfig().GetNodes())) + + // 2. tx2 - set raft config HeartbeatTicks param + tx, err = session.ConfigTx() + require.NoError(t, err) + + clusterConfig, version, err = tx.GetClusterConfig() + require.NoError(t, err) + require.NotNil(t, version) + raftConf = clusterConfig.GetConsensusConfig().GetRaftConfig() + raftConf.HeartbeatTicks++ + err = tx.UpdateRaftConfig(raftConf) + require.NoError(t, err) + + txID, receiptEnv, err = tx.Commit(true) + require.NoError(t, err) + require.True(t, txID != "") + require.NotNil(t, receiptEnv) + + txBlk, err = tx.GetLastConfigBlock() + require.NoError(t, err) + require.NotNil(t, txBlk) + + // check the last config block + err = proto.Unmarshal(txBlk, block) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, uint64(3), block.GetHeader().GetBaseHeader().GetNumber()) + }) +} diff --git a/pkg/bcdb/tx_context.go b/pkg/bcdb/tx_context.go index 662d291..3ff69dd 100644 --- a/pkg/bcdb/tx_context.go +++ b/pkg/bcdb/tx_context.go @@ -390,6 +390,8 @@ func ResponseSelector(envelop ResponseEnvelop) (ResponseWithHeader, error) { return envelop.(*types.GetDataRangeResponseEnvelope).GetResponse(), nil case *types.GetTxResponseEnvelope: return envelop.(*types.GetTxResponseEnvelope).GetResponse(), nil + case *types.GetConfigBlockResponseEnvelope: + return envelop.(*types.GetConfigBlockResponseEnvelope).GetResponse(), nil default: return nil, errors.Errorf("unknown response type %T", t)