diff --git a/go.mod b/go.mod index 8479ebe..1f18a92 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.13 require ( github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da + github.com/hashicorp/go-multierror v1.1.0 github.com/pkg/errors v0.9.1 gitlab.com/NebulousLabs/Sia v1.4.8 go.etcd.io/bbolt v1.3.4 diff --git a/go.sum b/go.sum index 871240a..0df620c 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,10 @@ github.com/hanwen/go-fuse v1.0.0 h1:GxS9Zrn6c35/BnfiVsZVWmsG803xwE7eVRDvcf/BEVc= github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok= github.com/hanwen/go-fuse/v2 v2.0.2 h1:BtsqKI5RXOqDMnTgpCb0IWgvRgGLJdqYVZ/Hm6KgKto= github.com/hanwen/go-fuse/v2 v2.0.2/go.mod h1:HH3ygZOoyRbP9y2q7y3+JM6hPL+Epe29IbWaS0UA81o= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8= github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg= @@ -41,6 +45,7 @@ github.com/klauspost/reedsolomon v1.9.2 h1:E9CMS2Pqbv+C7tsrYad4YC9MfhnMVWhMRsTi7 github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= github.com/klauspost/reedsolomon v1.9.3 h1:N/VzgeMfHmLc+KHMD1UL/tNkfXAt8FnUqlgXGIduwAY= github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -85,6 +90,7 @@ gitlab.com/NebulousLabs/merkletree v0.0.0-20190207030457-bc4a11e31a0d h1:ObC0V0W gitlab.com/NebulousLabs/merkletree v0.0.0-20190207030457-bc4a11e31a0d/go.mod h1:xItahGeKIkh9BQfxDEX6O3eWxOxbLBPX738sXm0uVaQ= gitlab.com/NebulousLabs/merkletree v0.0.0-20200118113624-07fbf710afc4 h1:iuNdBfBg0umjOvrEf9MxGzK+NwAyE2oCZjDqUx9zVFs= gitlab.com/NebulousLabs/merkletree v0.0.0-20200118113624-07fbf710afc4/go.mod h1:0cjDwhA+Pv9ZQXHED7HUSS3sCvo2zgsoaMgE7MeGBWo= +gitlab.com/NebulousLabs/monitor v0.0.0-20191205095550-2b0fd3e1012a h1:fs891phmYZrVdaCVPXfHGDMpV5LWPKvnOMjx70EpJkw= gitlab.com/NebulousLabs/monitor v0.0.0-20191205095550-2b0fd3e1012a/go.mod h1:QxXtb5hIp2xQkfb+lzBDIqQIGEj22U7AkYCXO3hkhqc= gitlab.com/NebulousLabs/ratelimit v0.0.0-20180716154200-1308156c2eaf h1:B0oWvYNYeov4s6nzoVPN4qxdAanrlR9mx552axpnXmg= gitlab.com/NebulousLabs/ratelimit v0.0.0-20180716154200-1308156c2eaf/go.mod h1:vowDA1cdvtWW678ugB7L/yKT2pCN37aH6zYp9NF5Isc= @@ -103,8 +109,6 @@ go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191107222254-f4817d981bb6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -117,6 +121,7 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -128,8 +133,6 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= diff --git a/renter/meta.go b/renter/meta.go index 69840b3..a1cda6e 100644 --- a/renter/meta.go +++ b/renter/meta.go @@ -15,9 +15,11 @@ import ( "unsafe" "github.com/aead/chacha20/chacha" + "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "gitlab.com/NebulousLabs/Sia/crypto" "lukechampine.com/frand" + "lukechampine.com/us/hostdb" "lukechampine.com/us/merkle" "lukechampine.com/us/renterhost" @@ -190,7 +192,7 @@ func NewMetaFile(mode os.FileMode, size int64, hosts []hostdb.HostPublicKey, min // WriteMetaFile creates a gzipped tar archive containing m's index and shards, // and writes it to filename. The write is atomic. -func WriteMetaFile(filename string, m *MetaFile) error { +func WriteMetaFile(filename string, m *MetaFile) (err error) { // validate before writing if err := validateShards(m.Shards); err != nil { return errors.Wrap(err, "invalid shards") @@ -200,7 +202,11 @@ func WriteMetaFile(filename string, m *MetaFile) error { if err != nil { return errors.Wrap(err, "could not create archive") } - defer f.Close() + defer func() { + if e := f.Close(); e != nil && !errors.Is(e, os.ErrClosed) { + err = multierror.Append(err, e) + } + }() zip := gzip.NewWriter(f) tw := tar.NewWriter(zip) @@ -256,12 +262,16 @@ func WriteMetaFile(filename string, m *MetaFile) error { } // ReadMetaFile reads a metafile archive into memory. -func ReadMetaFile(filename string) (*MetaFile, error) { +func ReadMetaFile(filename string) (_ *MetaFile, err error) { f, err := os.Open(filename) if err != nil { return nil, errors.Wrap(err, "could not open archive") } - defer f.Close() + defer func() { + if e := f.Close(); e != nil { + err = multierror.Append(err, e) + } + }() zip, err := gzip.NewReader(f) if err != nil { return nil, errors.Wrap(err, "could not read gzip header") @@ -331,18 +341,26 @@ func ReadMetaFile(filename string) (*MetaFile, error) { } // ReadMetaIndex reads the index of a metafile without reading any shards. -func ReadMetaIndex(filename string) (MetaIndex, error) { +func ReadMetaIndex(filename string) (_ MetaIndex, err error) { f, err := os.Open(filename) if err != nil { return MetaIndex{}, errors.Wrap(err, "could not open archive") } - defer f.Close() + defer func() { + if e := f.Close(); e != nil { + err = multierror.Append(err, e) + } + }() zip, err := gzip.NewReader(f) if err != nil { return MetaIndex{}, errors.Wrap(err, "could not read gzip header") } - defer zip.Close() + defer func() { + if e := zip.Close(); e != nil { + err = multierror.Append(err, e) + } + }() var index MetaIndex tr := tar.NewReader(zip) @@ -387,18 +405,26 @@ func MetaFileCanDownload(filename string) (bool, error) { // readMetaFileShards reads a metafile and returns its index and the number of // shards that represent fully-uploaded shards of the erasure-encoded file. -func readMetaFileShards(filename string) (MetaIndex, int, error) { +func readMetaFileShards(filename string) (_ MetaIndex, _ int, err error) { f, err := os.Open(filename) if err != nil { return MetaIndex{}, 0, errors.Wrap(err, "could not open archive") } - defer f.Close() + defer func() { + if e := f.Close(); e != nil { + err = multierror.Append(err, e) + } + }() zip, err := gzip.NewReader(f) if err != nil { return MetaIndex{}, 0, errors.Wrap(err, "could not read gzip header") } - defer zip.Close() + defer func() { + if e := zip.Close(); e != nil { + err = multierror.Append(err, e) + } + }() var haveIndex bool var index MetaIndex diff --git a/renter/proto/formcontract.go b/renter/proto/formcontract.go index 8a8895b..33b4097 100644 --- a/renter/proto/formcontract.go +++ b/renter/proto/formcontract.go @@ -6,10 +6,12 @@ import ( "sort" "time" + "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "gitlab.com/NebulousLabs/Sia/crypto" "gitlab.com/NebulousLabs/Sia/modules" "gitlab.com/NebulousLabs/Sia/types" + "lukechampine.com/us/ed25519hash" "lukechampine.com/us/hostdb" "lukechampine.com/us/renterhost" @@ -23,13 +25,17 @@ const ( // FormContract forms a contract with a host. The resulting contract will have // renterPayout coins in the renter output. -func FormContract(w Wallet, tpool TransactionPool, key ed25519.PrivateKey, host hostdb.ScannedHost, renterPayout types.Currency, startHeight, endHeight types.BlockHeight) (ContractRevision, []types.Transaction, error) { +func FormContract(w Wallet, tpool TransactionPool, key ed25519.PrivateKey, host hostdb.ScannedHost, renterPayout types.Currency, startHeight, endHeight types.BlockHeight) (_ ContractRevision, _ []types.Transaction, err error) { s, err := NewUnlockedSession(host.NetAddress, host.PublicKey, 0) if err != nil { return ContractRevision{}, nil, err } s.host = host - defer s.Close() + defer func() { + if e := s.Close(); e != nil { + err = multierror.Append(err, e) + } + }() return s.FormContract(w, tpool, key, renterPayout, startHeight, endHeight) } @@ -168,7 +174,10 @@ func (s *Session) FormContract(w Wallet, tpool TransactionPool, key ed25519.Priv err = w.SignTransaction(&txn, toSign) if err != nil { err = errors.Wrap(err, "failed to sign transaction") - s.sess.WriteResponse(nil, errors.New("internal error")) // don't want to reveal too much + // don't want to reveal too much + if e := s.sess.WriteResponse(nil, errors.New("internal error")); e != nil { + err = multierror.Append(err, e) + } return ContractRevision{}, nil, err } diff --git a/renter/proto/renew.go b/renter/proto/renew.go index ffb74dd..4bef600 100644 --- a/renter/proto/renew.go +++ b/renter/proto/renew.go @@ -5,6 +5,7 @@ import ( "math" "time" + "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "gitlab.com/NebulousLabs/Sia/build" "gitlab.com/NebulousLabs/Sia/crypto" @@ -17,13 +18,18 @@ import ( // RenewContract negotiates a new file contract and initial revision for data // already stored with a host. -func RenewContract(w Wallet, tpool TransactionPool, id types.FileContractID, key ed25519.PrivateKey, host hostdb.ScannedHost, renterPayout types.Currency, startHeight, endHeight types.BlockHeight) (ContractRevision, []types.Transaction, error) { +func RenewContract(w Wallet, tpool TransactionPool, id types.FileContractID, key ed25519.PrivateKey, host hostdb.ScannedHost, renterPayout types.Currency, startHeight, endHeight types.BlockHeight) (_ ContractRevision, _ []types.Transaction, err error) { s, err := NewUnlockedSession(host.NetAddress, host.PublicKey, 0) if err != nil { return ContractRevision{}, nil, err } s.host = host - defer s.Close() + defer func() { + if e := s.Close(); e != nil { + err = multierror.Append(err, e) + } + }() + if err := s.Lock(id, key); err != nil { return ContractRevision{}, nil, err } @@ -164,7 +170,9 @@ func (s *Session) RenewContract(w Wallet, tpool TransactionPool, renterPayout ty err = w.SignTransaction(&txn, toSign) if err != nil { err = errors.Wrap(err, "failed to sign transaction") - s.sess.WriteResponse(nil, err) + if e := s.sess.WriteResponse(nil, err); e != nil { + err = multierror.Append(err, e) + } return ContractRevision{}, nil, err } @@ -369,7 +377,9 @@ func (s *Session) RenewAndClearContract(w Wallet, tpool TransactionPool, renterP err = w.SignTransaction(&txn, toSign) if err != nil { err = errors.Wrap(err, "failed to sign transaction") - s.sess.WriteResponse(nil, err) + if e := s.sess.WriteResponse(nil, err); e != nil { + err = multierror.Append(err, e) + } return ContractRevision{}, nil, err } diff --git a/renter/proto/session.go b/renter/proto/session.go index d30e97a..8ce8d4a 100644 --- a/renter/proto/session.go +++ b/renter/proto/session.go @@ -13,10 +13,12 @@ import ( "sort" "time" + "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "gitlab.com/NebulousLabs/Sia/crypto" "gitlab.com/NebulousLabs/Sia/modules" "gitlab.com/NebulousLabs/Sia/types" + "lukechampine.com/us/ed25519hash" "lukechampine.com/us/hostdb" "lukechampine.com/us/merkle" @@ -384,7 +386,11 @@ func (s *Session) Read(w io.Writer, sections []renterhost.RPCReadRequestSection) // host will now stream back responses; ensure we send RPCLoopReadStop // before returning - defer s.sess.WriteResponse(&renterhost.RPCReadStop, nil) + defer func() { + if e := s.sess.WriteResponse(&renterhost.RPCReadStop, nil); e != nil { + err = multierror.Append(err, e) + } + }() var hostSig []byte for _, sec := range sections { // NOTE: normally, we would call ReadResponse here to read an AEAD RPC @@ -577,7 +583,9 @@ func (s *Session) Write(actions []renterhost.RPCWriteAction) (err error) { <-precompChan if newFileSize > 0 && !merkle.VerifyDiffProof(actions, s.rev.NumSectors(), proofHashes, leafHashes, oldRoot, newRoot, s.appendRoots) { err := ErrInvalidMerkleProof - s.sess.WriteResponse(nil, err) + if e := s.sess.WriteResponse(nil, err); e != nil { + err = multierror.Append(err, e) + } return err } @@ -701,11 +709,15 @@ func NewSession(hostIP modules.NetAddress, hostKey hostdb.HostPublicKey, id type return nil, err } if err := s.Lock(id, key); err != nil { - s.Close() + if e := s.Close(); e != nil { + err = multierror.Append(err, e) + } return nil, err } if _, err := s.Settings(); err != nil { - s.Close() + if e := s.Close(); e != nil { + err = multierror.Append(err, e) + } return nil, err } return s, nil @@ -727,10 +739,15 @@ func newUnlockedSession(hostIP modules.NetAddress, hostKey hostdb.HostPublicKey, } latency := time.Since(start) conn := &statsConn{Conn: tcpConn} - conn.SetDeadline(time.Now().Add(60 * time.Second)) + err = conn.SetDeadline(time.Now().Add(60 * time.Second)) + if err != nil { + return nil, err + } s, err := renterhost.NewRenterSession(conn, hostKey.Ed25519()) if err != nil { - conn.Close() + if e := conn.Close(); e != nil { + err = multierror.Append(err, e) + } return nil, err } return &Session{ diff --git a/renter/renterutil/filesystem.go b/renter/renterutil/filesystem.go index 16af1c1..631f268 100644 --- a/renter/renterutil/filesystem.go +++ b/renter/renterutil/filesystem.go @@ -11,8 +11,10 @@ import ( "sync" "time" + "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "gitlab.com/NebulousLabs/Sia/crypto" + "lukechampine.com/us/hostdb" "lukechampine.com/us/renter" ) @@ -460,11 +462,17 @@ func (fs *PseudoFS) Close() error { } delete(fs.files, fd) } + var err *multierror.Error for fd, d := range fs.dirs { - d.Close() + if e := d.Close(); e != nil { + err = multierror.Append(err, e) + } delete(fs.dirs, fd) } - return fs.hosts.Close() + if e := fs.hosts.Close(); e != nil { + err = multierror.Append(err, e) + } + return err.ErrorOrNil() } // NewFileSystem returns a new pseudo-filesystem rooted at root, which must be a diff --git a/renter/renterutil/hostset.go b/renter/renterutil/hostset.go index 21b1244..a557c69 100644 --- a/renter/renterutil/hostset.go +++ b/renter/renterutil/hostset.go @@ -5,6 +5,8 @@ import ( "sync" "time" + "github.com/hashicorp/go-multierror" + "github.com/pkg/errors" "gitlab.com/NebulousLabs/Sia/types" "lukechampine.com/us/hostdb" @@ -96,15 +98,18 @@ func (set *HostSet) HasHost(hostKey hostdb.HostPublicKey) bool { // Close closes all of the sessions in the set. func (set *HostSet) Close() error { + var err error for hostKey, lh := range set.sessions { lh.mu.Lock() if lh.s != nil { - lh.s.Close() + if e := lh.s.Close(); e != nil { + err = multierror.Append(err, e) + } lh.s = nil } delete(set.sessions, hostKey) } - return nil + return err } func (set *HostSet) acquire(host hostdb.HostPublicKey) (*proto.Session, error) {