gitlab.com/jokerrs1/Sia@v1.3.2/node/node.go (about) 1 // Package node provides tooling for creating a Sia node. Sia nodes consist of a 2 // collection of modules. The node package gives you tools to easily assemble 3 // various combinations of modules with varying dependencies and settings, 4 // including templates for assembling sane no-hassle Sia nodes. 5 package node 6 7 // TODO: Add support for the explorer. 8 9 // TODO: Add support for custom dependencies and parameters for all of the 10 // modules. 11 12 import ( 13 "path/filepath" 14 15 "github.com/NebulousLabs/Sia/modules" 16 "github.com/NebulousLabs/Sia/modules/consensus" 17 "github.com/NebulousLabs/Sia/modules/gateway" 18 "github.com/NebulousLabs/Sia/modules/host" 19 "github.com/NebulousLabs/Sia/modules/miner" 20 "github.com/NebulousLabs/Sia/modules/renter" 21 "github.com/NebulousLabs/Sia/modules/transactionpool" 22 "github.com/NebulousLabs/Sia/modules/wallet" 23 24 "github.com/NebulousLabs/errors" 25 ) 26 27 // NodeParams contains a bunch of parameters for creating a new test node. As 28 // there are many options, templates are provided that you can modify which 29 // cover the most common use cases. 30 // 31 // Each module is created separately. There are several ways to create a module, 32 // though not all methods are currently available for each module. You should 33 // only use one method for creating a module, using multiple methods will cause 34 // an error. 35 // + Indicate with the 'CreateModule' bool that a module should be created 36 // automatically. To create the module with custom dependencies, pass the 37 // custom dependencies in using the 'ModuleDependencies' field. 38 // + Pass an existing module in directly. 39 // + Set 'CreateModule' to false and do not pass in an existing module. 40 // This will result in a 'nil' module, meaning the node will not have 41 // that module. 42 type NodeParams struct { 43 // Flags to indicate which modules should be created automatically by the 44 // server. If you are providing a pre-existing module, do not set the flag 45 // for that module. 46 // 47 // NOTE / TODO: The code does not currently enforce this, but you should not 48 // provide a custom module unless all of its dependencies are also custom. 49 // Example: if the ConsensusSet is custom, the Gateway should also be 50 // custom. The TransactionPool however does not need to be custom in this 51 // example. 52 CreateConsensusSet bool 53 CreateExplorer bool 54 CreateGateway bool 55 CreateHost bool 56 CreateMiner bool 57 CreateRenter bool 58 CreateTransactionPool bool 59 CreateWallet bool 60 61 // Custom modules - if the modules is provided directly, the provided 62 // module will be used instead of creating a new one. If a custom module is 63 // provided, the 'omit' flag for that module must be set to false (which is 64 // the default setting). 65 ConsensusSet modules.ConsensusSet 66 Explorer modules.Explorer 67 Gateway modules.Gateway 68 Host modules.Host 69 Miner modules.TestMiner 70 Renter modules.Renter 71 TransactionPool modules.TransactionPool 72 Wallet modules.Wallet 73 74 // The high level directory where all the persistence gets stored for the 75 // moudles. 76 Dir string 77 } 78 79 // Node is a collection of Sia modules operating together as a Sia node. 80 type Node struct { 81 // The modules of the node. Modules that are not initialized will be nil. 82 ConsensusSet modules.ConsensusSet 83 Explorer modules.Explorer 84 Gateway modules.Gateway 85 Host modules.Host 86 Miner modules.TestMiner 87 Renter modules.Renter 88 TransactionPool modules.TransactionPool 89 Wallet modules.Wallet 90 91 // The high level directory where all the persistence gets stored for the 92 // moudles. 93 Dir string 94 } 95 96 // Close will call close on every module within the node, combining and 97 // returning the errors. 98 func (n *Node) Close() (err error) { 99 if n.Explorer != nil { 100 err = errors.Compose(n.Explorer.Close()) 101 } 102 if n.Miner != nil { 103 err = errors.Compose(n.Miner.Close()) 104 } 105 if n.Host != nil { 106 err = errors.Compose(n.Host.Close()) 107 } 108 if n.Renter != nil { 109 err = errors.Compose(n.Renter.Close()) 110 } 111 if n.Wallet != nil { 112 err = errors.Compose(n.Wallet.Close()) 113 } 114 if n.TransactionPool != nil { 115 err = errors.Compose(n.TransactionPool.Close()) 116 } 117 if n.ConsensusSet != nil { 118 err = errors.Compose(n.ConsensusSet.Close()) 119 } 120 if n.Gateway != nil { 121 err = errors.Compose(n.Gateway.Close()) 122 } 123 return err 124 } 125 126 // New will create a new test node. The inputs to the function are the 127 // respective 'New' calls for each module. We need to use this awkward method 128 // of initialization because the siatest package cannot import any of the 129 // modules directly (so that the modules may use the siatest package to test 130 // themselves). 131 func New(params NodeParams) (*Node, error) { 132 dir := params.Dir 133 134 // Gateway. 135 g, err := func() (modules.Gateway, error) { 136 if params.CreateGateway && params.Gateway != nil { 137 return nil, errors.New("cannot both create a gateway and use a passed in gateway") 138 } 139 /* Template for dealing with optional dependencies: 140 if !params.CreateGateway && parames.GatewayDependencies != nil { 141 return nil, errors.New("cannot pass in gateway dependencies if you are not creating a gateway") 142 } 143 */ 144 if params.Gateway != nil { 145 return params.Gateway, nil 146 } 147 if !params.CreateGateway { 148 return nil, nil 149 } 150 /* Template for dealing with optional dependencies: 151 if params.GatewayDependencies == nil { 152 gateway.New(... 153 } else { 154 gateway.NewDeps(... 155 } 156 */ 157 return gateway.New("localhost:0", false, filepath.Join(dir, modules.GatewayDir)) 158 }() 159 if err != nil { 160 return nil, errors.Extend(err, errors.New("unable to create gateway")) 161 } 162 163 // Consensus. 164 cs, err := func() (modules.ConsensusSet, error) { 165 if params.CreateConsensusSet && params.ConsensusSet != nil { 166 return nil, errors.New("cannot both create consensus and use passed in consensus") 167 } 168 if params.ConsensusSet != nil { 169 return params.ConsensusSet, nil 170 } 171 if !params.CreateConsensusSet { 172 return nil, nil 173 } 174 return consensus.New(g, false, filepath.Join(dir, modules.ConsensusDir)) 175 }() 176 if err != nil { 177 return nil, errors.Extend(err, errors.New("unable to create consensus set")) 178 } 179 180 // Transaction Pool. 181 tp, err := func() (modules.TransactionPool, error) { 182 if params.CreateTransactionPool && params.TransactionPool != nil { 183 return nil, errors.New("cannot create transaction pool and also use custom transaction pool") 184 } 185 if params.TransactionPool != nil { 186 return params.TransactionPool, nil 187 } 188 if !params.CreateTransactionPool { 189 return nil, nil 190 } 191 return transactionpool.New(cs, g, filepath.Join(dir, modules.TransactionPoolDir)) 192 }() 193 if err != nil { 194 return nil, errors.Extend(err, errors.New("unable to create transaction pool")) 195 } 196 197 // Wallet. 198 w, err := func() (modules.Wallet, error) { 199 if params.CreateWallet && params.Wallet != nil { 200 return nil, errors.New("cannot create wallet and use custom wallet") 201 } 202 if params.Wallet != nil { 203 return params.Wallet, nil 204 } 205 if !params.CreateWallet { 206 return nil, nil 207 } 208 return wallet.New(cs, tp, filepath.Join(dir, modules.WalletDir)) 209 }() 210 if err != nil { 211 return nil, errors.Extend(err, errors.New("unable to create wallet")) 212 } 213 214 // Host. 215 h, err := func() (modules.Host, error) { 216 if params.CreateHost && params.Host != nil { 217 return nil, errors.New("cannot create host and use custom host") 218 } 219 if params.Host != nil { 220 return params.Host, nil 221 } 222 if !params.CreateHost { 223 return nil, nil 224 } 225 return host.New(cs, tp, w, "localhost:0", filepath.Join(dir, modules.HostDir)) 226 }() 227 if err != nil { 228 return nil, errors.Extend(err, errors.New("unable to create host")) 229 } 230 231 // Renter. 232 r, err := func() (modules.Renter, error) { 233 if params.CreateRenter && params.Renter != nil { 234 return nil, errors.New("cannot create renter and also use custom renter") 235 } 236 if params.Renter != nil { 237 return params.Renter, nil 238 } 239 if !params.CreateRenter { 240 return nil, nil 241 } 242 return renter.New(g, cs, w, tp, filepath.Join(dir, modules.RenterDir)) 243 }() 244 if err != nil { 245 return nil, errors.Extend(err, errors.New("unable to create renter")) 246 } 247 248 // Miner. 249 m, err := func() (modules.TestMiner, error) { 250 if params.CreateMiner && params.Miner != nil { 251 return nil, errors.New("cannot create miner and also use custom miner") 252 } 253 if params.Miner != nil { 254 return params.Miner, nil 255 } 256 if !params.CreateMiner { 257 return nil, nil 258 } 259 m, err := miner.New(cs, tp, w, filepath.Join(dir, modules.MinerDir)) 260 if err != nil { 261 return nil, err 262 } 263 return m, nil 264 }() 265 if err != nil { 266 return nil, errors.Extend(err, errors.New("unable to create miner")) 267 } 268 269 // Explorer. 270 e, err := func() (modules.Explorer, error) { 271 if !params.CreateExplorer && params.Explorer != nil { 272 return nil, errors.New("cannot create explorer and also use custom explorer") 273 } 274 if params.Explorer != nil { 275 return params.Explorer, nil 276 } 277 if !params.CreateExplorer { 278 return nil, nil 279 } 280 // TODO: Implement explorer. 281 return nil, errors.New("explorer not implemented") 282 }() 283 if err != nil { 284 return nil, errors.Extend(err, errors.New("unable to create explorer")) 285 } 286 287 return &Node{ 288 ConsensusSet: cs, 289 Explorer: e, 290 Gateway: g, 291 Host: h, 292 Miner: m, 293 Renter: r, 294 TransactionPool: tp, 295 Wallet: w, 296 297 Dir: dir, 298 }, nil 299 }