hotstuff icon indicating copy to clipboard operation
hotstuff copied to clipboard

config: generate ConfigOpts proto message from schema.cue

Open meling opened this issue 1 year ago • 0 comments

We can use the cue command line tool to generate a cue schema based on a protobuf file. This is explained here.

It requires a small hack to get it to work since our orchestration.proto file imports duration.proto, which isn't easily imported (it is part of the protobuf tooling). A temporary workaround is to copy it from the protobuf project.

cd hotstuff
mkdir -p google/protobuf
cp <protobuf-project>/src/google/protobuf/duration.proto google/protobuf
cue import -I . internal/proto/orchestrationpb/orchestration.proto

This will generate an orchestration.cue file, as shown below (I've removed some unnecessary parts). This includes too many fields that aren't relevant to include in a schema.cue file since they are either generated dynamically or loaded from separate files (keys and certificates). Moreover, it doesn't take advantage of the constraints we want to specify in the schema.cue file.

There are two options:

  • Create a separate ConfigOpts proto message that could be nested inside ReplicaOpts, which could serve as the schema.cue file.
  • Another option would be to generate a proto file with a ConfigOpts proto message based on a schema.cue file. The cue command does not support export to proto format. But a separate protoc-gen-cue plugin exists. The plugin has limitations on time.Duration, as mentioned in #164. The concern is that the plugin hasn't been updated in two years. I have not tested the plugin.
package orchestrationpb

import "time"

// ReplicaOpts contains the configuration options for a replica.
#ReplicaOpts: {
	// The replica's ID.
	ID?: uint32 @protobuf(1,uint32)

	// The replica's private key.
	PrivateKey?: bytes @protobuf(3,bytes)

	// The replica's public key.
	PublicKey?: bytes @protobuf(16,bytes)

	// Determines whether TLS should be used.
	UseTLS?: bool @protobuf(4,bool)

	// The replica's TLS certificate.
	Certificate?: bytes @protobuf(5,bytes)

	// The private key of the TLS certificate.
	CertificateKey?: bytes @protobuf(6,bytes)

	// The certificate authority that created the TLS certificates.
	CertificateAuthority?: bytes @protobuf(7,bytes)

	// The name of the crypto implementation to use.
	Crypto?: string @protobuf(8,string)

	// The name of the consensus implementation to use.
	Consensus?: string @protobuf(9,string)

	// The name of the leader rotation algorithm to use.
	LeaderRotation?: string @protobuf(10,string)

	// The number of client commands that should be batched together.
	BatchSize?: uint32 @protobuf(11,uint32)

	// The timeout of the initial connection setup.
	ConnectTimeout?: time.Duration @protobuf(17,google.protobuf.Duration)

	// The initial view duration.
	InitialTimeout?: time.Duration @protobuf(12,google.protobuf.Duration)

	// The maximum view timeout.
	MaxTimeout?: time.Duration @protobuf(19,google.protobuf.Duration)

	// The number of samples used to calculate view duration.
	TimeoutSamples?: uint32 @protobuf(13,uint32)

	// The number that the old view duration should be multiplied by when a new
	// timeout happens.
	TimeoutMultiplier?: float32 @protobuf(14,float)

	// The byzantine strategy to use. If empty, the replica will act normally.
	ByzantineStrategy?: string @protobuf(18,string)

	// A shared random number for seeding random number generators.
	SharedSeed?: int64 @protobuf(20,int64)

	// A list of modules to load.
	Modules?: [...string] @protobuf(21,string)

	// Replica locations indexed by replica ID.
	Locations?: [...string] @protobuf(22,string)

	// Tree positions of the replica.
	TreePositions?: [...uint32] @protobuf(23,uint32)

	// Branch Factor in tree communication
	BranchFactor?: uint32 @protobuf(24,uint32)

	// Tree Duration in tree communication
	TreeDelta?: time.Duration @protobuf(25,google.protobuf.Duration)
	// DelayType is the type of delay to use for the wait time.
	{} | {
		// AggregationTime computes the wait time based on the latency of links in the tree.
		AggregationTime: bool @protobuf(26,bool)
	} | {
		// TreeHeightTime computes the wait time only based on the height of the tree.
		TreeHeightTime: bool @protobuf(27,bool)
	}
}

meling avatar Jan 25 '25 11:01 meling