Refactor/waku tidy 1 (#1958)

* Refactor tidy of waku package

* Added deprecation warning on whisper README.md

* Appeasing the lint gods and testing is good

* Place Whisper deprecation warning in the correct package README

:facepalm

* Implementing changes after team feedback

* More offerings to the lint gods

* Remove apparently redundant context params

* Correctly handle concurrent HandlePeer err

* Revert "Remove apparently redundant context params"

This reverts commit 557dbd0d64.

* Added note to waku/api.go about context

* renamed statusoptions and removed unused global

* Removed OnNewP2PEnvelopes() from WakuHost interface

* Matched v1 Peer with new interface sig

Also changed common/helper.go to common/helpers.go

* Formatting of waku tests and some additional error handling

* Changed version to 0.53.0

* Removed redundant type declaration

* Moved TopicToBloom function into a Topic{} method

* Moved GenerateSecureRandomData() into helpers.go
This commit is contained in:
Samuel Hawksby-Robinson 2020-05-01 19:14:01 +01:00 committed by GitHub
parent 0e27e464d3
commit 4d00656c41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 111 additions and 193 deletions

View File

@ -1 +1 @@
0.52.5
0.53.0

View File

@ -247,30 +247,11 @@ func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) {
// Bloom maps 4-bytes Topic into 64-byte bloom filter with 3 bits set (at most).
func (e *Envelope) Bloom() []byte {
if e.bloom == nil {
e.bloom = TopicToBloom(e.Topic)
e.bloom = e.Topic.ToBloom()
}
return e.bloom
}
// TopicToBloom converts the topic (4 bytes) to the bloom filter (64 bytes)
func TopicToBloom(topic TopicType) []byte {
b := make([]byte, BloomFilterSize)
var index [3]int
for j := 0; j < 3; j++ {
index[j] = int(topic[j])
if (topic[3] & (1 << uint(j))) != 0 {
index[j] += 256
}
}
for j := 0; j < 3; j++ {
byteIndex := index[j] / 8
bitIndex := index[j] % 8
b[byteIndex] = 1 << uint(bitIndex)
}
return b
}
// EnvelopeError code and optional description of the error.
type EnvelopeError struct {
Hash common.Hash

View File

@ -2,7 +2,10 @@ package common
import (
"crypto/ecdsa"
crand "crypto/rand"
"errors"
"fmt"
mrand "math/rand"
"github.com/ethereum/go-ethereum/common"
)
@ -52,6 +55,37 @@ func ContainsOnlyZeros(data []byte) bool {
return true
}
// GenerateSecureRandomData generates random data where extra security is required.
// The purpose of this function is to prevent some bugs in software or in hardware
// from delivering not-very-random data. This is especially useful for AES nonce,
// where true randomness does not really matter, but it is very important to have
// a unique nonce for every message.
func GenerateSecureRandomData(length int) ([]byte, error) {
x := make([]byte, length)
y := make([]byte, length)
res := make([]byte, length)
_, err := crand.Read(x)
if err != nil {
return nil, err
} else if !ValidateDataIntegrity(x, length) {
return nil, errors.New("crypto/rand failed to generate secure random data")
}
_, err = mrand.Read(y) // nolint: gosec
if err != nil {
return nil, err
} else if !ValidateDataIntegrity(y, length) {
return nil, errors.New("math/rand failed to generate secure random data")
}
for i := 0; i < length; i++ {
res[i] = x[i] ^ y[i]
}
if !ValidateDataIntegrity(res, length) {
return nil, errors.New("failed to generate secure random data")
}
return res, nil
}
// GenerateRandomID generates a random string, which is then returned to be used as a key id
func GenerateRandomID() (id string, err error) {
buf, err := GenerateSecureRandomData(KeyIDSize)

View File

@ -26,7 +26,6 @@ import (
"encoding/binary"
"errors"
"fmt"
mrand "math/rand"
"strconv"
"sync"
"time"
@ -262,37 +261,6 @@ func (msg *sentMessage) encryptSymmetric(key []byte) (err error) {
return nil
}
// GenerateSecureRandomData generates random data where extra security is required.
// The purpose of this function is to prevent some bugs in software or in hardware
// from delivering not-very-random data. This is especially useful for AES nonce,
// where true randomness does not really matter, but it is very important to have
// a unique nonce for every message.
func GenerateSecureRandomData(length int) ([]byte, error) {
x := make([]byte, length)
y := make([]byte, length)
res := make([]byte, length)
_, err := crand.Read(x)
if err != nil {
return nil, err
} else if !ValidateDataIntegrity(x, length) {
return nil, errors.New("crypto/rand failed to generate secure random data")
}
_, err = mrand.Read(y) // nolint: gosec
if err != nil {
return nil, err
} else if !ValidateDataIntegrity(y, length) {
return nil, errors.New("math/rand failed to generate secure random data")
}
for i := 0; i < length; i++ {
res[i] = x[i] ^ y[i]
}
if !ValidateDataIntegrity(res, length) {
return nil, errors.New("failed to generate secure random data")
}
return res, nil
}
// Wrap bundles the message into an Envelope to transmit over the network.
func (msg *sentMessage) Wrap(options *MessageParams, now time.Time) (envelope *Envelope, err error) {
if options.TTL == 0 {

View File

@ -84,7 +84,7 @@ type WakuHost interface {
OnNewEnvelopes([]*Envelope, Peer) ([]EnvelopeError, error)
// OnNewP2PEnvelopes handles envelopes received though the P2P
// protocol (i.e from a mailserver in most cases)
OnNewP2PEnvelopes([]*Envelope, Peer) error
OnNewP2PEnvelopes([]*Envelope) error
// OnMessagesResponse handles when the peer receive a message response
// from a mailserver
OnMessagesResponse(MessagesResponse, Peer) error

View File

@ -54,3 +54,22 @@ func (t TopicType) MarshalText() ([]byte, error) {
func (t *TopicType) UnmarshalText(input []byte) error {
return hexutil.UnmarshalFixedText("Topic", input, t[:])
}
// ToBloom converts the topic (4 bytes) to the bloom filter (64 bytes)
func (t TopicType) ToBloom() []byte {
b := make([]byte, BloomFilterSize)
var index [3]int
for j := 0; j < 3; j++ {
index[j] = int(t[j])
if (t[3] & (1 << uint(j))) != 0 {
index[j] += 256
}
}
for j := 0; j < 3; j++ {
byteIndex := index[j] / 8
bitIndex := index[j] % 8
b[byteIndex] = 1 << uint(bitIndex)
}
return b
}

View File

@ -100,7 +100,6 @@ var unexpectedMessage = []byte("per rectum ad astra")
var masterBloomFilter []byte
var masterPow = 0.00000001
var round = 1
var prevTime time.Time
func TestSimulationBloomFilter(t *testing.T) {
// create a chain of waku nodes,
@ -144,7 +143,7 @@ func resetParams() {
_ = nodes[0].waku.SetMinimumPoW(masterPow, true)
// change bloom for all nodes
masterBloomFilter = common.TopicToBloom(sharedTopic)
masterBloomFilter = sharedTopic.ToBloom()
for i := 0; i < NumNodes; i++ {
_ = nodes[i].waku.SetBloomFilter(masterBloomFilter)
}
@ -159,7 +158,7 @@ func initBloom(t *testing.T) {
t.Fatalf("rand failed: %s.", err)
}
msgBloom := common.TopicToBloom(sharedTopic)
msgBloom := sharedTopic.ToBloom()
masterBloomFilter = addBloom(masterBloomFilter, msgBloom)
for i := 0; i < 32; i++ {
masterBloomFilter[i] = 0xFF
@ -255,7 +254,6 @@ func checkPropagation(t *testing.T, includingNodeZero bool) {
return
}
prevTime = time.Now()
// (cycle * iterations) should not exceed 50 seconds, since TTL=50
const cycle = 200 // time in milliseconds
const iterations = 250

View File

@ -356,7 +356,7 @@ func (p *Peer) handleP2PMessageCode(packet p2p.Msg) error {
return fmt.Errorf("invalid direct message payload: %v", err)
}
return p.host.OnNewP2PEnvelopes(envelopes, p)
return p.host.OnNewP2PEnvelopes(envelopes)
}
func (p *Peer) handleP2PRequestCompleteCode(packet p2p.Msg) error {

View File

@ -17,7 +17,7 @@ func TestEncodeDecodeRLP(t *testing.T) {
opts := StatusOptions{
PoWRequirement: &pow,
BloomFilter: common.TopicToBloom(common.TopicType{0xaa, 0xbb, 0xcc, 0xdd}),
BloomFilter: common.TopicType{0xaa, 0xbb, 0xcc, 0xdd}.ToBloom(),
LightNodeEnabled: &lightNodeEnabled,
ConfirmationsEnabled: &confirmationsEnabled,
RateLimits: &common.RateLimits{

View File

@ -356,7 +356,7 @@ func (p *Peer) handleP2PMessageCode(packet p2p.Msg) error {
return fmt.Errorf("invalid direct message payload: %v", err)
}
return p.host.OnNewP2PEnvelopes(envelopes, p)
return p.host.OnNewP2PEnvelopes(envelopes)
}
func (p *Peer) handleP2PRequestCompleteCode(packet p2p.Msg) error {

View File

@ -17,7 +17,7 @@ func TestEncodeDecodeRLP(t *testing.T) {
opts := StatusOptions{
PoWRequirement: &pow,
BloomFilter: common.TopicToBloom(common.TopicType{0xaa, 0xbb, 0xcc, 0xdd}),
BloomFilter: common.TopicType{0xaa, 0xbb, 0xcc, 0xdd}.ToBloom(),
LightNodeEnabled: &lightNodeEnabled,
ConfirmationsEnabled: &confirmationsEnabled,
RateLimits: &common.RateLimits{

View File

@ -952,7 +952,7 @@ func (w *Waku) updateBloomFilter(f *common.Filter) error {
aggregate := make([]byte, common.BloomFilterSize)
for _, t := range f.Topics {
top := common.BytesToTopic(t)
b := common.TopicToBloom(top)
b := top.ToBloom()
aggregate = addBloom(aggregate, b)
}
@ -1087,12 +1087,13 @@ func (w *Waku) OnNewEnvelopes(envelopes []*common.Envelope, peer common.Peer) ([
return envelopeErrors, nil
}
func (w *Waku) OnNewP2PEnvelopes(envelopes []*common.Envelope, p common.Peer) error {
func (w *Waku) OnNewP2PEnvelopes(envelopes []*common.Envelope) error {
for _, envelope := range envelopes {
w.postP2P(envelope)
}
return nil
}
func (w *Waku) Mailserver() bool {
return w.mailServer != nil
}

View File

@ -459,21 +459,15 @@ func TestExpiry(t *testing.T) {
InitSingleTest()
w := New(nil, nil)
err := w.SetMinimumPoW(0.0000001, false)
if err != nil {
if err := w.SetMinimumPoW(0.0000001, false); err != nil {
t.Fatal("failed to set min pow")
}
defer func() {
handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false))
}()
err = w.Start(nil)
if err != nil {
defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }()
if err := w.Start(nil); err != nil {
t.Fatal("failed to start waku")
}
defer func() {
handleError(t, w.Stop())
}()
defer func() { handleError(t, w.Stop()) }()
params, err := generateMessageParams()
if err != nil {
@ -534,18 +528,12 @@ func TestCustomization(t *testing.T) {
InitSingleTest()
w := New(nil, nil)
defer func() {
handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false))
}()
defer func() {
handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize))
}()
defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }()
defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }()
if err := w.Start(nil); err != nil {
t.Fatal("failed to start node")
}
defer func() {
handleError(t, w.Stop())
}()
defer func() { handleError(t, w.Stop()) }()
const smallPoW = 0.00001
@ -633,19 +621,12 @@ func TestSymmetricSendCycle(t *testing.T) {
InitSingleTest()
w := New(nil, nil)
defer func() {
handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false))
}()
defer func() {
handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize))
}()
err := w.Start(nil)
if err != nil {
defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }()
defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }()
if err := w.Start(nil); err != nil {
t.Fatal("failed to start node")
}
defer func() {
handleError(t, w.Stop())
}()
defer func() { handleError(t, w.Stop()) }()
filter1, err := generateFilter(t, true)
if err != nil {
@ -731,18 +712,12 @@ func TestSymmetricSendCycleWithTopicInterest(t *testing.T) {
InitSingleTest()
w := New(nil, nil)
defer func() {
handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false))
}()
defer func() {
handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize))
}()
defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }()
defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }()
if err := w.Start(nil); err != nil {
t.Fatal("could not start node")
}
defer func() {
handleError(t, w.Stop())
}()
defer func() { handleError(t, w.Stop()) }()
filter1, err := generateFilter(t, true)
if err != nil {
@ -832,15 +807,9 @@ func TestSymmetricSendWithoutAKey(t *testing.T) {
t.Errorf("failed to start waku: '%s'", err)
}
defer func() {
handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false))
}()
defer func() {
handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize))
}()
defer func() {
handleError(t, w.Stop())
}()
defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }()
defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }()
defer func() { handleError(t, w.Stop()) }()
filter, err := generateFilter(t, true)
if err != nil {
@ -908,15 +877,9 @@ func TestSymmetricSendKeyMismatch(t *testing.T) {
if err := w.Start(nil); err != nil {
t.Errorf("failed to start waku: '%s'", err)
}
defer func() {
handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false))
}()
defer func() {
handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize))
}()
defer func() {
handleError(t, w.Stop())
}()
defer func() { handleError(t, w.SetMinimumPoW(common.DefaultMinimumPoW, false)) }()
defer func() { handleError(t, w.SetMaxMessageSize(common.DefaultMaxMessageSize)) }()
defer func() { handleError(t, w.Stop()) }()
filter, err := generateFilter(t, true)
if err != nil {
@ -977,7 +940,7 @@ func TestSymmetricSendKeyMismatch(t *testing.T) {
func TestBloom(t *testing.T) {
topic := common.TopicType{0, 0, 255, 6}
b := common.TopicToBloom(topic)
b := topic.ToBloom()
x := make([]byte, common.BloomFilterSize)
x[0] = byte(1)
x[32] = byte(1)

View File

@ -69,16 +69,12 @@ func (s *WakuTestSuite) TestHandleP2PMessageCode() {
s.Require().NoError(w1.SetMinimumPoW(0.0000001, false))
s.Require().NoError(w1.Start(nil))
go func() {
handleError(s.T(), w1.Stop())
}()
go func() { handleError(s.T(), w1.Stop()) }()
w2 := New(nil, nil)
s.Require().NoError(w2.SetMinimumPoW(0.0000001, false))
s.Require().NoError(w2.Start(nil))
go func() {
handleError(s.T(), w2.Stop())
}()
go func() { handleError(s.T(), w2.Stop()) }()
envelopeEvents := make(chan common.EnvelopeEvent, 10)
sub := w1.SubscribeEnvelopeEvents(envelopeEvents)
@ -187,10 +183,7 @@ func (s *WakuTestSuite) TestMessagesResponseWithError() {
p2 := s.newPeer(w2, p2p.NewPeer(enode.ID{2}, "2", []p2p.Cap{{"waku", 0}}), rw1, nil)
errorc := make(chan error, 1)
go func() {
err := w1.HandlePeer(p1, rw2)
errorc <- err
}()
go func() { errorc <- w1.HandlePeer(p1, rw2) }()
s.Require().NoError(p2.Start())
failed := common.Envelope{
@ -253,10 +246,7 @@ func (s *WakuTestSuite) testConfirmationEvents(envelope common.Envelope, envelop
p2 := s.newPeer(w2, p2p.NewPeer(enode.ID{2}, "2", []p2p.Cap{{"waku", 0}}), rw1, nil)
errorc := make(chan error, 1)
go func() {
err := w1.HandlePeer(p1, rw2)
errorc <- err
}()
go func() { errorc <- w1.HandlePeer(p1, rw2) }()
timer := time.AfterFunc(5*time.Second, func() {
if err := rw1.Close(); err != nil {
@ -273,10 +263,7 @@ func (s *WakuTestSuite) testConfirmationEvents(envelope common.Envelope, envelop
s.Require().NoError(err)
// And run mainloop
go func() {
err := p2.Run()
errorc <- err
}()
go func() { errorc <- p2.Run() }()
w1.addEnvelope(&envelope)
@ -355,9 +342,7 @@ func (s *WakuTestSuite) TestEventsWithoutConfirmation() {
rw1, rw2 := p2p.MsgPipe()
p1 := s.newPeer(w1, p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{"waku", 0}}), rw2, nil)
go func() {
handleError(s.T(), w1.HandlePeer(p1, rw2))
}()
go func() { handleError(s.T(), w1.HandlePeer(p1, rw2)) }()
timer := time.AfterFunc(5*time.Second, func() {
handleError(s.T(), rw1.Close())
@ -365,9 +350,7 @@ func (s *WakuTestSuite) TestEventsWithoutConfirmation() {
peer2 := s.newPeer(w2, p2p.NewPeer(enode.ID{1}, "1", nil), rw1, nil)
s.Require().NoError(peer2.Start())
go func() {
handleError(s.T(), peer2.Run())
}()
go func() { handleError(s.T(), peer2.Run()) }()
e := common.Envelope{
Expiry: uint32(time.Now().Add(10 * time.Second).Unix()),
@ -423,12 +406,8 @@ func (s *WakuTestSuite) TestWakuTimeDesyncEnvelopeIgnored() {
p2 := s.newPeer(w1, p2p.NewPeer(enode.ID{2}, "2", []p2p.Cap{{"waku", 1}}), rw2, nil)
errc := make(chan error)
go func() {
errc <- w1.HandlePeer(p2, rw2)
}()
go func() {
errc <- w2.HandlePeer(p1, rw1)
}()
go func() { errc <- w1.HandlePeer(p2, rw2) }()
go func() { errc <- w2.HandlePeer(p1, rw1) }()
w1.SetTimeSource(func() time.Time {
return time.Now().Add(time.Hour)
})
@ -457,9 +436,7 @@ func (s *WakuTestSuite) TestRequestSentEventWithExpiry() {
w := New(nil, nil)
p := p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{"waku", 1}})
rw := discardPipe()
defer func() {
handleError(s.T(), rw.Close())
}()
defer func() { handleError(s.T(), rw.Close()) }()
w.peers[s.newPeer(w, p, rw, nil)] = struct{}{}
events := make(chan common.EnvelopeEvent, 1)
sub := w.SubscribeEnvelopeEvents(events)
@ -510,8 +487,8 @@ func (s *WakuTestSuite) TestSendMessagesRequest() {
// Read out so that it's consumed
_, err := rw2.ReadMsg()
s.Require().NoError(err)
rw2.Close()
rw1.Close()
s.Require().NoError(rw1.Close())
s.Require().NoError(rw2.Close())
}()
err := w.SendMessagesRequest(p.ID().Bytes(), validMessagesRequest)
@ -537,10 +514,7 @@ func (s *WakuTestSuite) TestRateLimiterIntegration() {
}()
p := s.newPeer(w, p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{"waku", 0}}), rw2, nil)
errorc := make(chan error, 1)
go func() {
err := w.HandlePeer(p, rw2)
errorc <- err
}()
go func() { errorc <- w.HandlePeer(p, rw2) }()
_, err := rw1.ReadMsg()
s.Require().NoError(err)
@ -555,9 +529,7 @@ func (s *WakuTestSuite) TestRateLimiterIntegration() {
func (s *WakuTestSuite) TestMailserverCompletionEvent() {
w1 := New(nil, nil)
s.Require().NoError(w1.Start(nil))
defer func() {
handleError(s.T(), w1.Stop())
}()
defer func() { handleError(s.T(), w1.Stop()) }()
rw1, rw2 := p2p.MsgPipe()
errorc := make(chan error, 1)
@ -568,9 +540,7 @@ func (s *WakuTestSuite) TestMailserverCompletionEvent() {
w2 := New(nil, nil)
s.Require().NoError(w2.Start(nil))
defer func() {
handleError(s.T(), w2.Stop())
}()
defer func() { handleError(s.T(), w2.Stop()) }()
peer2 := s.newPeer(w2, p2p.NewPeer(enode.ID{1}, "1", nil), rw2, nil)
peer2.SetPeerTrusted(true)
@ -586,7 +556,7 @@ func (s *WakuTestSuite) TestMailserverCompletionEvent() {
s.Require().NoError(peer2.SendP2PMessages(envelopes))
s.Require().NoError(peer2.SendHistoricMessageResponse(make([]byte, 100)))
rw2.Close()
s.Require().NoError(rw2.Close())
// Wait for all messages to be read
err := <-errorc
@ -614,15 +584,11 @@ func (s *WakuTestSuite) TestMailserverCompletionEvent() {
//two generic waku node handshake
func (s *WakuTestSuite) TestPeerHandshakeWithTwoFullNode() {
rw1, rw2 := p2p.MsgPipe()
defer func() {
handleError(s.T(), rw1.Close())
}()
defer func() {
handleError(s.T(), rw2.Close())
}()
defer func() { handleError(s.T(), rw1.Close()) }()
defer func() { handleError(s.T(), rw2.Close()) }()
w1 := New(nil, nil)
var pow float64 = 0.1
var pow = 0.1
err := w1.SetMinimumPoW(pow, true)
s.Require().NoError(err)
@ -642,12 +608,8 @@ func (s *WakuTestSuite) TestPeerHandshakeWithTwoFullNode() {
//two generic waku node handshake. one don't send light flag
func (s *WakuTestSuite) TestHandshakeWithOldVersionWithoutLightModeFlag() {
rw1, rw2 := p2p.MsgPipe()
defer func() {
handleError(s.T(), rw1.Close())
}()
defer func() {
handleError(s.T(), rw2.Close())
}()
defer func() { handleError(s.T(), rw1.Close()) }()
defer func() { handleError(s.T(), rw2.Close()) }()
w1 := New(nil, nil)
w1.SetLightClientMode(true)
@ -666,12 +628,8 @@ func (s *WakuTestSuite) TestHandshakeWithOldVersionWithoutLightModeFlag() {
//two light nodes handshake. restriction enable
func (s *WakuTestSuite) TestTwoLightPeerHandshakeRestrictionOff() {
rw1, rw2 := p2p.MsgPipe()
defer func() {
handleError(s.T(), rw1.Close())
}()
defer func() {
handleError(s.T(), rw2.Close())
}()
defer func() { handleError(s.T(), rw1.Close()) }()
defer func() { handleError(s.T(), rw2.Close()) }()
w1 := New(nil, nil)
w1.SetLightClientMode(true)
@ -692,12 +650,8 @@ func (s *WakuTestSuite) TestTwoLightPeerHandshakeRestrictionOff() {
//two light nodes handshake. restriction enabled
func (s *WakuTestSuite) TestTwoLightPeerHandshakeError() {
rw1, rw2 := p2p.MsgPipe()
defer func() {
handleError(s.T(), rw1.Close())
}()
defer func() {
handleError(s.T(), rw2.Close())
}()
defer func() { handleError(s.T(), rw1.Close()) }()
defer func() { handleError(s.T(), rw2.Close()) }()
w1 := New(nil, nil)
w1.SetLightClientMode(true)