-
Notifications
You must be signed in to change notification settings - Fork 57
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
Fix: Solve issue #331 by adding FirstEvent support in FireFly config #332
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,27 @@ go install github.com/hyperledger/firefly-cli/ff@latest | |
$ ff init <stack_name> | ||
``` | ||
|
||
### Stack Initialization Options | ||
|
||
When initializing a new stack, you can configure various options including: | ||
|
||
``` | ||
--from-block For multiparty networks only: specify the starting block for event processing. | ||
Use 'newest' for latest block, or a specific block number (default: "0") | ||
``` | ||
|
||
Examples: | ||
``` | ||
# Initialize with default settings (starts from block 0) | ||
ff init mystack | ||
|
||
# Initialize starting from the latest block | ||
ff init mystack --from-block newest | ||
|
||
# Initialize starting from a specific block number | ||
ff init mystack --from-block 1234567 | ||
Comment on lines
+70
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would make these examples to be with |
||
``` | ||
|
||
## Start a stack | ||
|
||
``` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,6 +102,9 @@ This command will start a stack and run it in the background. | |
}, | ||
} | ||
|
||
|
||
// ... existing code ... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove this |
||
|
||
func init() { | ||
startCmd.Flags().BoolVarP(&startOptions.NoRollback, "no-rollback", "b", false, "Do not automatically rollback changes if first time setup fails") | ||
rootCmd.AddCommand(startCmd) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,6 @@ | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package stacks | ||
|
||
import ( | ||
|
@@ -611,44 +610,44 @@ func (s *StackManager) createMember(id string, index int, options *types.InitOpt | |
|
||
func (s *StackManager) StartStack(options *types.StartOptions) (messages []string, err error) { | ||
fmt.Printf("starting FireFly stack '%s'... ", s.Stack.Name) | ||
// Check to make sure all of our ports are available | ||
|
||
// Check port availability | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why the comment change? |
||
err = s.checkPortsAvailable() | ||
if err != nil { | ||
return messages, err | ||
} | ||
|
||
hasBeenRun, err := s.Stack.HasRunBefore() | ||
if err != nil { | ||
return messages, err | ||
} | ||
if !hasBeenRun { | ||
setupMessages, err := s.runFirstTimeSetup(options) | ||
messages = append(messages, setupMessages...) | ||
// Pass FirstEvent to the first-time setup | ||
setupMessages, err := s.runFirstTimeSetup(&types.InitOptions{ | ||
FromBlock: options.FromBlock, | ||
}) | ||
Comment on lines
+626
to
+628
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FromBlock doesn't exist in InitOptions, it should be StartOptions. Getting errors in the IDE |
||
messages = append(messages, setupMessages...) | ||
if err != nil { | ||
// Something bad happened during setup | ||
// Handle rollback if necessary | ||
if options.NoRollback { | ||
return messages, err | ||
} else { | ||
// Rollback changes | ||
s.Log.Error(fmt.Errorf("an error occurred - rolling back changes")) | ||
resetErr := s.ResetStack() | ||
|
||
var finalErr error | ||
|
||
if resetErr != nil { | ||
finalErr = fmt.Errorf("%s - error resetting stack: %s", err.Error(), resetErr.Error()) | ||
} else { | ||
finalErr = fmt.Errorf("%s - all changes rolled back", err.Error()) | ||
return messages, fmt.Errorf("%s - error resetting stack: %s", err.Error(), resetErr.Error()) | ||
} | ||
|
||
return messages, finalErr | ||
return messages, fmt.Errorf("%s - all changes rolled back", err.Error()) | ||
} | ||
} | ||
} else { | ||
// Standard startup sequence | ||
err = s.runStartupSequence(false) | ||
if err != nil { | ||
return messages, err | ||
} | ||
} | ||
|
||
return messages, s.ensureFireflyNodesUp(true) | ||
} | ||
|
||
|
@@ -864,7 +863,7 @@ func checkPortAvailable(port int) (bool, error) { | |
} | ||
|
||
//nolint:gocyclo // TODO: Breaking this function apart would be great for code tidiness, but it's not an urgent priority | ||
func (s *StackManager) runFirstTimeSetup(options *types.StartOptions) (messages []string, err error) { | ||
func (s *StackManager) runFirstTimeSetup(options *types.InitOptions) (messages []string, err error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should still be the StartOptions |
||
configDir := filepath.Join(s.Stack.RuntimeDir, "config") | ||
|
||
for i := 0; i < len(s.Stack.Members); i++ { | ||
|
@@ -943,26 +942,12 @@ func (s *StackManager) runFirstTimeSetup(options *types.StartOptions) (messages | |
var contractDeploymentResult *types.ContractDeploymentResult | ||
if s.Stack.MultipartyEnabled { | ||
if s.Stack.ContractAddress == "" { | ||
// TODO: This code assumes that there is only one plugin instance per type. When we add support for | ||
// multiple namespaces, this code will likely have to change a lot | ||
s.Log.Info("deploying FireFly smart contracts") | ||
contractDeploymentResult, err = s.blockchainProvider.DeployFireFlyContract() | ||
if err != nil { | ||
return messages, err | ||
} | ||
if contractDeploymentResult != nil { | ||
if contractDeploymentResult.Message != "" { | ||
messages = append(messages, contractDeploymentResult.Message) | ||
} | ||
s.Stack.State.DeployedContracts = append(s.Stack.State.DeployedContracts, contractDeploymentResult.DeployedContract) | ||
} | ||
} | ||
} | ||
|
||
for _, member := range s.Stack.Members { | ||
orgConfig := s.blockchainProvider.GetOrgConfig(s.Stack, member) | ||
newConfig.Namespaces.Predefined[0].DefaultKey = orgConfig.Key | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need this key as well
Comment on lines
-946
to
-964
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I mentioned in my previous review, keep this code as it was |
||
if s.Stack.MultipartyEnabled { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we still need this |
||
var contractLocation interface{} | ||
if s.Stack.ContractAddress != "" { | ||
contractLocation = map[string]interface{}{ | ||
|
@@ -971,40 +956,97 @@ func (s *StackManager) runFirstTimeSetup(options *types.StartOptions) (messages | |
} else { | ||
contractLocation = contractDeploymentResult.DeployedContract.Location | ||
} | ||
|
||
options := make(map[string]interface{}) | ||
if s.Stack.CustomPinSupport { | ||
options["customPinSupport"] = true | ||
} | ||
|
||
newConfig.Namespaces.Predefined[0].Multiparty = &types.MultipartyConfig{ | ||
Enabled: true, | ||
Org: orgConfig, | ||
Node: &types.NodeConfig{ | ||
Name: member.NodeName, | ||
if newConfig.Namespaces.Predefined[0].Multiparty == nil { | ||
newConfig.Namespaces.Predefined[0].Multiparty = &types.MultipartyConfig{ | ||
Enabled: true, | ||
Org: orgConfig, | ||
Node: &types.NodeConfig{ | ||
Name: member.NodeName, | ||
}, | ||
} | ||
} | ||
|
||
newConfig.Namespaces.Predefined[0].Multiparty.Contract = []*types.ContractConfig{ | ||
{ | ||
Location: contractLocation, | ||
FirstEvent: options.FromBlock, | ||
Options: options, | ||
}, | ||
Contract: []*types.ContractConfig{ | ||
} | ||
|
||
if contractDeploymentResult.Message != "" { | ||
messages = append(messages, contractDeploymentResult.Message) | ||
} | ||
s.Stack.State.DeployedContracts = append(s.Stack.State.DeployedContracts, contractDeploymentResult.DeployedContract) | ||
if err = s.writeStackStateJSON(s.Stack.RuntimeDir); err != nil { | ||
return messages, err | ||
} | ||
} | ||
} | ||
|
||
for _, member := range s.Stack.Members { | ||
orgConfig := s.blockchainProvider.GetOrgConfig(s.Stack, member) | ||
newConfig.Namespaces.Predefined[0].DefaultKey = orgConfig.Key | ||
|
||
if s.Stack.MultipartyEnabled { | ||
if s.Stack.ContractAddress == "" { | ||
s.Log.Info("deploying FireFly smart contracts") | ||
contractDeploymentResult, err = s.blockchainProvider.DeployFireFlyContract() | ||
if err != nil { | ||
return messages, err | ||
} | ||
|
||
var contractLocation interface{} | ||
if s.Stack.ContractAddress != "" { | ||
contractLocation = map[string]interface{}{ | ||
"address": s.Stack.ContractAddress, | ||
} | ||
} else { | ||
contractLocation = contractDeploymentResult.DeployedContract.Location | ||
} | ||
|
||
options := make(map[string]interface{}) | ||
if s.Stack.CustomPinSupport { | ||
options["customPinSupport"] = true | ||
} | ||
|
||
if newConfig.Namespaces.Predefined[0].Multiparty == nil { | ||
newConfig.Namespaces.Predefined[0].Multiparty = &types.MultipartyConfig{ | ||
Enabled: true, | ||
Org: orgConfig, | ||
Node: &types.NodeConfig{ | ||
Name: member.NodeName, | ||
}, | ||
} | ||
} | ||
|
||
newConfig.Namespaces.Predefined[0].Multiparty.Contract = []*types.ContractConfig{ | ||
{ | ||
Location: contractLocation, | ||
FirstEvent: "0", | ||
FirstEvent: options.FromBlock, | ||
Options: options, | ||
}, | ||
}, | ||
} | ||
|
||
if contractDeploymentResult.Message != "" { | ||
messages = append(messages, contractDeploymentResult.Message) | ||
} | ||
s.Stack.State.DeployedContracts = append(s.Stack.State.DeployedContracts, contractDeploymentResult.DeployedContract) | ||
if err = s.writeStackStateJSON(s.Stack.RuntimeDir); err != nil { | ||
return messages, err | ||
} | ||
} | ||
} | ||
|
||
if err := s.patchFireFlyCoreConfigs(configDir, member, newConfig); err != nil { | ||
return messages, err | ||
} | ||
|
||
// Create data directory with correct permissions inside volume | ||
dataVolumeName := fmt.Sprintf("%s_firefly_core_data_%s", s.Stack.Name, member.ID) | ||
if err := docker.CreateVolume(s.ctx, dataVolumeName); err != nil { | ||
return messages, err | ||
} | ||
if err := docker.MkdirInVolume(s.ctx, dataVolumeName, "db"); err != nil { | ||
return messages, err | ||
} | ||
|
||
} | ||
|
||
// Re-write the docker-compose config again, in case new values have been added | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should only work with
remote-node-url
as with the local chain that the CLI creates we want to start from 0There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as it should point to when the contract was deployed - I'm more tempted for this to be
--contract-block
as you pass in the MultiParty Contract address through--contract