@@ -611,44 +611,52 @@ func (s *StackManager) createMember(id string, index int, options *types.InitOpt
611611
612612func (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