Repository: celestiaorg/celestia-node
Pull request #590 (2022-04-05 14:46:06)

chore(node): move out fxutil into libs
This is follow-up PR for #589, which is also based on it
* Extracts fxutil into libs pkg
* Removes unused code
* Re-introduces ProvideAs and ReplaceAs to fxutil
* Uses the above on the node


Patch:
diff --git a/README.md b/README.md
index aaf9e88d..aa7c1a78 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,12 @@
 # Celestia Node
 
-[![Go Reference](https://pkg.go.dev/badge/github.com/celestiaorg/celestia-node.svg)](https://pkg.go.dev/github.com/celestiaorg/celestia-node)
-[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/celestiaorg/celestia-node)](https://github.com/celestiaorg/celestia-node/releases/latest)
 [![test](https://github.com/celestiaorg/celestia-node/actions/workflows/test.yml/badge.svg)](https://github.com/celestiaorg/celestia-node/actions/workflows/test.yml)
 [![lint](https://github.com/celestiaorg/celestia-node/actions/workflows/lint.yml/badge.svg)](https://github.com/celestiaorg/celestia-node/actions/workflows/lint.yml)
 [![Go Report Card](https://goreportcard.com/badge/github.com/celestiaorg/celestia-node)](https://goreportcard.com/report/github.com/celestiaorg/celestia-node)
 [![codecov](https://codecov.io/gh/celestiaorg/celestia-node/branch/main/graph/badge.svg?token=CWGA4RLDS9)](https://codecov.io/gh/celestiaorg/celestia-node)
 
-
 Golang implementation of Celestia's data availability node types (`light` | `full` | `bridge`).
 
-The celestia-node types described above comprise the celestia data availability (DA) network. 
-
-The DA network wraps the celestia-core consensus network by listening for blocks from the consensus 
-network and making them digestible for data availability sampling (DAS). 
-
-Continue reading [here](https://blog.celestia.org/celestia-mvp-release-data-availability-sampling-light-clients)
-if you want to learn more about DAS and how it enables secure and scalable access to celestia chain data.
-
 ### Minimum requirements
 
 | Requirement | Notes            |
@@ -27,32 +16,6 @@ if you want to learn more about DAS and how it enables secure and scalable acces
 ### Installation
 
 ```sh
-git clone https://github.com/celestiaorg/celestia-node.git 
-```
-```
+git clone https://github.com/celestiaorg/celestia-node.git
 make install
 ```
-
-### Node types
-* **Bridge** nodes - relay blocks from the celestia consensus network to the celestia data availability 
-(DA) network
-* **Full** nodes - fully reconstruct and store blocks by sampling the DA network for shares
-* **Light** nodes - verify the availability of block data by sampling the DA network for shares
-
-More information can be found [here](https://github.com/celestiaorg/celestia-node/blob/main/docs/adr/adr-003-march2022-testnet.md#legend).
-
-### Run a node
-
-`<node_type>` can be `bridge`, `full` or `light`.
-
-```sh
-celestia <node_type> init 
-```
-```sh
-celestia <node_type> start
-``` 
-
-### Package-specific documentation
-* [Header](./service/header/doc.go)
-* [Share](./service/share/doc.go)
-* [DAS](./das/doc.go)
diff --git a/docs/adr/adr-004-state-interaction.md b/docs/adr/adr-004-state-interaction.md
index 68874875..70c8f775 100644
--- a/docs/adr/adr-004-state-interaction.md
+++ b/docs/adr/adr-004-state-interaction.md
@@ -67,19 +67,6 @@ type StateAccessor interface {
    respond to the queries without relaying queries to celestia-core (*to be scoped out and implemented in later
    iterations*)
 
-### Verification of Balances
-In order to check that the balances returned via the `AccountBalance` query are correct, it is necessary to also request
-Merkle proofs from the celestia-app and verify them against the latest head's `AppHash`. In order for the `StateAccessor`
-to do this, it would need access to the `header.Store`'s `Head()` method in order to get the latest known header of the 
-node and check its `AppHash`.
-
-### Availability of `StateService` during sync
-The `Syncer` in the `header`  package provides one public method, `Finished()`, that indicates whether the syncer has 
-finished syncing. Introducing the availability of `StateService` would require extending the public API for `Syncer` 
-with an additional method, `NetworkHead()`, in order to be able to fetch *current* state from the network. The `Syncer`
-would then have to be passed to any implementation of `StateService` upon construction and relied on in order to access 
-the network head even if the syncer is still syncing, as the network head is still verified even during sync.
-
 ### 1. Core Implementation of `StateAccessor`: `CoreAccess`
 
 `CoreAccess` will be the direct RPC connection implementation of `StateAccessor`. It will maintain a gRPC connection
diff --git a/libs/fxutil/fxutil.go b/libs/fxutil/fxutil.go
new file mode 100644
index 00000000..a03ab0cb
--- /dev/null
+++ b/libs/fxutil/fxutil.go
@@ -0,0 +1,56 @@
+package fxutil
+
+import (
+	"context"
+
+	"go.uber.org/fx"
+)
+
+// WithLifecycle wraps a context to be canceled when the lifecycle stops.
+func WithLifecycle(ctx context.Context, lc fx.Lifecycle) context.Context {
+	ctx, cancel := context.WithCancel(ctx)
+	lc.Append(fx.Hook{
+		OnStop: func(_ context.Context) error {
+			cancel()
+			return nil
+		},
+	})
+	return ctx
+}
+
+// SupplyIf supplies DI if a condition is met.
+func SupplyIf(cond bool, val ...interface{}) fx.Option {
+	if cond {
+		return fx.Supply(val...)
+	}
+	return fx.Options()
+}
+
+// ProvideIf provides a given constructor if a condition is met.
+func ProvideIf(cond bool, ctor ...interface{}) fx.Option {
+	if cond {
+		return fx.Provide(ctor...)
+	}
+
+	return fx.Options()
+}
+
+// InvokeIf invokes a given function if a condition is met.
+func InvokeIf(cond bool, function interface{}) fx.Option {
+	if cond {
+		return fx.Invoke(function)
+	}
+	return fx.Options()
+}
+
+// ProvideAs creates an FX option that provides constructor 'cnstr' with the returned values types as 'cnstrs'
+// It is as simple utility that hides away FX annotation details.
+func ProvideAs(cnstr interface{}, cnstrs ...interface{}) fx.Option {
+	return fx.Provide(fx.Annotate(cnstr, fx.As(cnstrs...)))
+}
+
+// ReplaceAs creates an FX option that substitutes types defined by constructors 'cnstrs' with the value 'val'.
+// It is as simple utility that hides away FX annotation details.
+func ReplaceAs(val interface{}, cnstrs ...interface{}) fx.Option {
+	return fx.Replace(fx.Annotate(val, fx.As(cnstrs...)))
+}
diff --git a/node/components.go b/node/components.go
index 81138efc..f32a62b4 100644
--- a/node/components.go
+++ b/node/components.go
@@ -9,6 +9,8 @@ import (
 	"github.com/raulk/go-watchdog"
 	"go.uber.org/fx"
 
+	"github.com/celestiaorg/celestia-node/libs/fxutil"
+
 	nodecore "github.com/celestiaorg/celestia-node/node/core"
 
 	"github.com/celestiaorg/celestia-node/node/p2p"
@@ -65,7 +67,7 @@ func baseComponents(cfg *Config, store Store) fx.Option {
 		fx.Provide(services.HeaderStore),
 		fx.Invoke(services.HeaderStoreInit(&cfg.Services)),
 		fx.Provide(services.HeaderSyncer),
-		fx.Provide(fx.Annotate(services.P2PSubscriber, fx.As(new(header.Broadcaster), new(header.Subscriber)))),
+		fxutil.ProvideAs(services.P2PSubscriber, new(header.Broadcaster), new(header.Subscriber)),
 		fx.Provide(services.HeaderP2PExchangeServer),
 		fx.Invoke(invokeWatchdog(store.Path())),
 		p2p.Components(cfg.P2P),
diff --git a/node/core/core.go b/node/core/core.go
index db875b67..de358004 100644
--- a/node/core/core.go
+++ b/node/core/core.go
@@ -7,6 +7,8 @@ import (
 	format "github.com/ipfs/go-ipld-format"
 	"go.uber.org/fx"
 
+	"github.com/celestiaorg/celestia-node/libs/fxutil"
+
 	"github.com/celestiaorg/celestia-node/core"
 	"github.com/celestiaorg/celestia-node/service/header"
 )
@@ -26,7 +28,7 @@ func DefaultConfig() Config {
 func Components(cfg Config) fx.Option {
 	return fx.Options(
 		fx.Provide(core.NewBlockFetcher),
-		fx.Provide(fx.Annotate(header.NewCoreExchange, fx.As(new(header.Exchange)))),
+		fxutil.ProvideAs(header.NewCoreExchange, new(header.Exchange)),
 		fx.Invoke(HeaderCoreListener),
 		fx.Provide(func(lc fx.Lifecycle) (core.Client, error) {
 			if cfg.RemoteAddr == "" {
diff --git a/node/fxutil/options.go b/node/fxutil/options.go
deleted file mode 100644
index 901b68c8..00000000
--- a/node/fxutil/options.go
+++ /dev/null
@@ -1,269 +0,0 @@
-package fxutil
-
-import (
-	"fmt"
-	"reflect"
-
-	"go.uber.org/fx"
-)
-
-// FIXME: This file is intended to be removed once the upstream issue https://github.com/uber-go/fx/issues/825
-//  is resolved
-
-// Option mimics fx.Option but provides one more OverrideSupply feature.
-type Option func(*fxOptions) error
-
-// ParseOptions parses multiple given instances of Option and coverts them into a fx.Option.
-func ParseOptions(opts ...Option) (fx.Option, error) {
-	fopts := &fxOptions{
-		overrideSupplies: map[reflect.Type]*override{},
-		provides:         map[reflect.Type]*provide{},
-		supplies:         map[reflect.Type]interface{}{},
-	}
-	for _, opt := range opts {
-		err := opt(fopts)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	parsed := make([]fx.Option, 0)
-out:
-	for tp, val := range fopts.provides {
-		allAs := make([]fx.Annotation, len(val.as))
-		for i, as := range val.as {
-			ovr, ok := fopts.overrideSupplies[as]
-			if ok && !ovr.used {
-				ovr.used = true
-				continue out
-			}
-
-			allAs[i] = fx.As(reflect.New(as).Interface())
-		}
-
-		if len(allAs) == 0 {
-			// exclude provides that are overridden
-			// this has a potentially negative effect for provides with more than one return parameters
-			for i := 0; i < tp.NumOut(); i++ {
-				ovr, ok := fopts.overrideSupplies[tp.Out(i)]
-				if ok && !ovr.used {
-					ovr.used = true
-					continue out
-				}
-			}
-		}
-
-		parsed = append(parsed, fx.Provide(fx.Annotate(val.target, allAs...)))
-	}
-
-	for tp, val := range fopts.supplies {
-		ovr, ok := fopts.overrideSupplies[tp]
-		if ok && !ovr.used {
-			ovr.used = true
-			continue
-		}
-
-		switch tp.Kind() {
-		case reflect.Interface:
-			// if type is an interface - we have to say FX to build the `val` as the interface
-			parsed = append(parsed, fx.Supply(fx.Annotate(
-				val,
-				fx.As(reflect.New(tp).Interface()),
-			)))
-		default:
-			parsed = append(parsed, fx.Supply(val))
-		}
-	}
-
-	for _, val := range fopts.invokes {
-		parsed = append(parsed, fx.Invoke(val))
-	}
-
-	for tp, val := range fopts.overrideSupplies {
-		if !val.used {
-			return nil, fmt.Errorf("fxutil: nothing to override for the given %s", tp)
-		}
-
-		switch tp.Kind() {
-		case reflect.Interface:
-			// if type is an interface - we have to say FX to build the `val` as the interface
-			parsed = append(parsed, fx.Supply(fx.Annotate(
-				val.target,
-				fx.As(reflect.New(tp).Interface()),
-			)))
-		default:
-			parsed = append(parsed, fx.Supply(val.target))
-		}
-	}
-
-	return fx.Options(parsed...), nil
-}
-
-// OverrideSupply overwrites values passed to Provide and Supply.
-// It mimics fx.Supply with one difference - it does not error if there are multiple instances of a type
-// are supplied/provided. Instead, OverrideSupply forces the supply and overrides other Supply and Provide.
-//
-// Only one overriding must exist for a type.
-//
-// Only recvs ptr to a value or an interface.
-// To override an interface a ptr to the interface should be provided:
-//
-//  var r io.Reader
-//  OverrideSupply(&r)
-//
-// and not:
-//
-//  var r io.Reader
-//  OverrideSupply(r)
-//
-// Otherwise, real value of r will be provided, e.g. *bytes.Buffer.
-func OverrideSupply(vals ...interface{}) Option {
-	return func(o *fxOptions) error {
-		for _, val := range vals {
-			refVal := reflect.ValueOf(val)
-			if refVal.Kind() != reflect.Ptr {
-				return fmt.Errorf("fxutil: only ptrs are allowed in OverrideSupply")
-			}
-
-			tp := refVal.Type()
-			if tp.Elem().Kind() == reflect.Interface {
-				// if ptr to an interface is passed - unwrap the interface type and a real value
-				refVal, tp = refVal.Elem().Elem(), tp.Elem()
-			} else if tp.Elem().Kind() != reflect.Struct {
-				// if prt is not pointing at struct, e.g. Slice/String/... - unwrap the value
-				refVal, tp = refVal.Elem(), tp.Elem()
-			}
-
-			if !refVal.IsValid() || refVal.IsZero() {
-				// All the really invalid cases are checked and errors for them are thrown above the line.
-				// Regarding this case, it is basically nil or zero value, and it is usually fine to allow zeros to be
-				// passed in the optional pattern, e.g WithSomething(nil), so you don't need to check for
-				// if something != nil { WithSomething(something) }.
-				continue
-			}
-
-			_, ok := o.overrideSupplies[tp]
-			if ok {
-				return fmt.Errorf("fxutil: already overridden")
-			}
-			o.overrideSupplies[tp] = &override{target: refVal.Interface()}
-		}
-
-		return nil
-	}
-}
-
-// Supply mimics fx.Supply.
-func Supply(vals ...interface{}) Option {
-	return func(o *fxOptions) error {
-		for _, val := range vals {
-			tp := reflect.TypeOf(val)
-			_, ok := o.supplies[tp]
-			if ok {
-				return fmt.Errorf("fxutil: already supplied")
-			}
-
-			o.supplies[tp] = val
-		}
-
-		return nil
-	}
-}
-
-// SupplyAs mimics fx.Supply(fx.Annotate(fx.As())).
-func SupplyAs(val interface{}, as interface{}) Option {
-	return func(o *fxOptions) error {
-		tp := reflect.TypeOf(as)
-		if tp.Kind() != reflect.Ptr && tp.Elem().Kind() != reflect.Interface {
-			return fmt.Errorf("fxutil: As values must be ptr to an interface")
-		}
-		tp = tp.Elem()
-
-		_, ok := o.supplies[tp]
-		if ok {
-			return fmt.Errorf("fxutil: already supplied")
-		}
-
-		o.supplies[tp] = val
-		return nil
-	}
-}
-
-// Provide mimics fx.Provide.
-// Provided ctors can be overridden by OverrideSupply.
-func Provide(vals ...interface{}) Option {
-	opts := make([]Option, len(vals))
-	for i, val := range vals {
-		opts[i] = ProvideAs(val)
-	}
-	return Options(opts...)
-}
-
-// ProvideAs mimics fx.Provide(fx.Annotate(fx.As())).
-func ProvideAs(val interface{}, as ...interface{}) Option {
-	return func(o *fxOptions) error {
-		tp := reflect.TypeOf(val)
-		if tp.Kind() != reflect.Func || tp.NumOut() == 0 {
-			return fmt.Errorf("fxutil: ctor functions must be passed to Provide and have return params")
-		}
-
-		defAs := make([]reflect.Type, len(as))
-		for i, as := range as {
-			tp := reflect.TypeOf(as)
-			if tp.Kind() != reflect.Ptr && tp.Elem().Kind() != reflect.Interface {
-				return fmt.Errorf("fxutil: As values must be ptr to an interface")
-			}
-
-			defAs[i] = tp.Elem()
-		}
-
-		_, ok := o.provides[tp]
-		if ok {
-			return fmt.Errorf("fxutil: already provided")
-		}
-
-		o.provides[tp] = &provide{
-			target: val,
-			as:     defAs,
-		}
-		return nil
-	}
-}
-
-// Invoke mimics fx.Invoke.
-func Invoke(vals ...interface{}) Option {
-	return func(o *fxOptions) error {
-		o.invokes = append(o.invokes, vals...)
-		return nil
-	}
-}
-
-// Options combines multiples options into a one Option.
-func Options(opts ...Option) Option {
-	return func(o *fxOptions) error {
-		for _, opt := range opts {
-			err := opt(o)
-			if err != nil {
-				return err
-			}
-		}
-		return nil
-	}
-}
-
-type fxOptions struct {
-	overrideSupplies map[reflect.Type]*override
-	provides         map[reflect.Type]*provide
-	supplies         map[reflect.Type]interface{}
-	invokes          []interface{}
-}
-
-type override struct {
-	target interface{}
-	used   bool
-}
-
-type provide struct {
-	target interface{}
-	as     []reflect.Type
-}
diff --git a/node/fxutil/util.go b/node/fxutil/util.go
deleted file mode 100644
index f15bbdf7..00000000
--- a/node/fxutil/util.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package fxutil
-
-import (
-	"context"
-
-	"go.uber.org/fx"
-)
-
-// WithLifecycle wraps a context to be canceled when the lifecycle stops.
-func WithLifecycle(ctx context.Context, lc fx.Lifecycle) context.Context {
-	ctx, cancel := context.WithCancel(ctx)
-	lc.Append(fx.Hook{
-		OnStop: func(_ context.Context) error {
-			cancel()
-			return nil
-		},
-	})
-	return ctx
-}
-
-// SupplyIf supplies DI if a condition is met.
-func SupplyIf(cond bool, val ...interface{}) Option {
-	if cond {
-		return Supply(val...)
-	}
-	return Options()
-}
-
-// ProvideIf provides a given constructor if a condition is met.
-func ProvideIf(cond bool, ctor ...interface{}) Option {
-	if cond {
-		return Provide(ctor...)
-	}
-
-	return Options()
-}
-
-// InvokeIf invokes a given function if a condition is met.
-func InvokeIf(cond bool, function interface{}) Option {
-	if cond {
-		return Invoke(function)
-	}
-	return Options()
-}
diff --git a/node/p2p/bitswap.go b/node/p2p/bitswap.go
index 9d0d26ac..db8581de 100644
--- a/node/p2p/bitswap.go
+++ b/node/p2p/bitswap.go
@@ -14,7 +14,7 @@ import (
 	"github.com/libp2p/go-libp2p-core/routing"
 	"go.uber.org/fx"
 
-	"github.com/celestiaorg/celestia-node/node/fxutil"
+	"github.com/celestiaorg/celestia-node/libs/fxutil"
 	nparams "github.com/celestiaorg/celestia-node/params"
 )
 
diff --git a/node/p2p/host.go b/node/p2p/host.go
index d22915a4..a9276eb2 100644
--- a/node/p2p/host.go
+++ b/node/p2p/host.go
@@ -15,7 +15,7 @@ import (
 	routedhost "github.com/libp2p/go-libp2p/p2p/host/routed"
 	"go.uber.org/fx"
 
-	"github.com/celestiaorg/celestia-node/node/fxutil"
+	"github.com/celestiaorg/celestia-node/libs/fxutil"
 	nparams "github.com/celestiaorg/celestia-node/params"
 )
 
diff --git a/node/p2p/pubsub.go b/node/p2p/pubsub.go
index 86e80c09..0f39829f 100644
--- a/node/p2p/pubsub.go
+++ b/node/p2p/pubsub.go
@@ -9,7 +9,7 @@ import (
 	"github.com/minio/blake2b-simd"
 	"go.uber.org/fx"
 
-	"github.com/celestiaorg/celestia-node/node/fxutil"
+	"github.com/celestiaorg/celestia-node/libs/fxutil"
 )
 
 // PubSub provides a constructor for PubSub protocol with GossipSub routing.
diff --git a/node/p2p/routing.go b/node/p2p/routing.go
index 2b292188..e10a2fd9 100644
--- a/node/p2p/routing.go
+++ b/node/p2p/routing.go
@@ -11,7 +11,7 @@ import (
 	routinghelpers "github.com/libp2p/go-libp2p-routing-helpers"
 	"go.uber.org/fx"
 
-	"github.com/celestiaorg/celestia-node/node/fxutil"
+	"github.com/celestiaorg/celestia-node/libs/fxutil"
 	nparams "github.com/celestiaorg/celestia-node/params"
 )
 
diff --git a/node/services/service.go b/node/services/service.go
index 15e7e514..c2a12263 100644
--- a/node/services/service.go
+++ b/node/services/service.go
@@ -12,10 +12,9 @@ import (
 	pubsub "github.com/libp2p/go-libp2p-pubsub"
 	"go.uber.org/fx"
 
-	"github.com/celestiaorg/celestia-node/params"
-
 	"github.com/celestiaorg/celestia-node/das"
-	"github.com/celestiaorg/celestia-node/node/fxutil"
+	"github.com/celestiaorg/celestia-node/libs/fxutil"
+	"github.com/celestiaorg/celestia-node/params"
 	"github.com/celestiaorg/celestia-node/service/header"
 	"github.com/celestiaorg/celestia-node/service/share"
 )
diff --git a/node/settings.go b/node/settings.go
index 0bd4e15a..8039eb17 100644
--- a/node/settings.go
+++ b/node/settings.go
@@ -8,6 +8,7 @@ import (
 	"go.uber.org/fx"
 
 	"github.com/celestiaorg/celestia-node/core"
+	"github.com/celestiaorg/celestia-node/libs/fxutil"
 	"github.com/celestiaorg/celestia-node/node/p2p"
 	"github.com/celestiaorg/celestia-node/params"
 )
@@ -32,7 +33,7 @@ func WithNetwork(net params.Network) Option {
 // WithP2PKey sets custom Ed25519 private key for p2p networking.
 func WithP2PKey(key crypto.PrivKey) Option {
 	return func(sets *settings) {
-		sets.opts = append(sets.opts, fx.Replace(fx.Annotate(key, fx.As(new(crypto.PrivKey)))))
+		sets.opts = append(sets.opts, fxutil.ReplaceAs(key, new(crypto.PrivKey)))
 	}
 }
 
@@ -51,7 +52,7 @@ func WithP2PKeyStr(key string) Option {
 			return
 		}
 
-		sets.opts = append(sets.opts, fx.Replace(fx.Annotate(key, fx.As(new(crypto.PrivKey)))))
+		sets.opts = append(sets.opts, fxutil.ReplaceAs(key, new(crypto.PrivKey)))
 	}
 
 }
@@ -59,13 +60,13 @@ func WithP2PKeyStr(key string) Option {
 // WithHost sets custom Host's data for p2p networking.
 func WithHost(hst host.Host) Option {
 	return func(sets *settings) {
-		sets.opts = append(sets.opts, fx.Replace(fx.Annotate(hst, fx.As(new(p2p.HostBase)))))
+		sets.opts = append(sets.opts, fxutil.ReplaceAs(hst, new(p2p.HostBase)))
 	}
 }
 
 // WithCoreClient sets custom client for core process
 func WithCoreClient(client core.Client) Option {
 	return func(sets *settings) {
-		sets.opts = append(sets.opts, fx.Replace(fx.Annotate(client, fx.As(new(core.Client)))))
+		sets.opts = append(sets.opts, fxutil.ReplaceAs(client, new(core.Client)))
 	}
 }
diff --git a/service/header/doc.go b/service/header/doc.go
deleted file mode 100644
index 98ca7567..00000000
--- a/service/header/doc.go
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-Package header contains all services related to generating, requesting, syncing and storing
-ExtendedHeaders.
-
-An ExtendedHeader is similar to a regular block header from celestia-core, but "extended" by adding
-the DataAvailabilityHeader (DAH), ValidatorSet and Commit in order to allow for light and full nodes
-to reconstruct block data by referencing the DAH.
-
-ExtendedHeaders are generated by bridge nodes that listen to the celestia-core network for blocks,
-validate and extend the block data in order to generate the DAH, and request both the ValidatorSet
-and Commit for that block height from the celestia-core network. Bridge nodes then package that data
-up into an ExtendedHeader and broadcast it to the 'header-sub' GossipSub topic (HeaderSub). All nodes subscribed
-to HeaderSub will receive and validate the ExtendedHeader, and store it, making it available to all
-other dependent services (such as the DataAvailabilitySampler, or DASer) to access.
-
-There are 5 main components in the header package:
-	1. CoreListener listens for new blocks from the celestia-core network (run by bridge nodes only),
-	   extends them, generates a new ExtendedHeader, and publishes it to the HeaderSub.
-	2. P2PSubscriber listens for new ExtendedHeaders from the Celestia Data Availability (DA) network (via
-	   the HeaderSub)
-	3. P2PExchange or CoreExchange request ExtendedHeaders from other celestia DA nodes (default for
-	   full and light nodes) or from a celestia-core node connection (bridge nodes only)
-	4. Syncer manages syncing of past and recent ExtendedHeaders from either the DA network or a celestia-core
-       connection (bridge nodes only).
-	5. Store manages storing ExtendedHeaders and making them available for access by other dependent services.
-
-For bridge nodes, the general flow of the header Service is as follows:
-	1. CoreListener listens for new blocks from the celestia-core connection
-	2. CoreListener validates the block and generates the ExtendedHeader, simultaneously storing the
-       extended block shares to disk
-	3. CoreListener publishes the new ExtendedHeader to HeaderSub, notifying all subscribed peers of the new
-	   ExtendedHeader
-	4. Syncer is already subscribed to the HeaderSub, so it receives new ExtendedHeaders locally from
-       the CoreListener and stores them to disk via Store.
-	4a. If the celestia-core connection is started simultaneously with the bridge node, then the celestia-core
-       connection will handle the syncing component, piping every synced block to the CoreListener
-	4b. If the celestia-core connection is already synced to the network, the Syncer handles requesting past
-		headers up to the network head from the celestia-core connection (using CoreExchange rather than P2PExchange).
-
-For full and light nodes, the general flow of the header Service is as follows:
-	1. Syncer listens for new ExtendedHeaders from HeaderSub
-	2. If there is a gap between the local head of chain and the new, validated network head, the Syncer
-	   kicks off a sync routine to request all ExtendedHeaders between local head and network head.
-	3. While the Syncer requests headers between the local head and network head in batches, it appends them to the subjective chain via Store with the last batched header as the new local head.
-*/
-package header
diff --git a/service/share/interface.go b/service/share/availability.go
similarity index 100%
rename from service/share/interface.go
rename to service/share/availability.go
diff --git a/service/share/doc.go b/service/share/doc.go
deleted file mode 100644
index fd3739ad..00000000
--- a/service/share/doc.go
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-Package share contains logic related to the retrieval and random sampling of shares of
-block data.
-
-Though this package contains several useful methods for getting specific shares and/or
-sampling them at random, a particularly useful method is GetSharesByNamespace which retrieves
-all shares of block data of the given namespace.ID from the block associated with the given
-DataAvailabilityHeader (DAH, but referred to as Root within this package).
-
-This package also contains both implementations of the Availability interface: lightAvailability
-which samples for 16 shares of block data (enough to verify the block's availability on the network)
-and fullAvailability which samples for as many shares as necessary to fully reconstruct the block data.
-*/
-package share
diff --git a/service/share/light_availability.go b/service/share/light_availability.go
index f0eab99e..a6acc223 100644
--- a/service/share/light_availability.go
+++ b/service/share/light_availability.go
@@ -14,7 +14,7 @@ var DefaultSampleAmount = 16
 
 // lightAvailability implements Availability using Data Availability Sampling technique.
 // It is light because it does not require the downloading of all the data to verify
-// its availability. It is assumed that there are a lot of lightAvailability instances
+// its availability. It is assumed that there are lots of lightAvailability instances
 // on the network doing sampling over the same Root to collectively verify its availability.
 type lightAvailability struct {
 	getter format.NodeGetter


Test patch:
diff --git a/docs/adr/adr-003-march2022-testnet.md b/docs/adr/adr-003-march2022-testnet.md
index 91ea2d00..12a43272 100644
--- a/docs/adr/adr-003-march2022-testnet.md
+++ b/docs/adr/adr-003-march2022-testnet.md
@@ -9,7 +9,6 @@
 ## Changelog
 
 * 2021-11-25: initial draft
-* 2022-03-30: update to bridge node definition
 
 <hr style="border:2px solid gray"> </hr>
 
@@ -21,17 +20,11 @@ Refers to the data availability "halo" network created around the Core network.
 
 ### **Bridge Node**
 
-A **bridge** node is a node that is connected to a celestia-core node via RPC. It receives a remote address from a 
-running celestia-core node and listens for blocks from celestia-core. For each new block from celestia-core, the **bridge**
-node performs basic validation on the block via `ValidateBasic()`, extends the block data, generates a Data Availability 
-Header (DAH) from the extended block data, and creates an `ExtendedHeader` from the block header and the DAH, and finally 
-broadcasts it to the data availability network (DA network).
-
-A **bridge** node does not care about what kind of celestia-core node it is connected to (validator or regular full node),
-it only cares that it has a direct RPC connection to a celestia-core node from which it can listen for new blocks.
-
-The name **bridge** was chosen as the purpose of this node type is to provide a mechanism to relay celestia-core blocks
-to the data availability network.  
+A **bridge** node is a **full** node that is connected to a Celestia Core node via RPC. It receives either a remote
+address from a running Core node or it can run a Core node as an embedded process, but the critical difference is that
+instead of reconstructing blocks via downloading enough shares from the network, it receives headers and blocks directly from its 
+trusted Core node, validating blocks, erasure coding them, and producing `ExtendedHeader`s to broadcast to the Celestia 
+DA network.
 
 ### **Full Node**
 
diff --git a/node/fxutil/options_test.go b/node/fxutil/options_test.go
deleted file mode 100644
index f047ad9b..00000000
--- a/node/fxutil/options_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-package fxutil
-
-import (
-	"bytes"
-	"io"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"go.uber.org/fx"
-	"go.uber.org/fx/fxtest"
-)
-
-func TestOverride(t *testing.T) {
-	tt := struct {
-		fx.In
-		Buf *bytes.Buffer
-		R   io.Reader
-		S   string
-	}{}
-
-	ovrS := "override"
-	prv := bytes.NewBuffer(nil)
-	ovr := bytes.NewBuffer([]byte("xyz"))
-
-	var prvR io.Reader = prv
-	var ovrR io.Reader = ovr
-
-	fopt, err := ParseOptions(
-		Supply("supplied"),
-		Provide(func() *bytes.Buffer {
-			return prv
-		}),
-		Provide(func() io.Reader {
-			return prvR
-		}),
-		OverrideSupply(&ovrS),
-		OverrideSupply(ovr),
-		OverrideSupply(&ovrR),
-	)
-	require.NoError(t, err)
-
-	fxtest.New(t, fopt, fx.Populate(&tt), fx.NopLogger)
-	assert.Equal(t, ovr, tt.Buf)
-	assert.Equal(t, ovr, tt.R)
-	assert.Equal(t, ovrS, tt.S)
-}
-
-func TestProvideAs(t *testing.T) {
-	tt := struct {
-		fx.In
-		R io.Reader
-	}{}
-
-	fopt, err := ParseOptions(
-		ProvideAs(
-			func() *bytes.Buffer {
-				return bytes.NewBuffer([]byte("xyz"))
-			},
-			new(io.Reader),
-		),
-	)
-	require.NoError(t, err)
-
-	fxtest.New(t, fopt, fx.Populate(&tt), fx.NopLogger)
-	assert.NotNil(t, tt.R)
-}
-
-func TestSupplyAs(t *testing.T) {
-	tt := struct {
-		fx.In
-		R io.Reader
-	}{}
-
-	fopt, err := ParseOptions(
-		SupplyAs(bytes.NewBuffer([]byte("xyz")), new(io.Reader)),
-	)
-	require.NoError(t, err)
-
-	fxtest.New(t, fopt, fx.Populate(&tt), fx.NopLogger)
-	assert.NotNil(t, tt.R)
-}