77 beacon "github.com/oasisprotocol/oasis-core/go/beacon/api"
88 "github.com/oasisprotocol/oasis-core/go/common"
99 "github.com/oasisprotocol/oasis-core/go/common/crypto/hash"
10+ "github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
1011 "github.com/oasisprotocol/oasis-core/go/common/node"
1112 "github.com/oasisprotocol/oasis-core/go/common/sgx"
1213 "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/config"
@@ -28,6 +29,7 @@ type NetworkFixture struct {
2829 Keymanagers []KeymanagerFixture `json:"keymanagers,omitempty"`
2930 KeymanagerPolicies []KeymanagerPolicyFixture `json:"keymanager_policies,omitempty"`
3031 ComputeWorkers []ComputeWorkerFixture `json:"compute_workers,omitempty"`
32+ Observers []ObserverFixture `json:"observers,omitempty"`
3133 Sentries []SentryFixture `json:"sentries,omitempty"`
3234 Clients []ClientFixture `json:"clients,omitempty"`
3335 StatelessClients []StatelessClientFixture `json:"stateless_clients,omitempty"`
@@ -107,6 +109,13 @@ func (f *NetworkFixture) Create(env *env.Env) (*Network, error) {
107109 }
108110 }
109111
112+ // Provision the observers.
113+ for _ , fx := range f .Observers {
114+ if _ , err = fx .Create (net ); err != nil {
115+ return nil , err
116+ }
117+ }
118+
110119 // Provision the client nodes.
111120 for _ , fx := range f .Clients {
112121 if _ , err = fx .Create (net ); err != nil {
@@ -241,7 +250,7 @@ type RuntimeFixture struct {
241250 TxnScheduler registry.TxnSchedulerParameters `json:"txn_scheduler"`
242251 Storage registry.StorageParameters `json:"storage"`
243252
244- AdmissionPolicy registry. RuntimeAdmissionPolicy `json:"admission_policy"`
253+ AdmissionPolicy RuntimeAdmissionPolicyFixture `json:"admission_policy"`
245254 Constraints map [scheduler.CommitteeKind ]map [scheduler.Role ]registry.SchedulingConstraints `json:"constraints,omitempty"`
246255 Staking registry.RuntimeStakingParameters `json:"staking,omitempty"`
247256
@@ -259,6 +268,10 @@ func (f *RuntimeFixture) Create(netFixture *NetworkFixture, net *Network) (*Runt
259268 if err != nil {
260269 return nil , err
261270 }
271+ admissionPolicy , err := f .AdmissionPolicy .Resolve (net )
272+ if err != nil {
273+ return nil , err
274+ }
262275
263276 var km * Runtime
264277 if f .Keymanager != - 1 {
@@ -282,7 +295,7 @@ func (f *RuntimeFixture) Create(netFixture *NetworkFixture, net *Network) (*Runt
282295 Executor : f .Executor ,
283296 TxnScheduler : f .TxnScheduler ,
284297 Storage : f .Storage ,
285- AdmissionPolicy : f . AdmissionPolicy ,
298+ AdmissionPolicy : admissionPolicy ,
286299 Staking : f .Staking ,
287300 GenesisRound : f .GenesisRound ,
288301 GenesisStateRoot : f .GenesisStateRoot ,
@@ -294,6 +307,69 @@ func (f *RuntimeFixture) Create(netFixture *NetworkFixture, net *Network) (*Runt
294307 })
295308}
296309
310+ type RuntimeAdmissionPolicyFixture struct {
311+ AnyNode bool `json:"any_node,omitempty"`
312+ EntityWhitelist * EntityWhitelistRuntimeAdmissionPolicyFixture `json:"entity_whitelist,omitempty"`
313+ PerRole map [node.RolesMask ]PerRoleAdmissionPolicyFixture `json:"per_role,omitempty"`
314+ }
315+
316+ type EntityWhitelistRuntimeAdmissionPolicyFixture struct {
317+ Entities map [int ]registry.EntityWhitelistConfig `json:"entities"`
318+ }
319+
320+ type PerRoleAdmissionPolicyFixture struct {
321+ EntityWhitelist * EntityWhitelistRoleAdmissionPolicyFixture `json:"entity_whitelist,omitempty"`
322+ }
323+
324+ type EntityWhitelistRoleAdmissionPolicyFixture struct {
325+ Entities map [int ]registry.EntityWhitelistRoleConfig `json:"entities"`
326+ }
327+
328+ func (f RuntimeAdmissionPolicyFixture ) Resolve (net * Network ) (registry.RuntimeAdmissionPolicy , error ) {
329+ var policy registry.RuntimeAdmissionPolicy
330+
331+ if f .AnyNode {
332+ policy .AnyNode = & registry.AnyNodeRuntimeAdmissionPolicy {}
333+ }
334+
335+ if f .EntityWhitelist != nil {
336+ whitelist := & registry.EntityWhitelistRuntimeAdmissionPolicy {
337+ Entities : make (map [signature.PublicKey ]registry.EntityWhitelistConfig ),
338+ }
339+ for idx , cfg := range f .EntityWhitelist .Entities {
340+ ent , err := resolveEntity (net , idx )
341+ if err != nil {
342+ return registry.RuntimeAdmissionPolicy {}, err
343+ }
344+ whitelist .Entities [ent .ID ()] = cfg
345+ }
346+ policy .EntityWhitelist = whitelist
347+ }
348+
349+ if f .PerRole != nil {
350+ policy .PerRole = make (map [node.RolesMask ]registry.PerRoleAdmissionPolicy )
351+ for role , prap := range f .PerRole {
352+ var perRolePolicy registry.PerRoleAdmissionPolicy
353+ if prap .EntityWhitelist != nil {
354+ whitelist := & registry.EntityWhitelistRoleAdmissionPolicy {
355+ Entities : make (map [signature.PublicKey ]registry.EntityWhitelistRoleConfig ),
356+ }
357+ for idx , cfg := range prap .EntityWhitelist .Entities {
358+ ent , err := resolveEntity (net , idx )
359+ if err != nil {
360+ return registry.RuntimeAdmissionPolicy {}, err
361+ }
362+ whitelist .Entities [ent .ID ()] = cfg
363+ }
364+ perRolePolicy .EntityWhitelist = whitelist
365+ }
366+ policy .PerRole [role ] = perRolePolicy
367+ }
368+ }
369+
370+ return policy , nil
371+ }
372+
297373// KeymanagerPolicyFixture is a key manager policy fixture.
298374type KeymanagerPolicyFixture struct {
299375 Runtime int `json:"runtime"`
@@ -458,6 +534,53 @@ func (f *ComputeWorkerFixture) Create(net *Network) (*Compute, error) {
458534 })
459535}
460536
537+ // ObserverFixture is an observer node fixture.
538+ type ObserverFixture struct {
539+ NodeFixture
540+
541+ // Entity is the index of the entity the node will be provisioned with.
542+ Entity int `json:"entity"`
543+
544+ AllowErrorTermination bool `json:"allow_error_termination"`
545+ AllowEarlyTermination bool `json:"allow_early_termination"`
546+
547+ // Consensus contains configuration for the consensus backend.
548+ Consensus ConsensusFixture `json:"consensus"`
549+
550+ // Runtimes contains the indexes of the runtimes to enable.
551+ Runtimes []int `json:"runtimes,omitempty"`
552+
553+ // RuntimeProvisioner is the runtime provisioner configuration.
554+ RuntimeProvisioner runtimeConfig.RuntimeProvisioner `json:"runtime_provisioner"`
555+
556+ // RuntimeConfig contains the per-runtime node-local configuration.
557+ RuntimeConfig map [int ]map [string ]any `json:"runtime_config,omitempty"`
558+ }
559+
560+ // Create instantiates the observer node described by the fixture.
561+ func (f * ObserverFixture ) Create (net * Network ) (* Observer , error ) {
562+ entity , err := resolveEntity (net , f .Entity )
563+ if err != nil {
564+ return nil , err
565+ }
566+
567+ return net .NewObserver (& ObserverCfg {
568+ NodeCfg : NodeCfg {
569+ Name : f .Name ,
570+ Consensus : f .Consensus ,
571+ AllowErrorTermination : f .AllowErrorTermination ,
572+ AllowEarlyTermination : f .AllowEarlyTermination ,
573+ NoAutoStart : f .NoAutoStart ,
574+ SupplementarySanityInterval : f .Consensus .SupplementarySanityInterval ,
575+ Entity : entity ,
576+ ExtraArgs : f .ExtraArgs ,
577+ },
578+ Runtimes : f .Runtimes ,
579+ RuntimeProvisioner : f .RuntimeProvisioner ,
580+ RuntimeConfig : f .RuntimeConfig ,
581+ })
582+ }
583+
461584// SeedFixture is a seed node fixture.
462585type SeedFixture struct {
463586 NodeFixture
0 commit comments