Skip to content

Commit 99368a5

Browse files
committed
Fix: Solve issue #331 by adding FirstEvent support in FireFly config
1 parent 14e7721 commit 99368a5

File tree

3 files changed

+93
-68
lines changed

3 files changed

+93
-68
lines changed

cmd/start.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,6 @@ This command will start a stack and run it in the background.
104104

105105
func init() {
106106
startCmd.Flags().BoolVarP(&startOptions.NoRollback, "no-rollback", "b", false, "Do not automatically rollback changes if first time setup fails")
107+
startCmd.Flags().StringVarP(&startOptions.FirstEvent, "first-event", "f", "0", "Specify the starting block for event processing (default: 0)")
107108
rootCmd.AddCommand(startCmd)
108109
}

internal/blockchain/ethereum/ethtypes/types.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ package ethtypes
1919
type CompiledContracts struct {
2020
Contracts map[string]*CompiledContract `json:"contracts"`
2121
}
22-
22+
// StartOptions holds the options for starting Firefly CLI
23+
type StartOptions struct {
24+
NoRollback bool
25+
FirstEvent string // "0", "newest", or a specific block number
26+
}
2327
type CompiledContract struct {
2428
Name string `json:"name"`
2529
ABI interface{} `json:"abi"`

internal/stacks/stack_manager.go

Lines changed: 87 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -611,44 +611,52 @@ func (s *StackManager) createMember(id string, index int, options *types.InitOpt
611611

612612
func (s *StackManager) StartStack(options *types.StartOptions) (messages []string, err error) {
613613
fmt.Printf("starting FireFly stack '%s'... ", s.Stack.Name)
614-
// Check to make sure all of our ports are available
614+
615+
// Validate the FirstEvent value
616+
if options.FirstEvent != "0" && options.FirstEvent != "newest" {
617+
if _, err := strconv.Atoi(options.FirstEvent); err != nil {
618+
return messages, fmt.Errorf("invalid FirstEvent value: %s", options.FirstEvent)
619+
}
620+
}
621+
622+
// Check port availability
615623
err = s.checkPortsAvailable()
616624
if err != nil {
617625
return messages, err
618626
}
627+
619628
hasBeenRun, err := s.Stack.HasRunBefore()
620629
if err != nil {
621630
return messages, err
622631
}
623632
if !hasBeenRun {
624-
setupMessages, err := s.runFirstTimeSetup(options)
625-
messages = append(messages, setupMessages...)
633+
// Pass FirstEvent to the first-time setup
634+
setupMessages, err := s.runFirstTimeSetup(&types.StartOptions{
635+
NoRollback: false, // Example
636+
FirstEvent: "newest", // Or the user-defined value
637+
})
638+
messages = append(messages, setupMessages...)
626639
if err != nil {
627-
// Something bad happened during setup
640+
// Handle rollback if necessary
628641
if options.NoRollback {
629642
return messages, err
630643
} else {
631-
// Rollback changes
632644
s.Log.Error(fmt.Errorf("an error occurred - rolling back changes"))
633645
resetErr := s.ResetStack()
634-
635-
var finalErr error
636-
637646
if resetErr != nil {
638-
finalErr = fmt.Errorf("%s - error resetting stack: %s", err.Error(), resetErr.Error())
639-
} else {
640-
finalErr = fmt.Errorf("%s - all changes rolled back", err.Error())
647+
return messages, fmt.Errorf("%s - error resetting stack: %s", err.Error(), resetErr.Error())
641648
}
642-
643-
return messages, finalErr
649+
return messages, fmt.Errorf("%s - all changes rolled back", err.Error())
644650
}
645651
}
646652
} else {
653+
// Standard startup sequence
647654
err = s.runStartupSequence(false)
648655
if err != nil {
649656
return messages, err
650657
}
651658
}
659+
652660
return messages, s.ensureFireflyNodesUp(true)
653661
}
654662

@@ -940,61 +948,73 @@ func (s *StackManager) runFirstTimeSetup(options *types.StartOptions) (messages
940948

941949
newConfig.Namespaces.Predefined[0].Plugins = append(newConfig.Namespaces.Predefined[0].Plugins, types.FFEnumArrayToStrings(s.Stack.TokenProviders)...)
942950

951+
952+
943953
var contractDeploymentResult *types.ContractDeploymentResult
944-
if s.Stack.MultipartyEnabled {
945-
if s.Stack.ContractAddress == "" {
946-
// TODO: This code assumes that there is only one plugin instance per type. When we add support for
947-
// multiple namespaces, this code will likely have to change a lot
948-
s.Log.Info("deploying FireFly smart contracts")
949-
contractDeploymentResult, err = s.blockchainProvider.DeployFireFlyContract()
950-
if err != nil {
951-
return messages, err
952-
}
953-
if contractDeploymentResult != nil {
954-
if contractDeploymentResult.Message != "" {
955-
messages = append(messages, contractDeploymentResult.Message)
956-
}
957-
s.Stack.State.DeployedContracts = append(s.Stack.State.DeployedContracts, contractDeploymentResult.DeployedContract)
958-
}
959-
}
960-
}
961-
962-
for _, member := range s.Stack.Members {
963-
orgConfig := s.blockchainProvider.GetOrgConfig(s.Stack, member)
964-
newConfig.Namespaces.Predefined[0].DefaultKey = orgConfig.Key
965-
if s.Stack.MultipartyEnabled {
966-
var contractLocation interface{}
967-
if s.Stack.ContractAddress != "" {
968-
contractLocation = map[string]interface{}{
969-
"address": s.Stack.ContractAddress,
970-
}
971-
} else {
972-
contractLocation = contractDeploymentResult.DeployedContract.Location
973-
}
974-
options := make(map[string]interface{})
975-
if s.Stack.CustomPinSupport {
976-
options["customPinSupport"] = true
977-
}
978-
979-
newConfig.Namespaces.Predefined[0].Multiparty = &types.MultipartyConfig{
980-
Enabled: true,
981-
Org: orgConfig,
982-
Node: &types.NodeConfig{
983-
Name: member.NodeName,
984-
},
985-
Contract: []*types.ContractConfig{
986-
{
987-
Location: contractLocation,
988-
FirstEvent: "0",
989-
Options: options,
990-
},
991-
},
992-
}
993-
}
994-
995-
if err := s.patchFireFlyCoreConfigs(configDir, member, newConfig); err != nil {
996-
return messages, err
997-
}
954+
if s.Stack.MultipartyEnabled {
955+
if s.Stack.ContractAddress == "" {
956+
s.Log.Info("deploying FireFly smart contracts")
957+
contractDeploymentResult, err = s.blockchainProvider.DeployFireFlyContract()
958+
if err != nil {
959+
return messages, err
960+
}
961+
}
962+
}
963+
964+
for _, member := range s.Stack.Members {
965+
orgConfig := s.blockchainProvider.GetOrgConfig(s.Stack, member)
966+
967+
// Default to "0" if FirstEvent is not provided
968+
firstEvent := "0"
969+
if options.FirstEvent != "" {
970+
firstEvent = options.FirstEvent
971+
}
972+
973+
var contractLocation interface{}
974+
if s.Stack.ContractAddress != "" {
975+
contractLocation = map[string]interface{}{
976+
"address": s.Stack.ContractAddress,
977+
}
978+
} else {
979+
contractLocation = contractDeploymentResult.DeployedContract.Location
980+
}
981+
982+
optionsMap := make(map[string]interface{})
983+
if s.Stack.CustomPinSupport {
984+
optionsMap["customPinSupport"] = true
985+
}
986+
987+
newConfig := &types.FireflyConfig{
988+
Namespaces: &types.NamespacesConfig{
989+
Default: "default",
990+
Predefined: []*types.Namespace{
991+
{
992+
Name: "default",
993+
Description: "Default predefined namespace",
994+
Plugins: []string{"database0", "blockchain0", "dataexchange0", "sharedstorage0"},
995+
Multiparty: &types.MultipartyConfig{
996+
Enabled: true,
997+
Org: orgConfig,
998+
Node: &types.NodeConfig{
999+
Name: member.NodeName,
1000+
},
1001+
Contract: []*types.ContractConfig{
1002+
{
1003+
Location: contractLocation,
1004+
FirstEvent: firstEvent, // Now configurable
1005+
Options: optionsMap,
1006+
},
1007+
},
1008+
},
1009+
},
1010+
},
1011+
},
1012+
}
1013+
1014+
if err := s.patchFireFlyCoreConfigs(configDir, member, newConfig); err != nil {
1015+
return messages, err
1016+
}
1017+
9981018

9991019
// Create data directory with correct permissions inside volume
10001020
dataVolumeName := fmt.Sprintf("%s_firefly_core_data_%s", s.Stack.Name, member.ID)

0 commit comments

Comments
 (0)