github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/session/pingpong/hermes_promise_settler_test.go (about)

     1  /*
     2   * Copyright (C) 2019 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  package pingpong
    18  
    19  import (
    20  	"encoding/hex"
    21  	"errors"
    22  	"fmt"
    23  	"math/big"
    24  	"strings"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/mysteriumnetwork/node/identity"
    31  	"github.com/mysteriumnetwork/node/identity/registry"
    32  	"github.com/mysteriumnetwork/node/session/pingpong/event"
    33  	"github.com/mysteriumnetwork/payments/bindings"
    34  	"github.com/mysteriumnetwork/payments/client"
    35  	"github.com/mysteriumnetwork/payments/crypto"
    36  	"github.com/mysteriumnetwork/payments/units"
    37  	"github.com/stretchr/testify/assert"
    38  )
    39  
    40  func TestPromiseSettler_loadInitialState(t *testing.T) {
    41  	mrsp := &mockRegistrationStatusProvider{
    42  		identities: map[string]mockRegistrationStatus{
    43  			mockChainIdentity: {
    44  				status: registry.Registered,
    45  			},
    46  		},
    47  	}
    48  	ks := identity.NewMockKeystore()
    49  	lbs := newMockAddressStorage()
    50  
    51  	fac := &mockHermesCallerFactory{}
    52  
    53  	settler := NewHermesPromiseSettler(
    54  		&mockTransactor{},
    55  		&mockHermesPromiseStorage{},
    56  		&mockPayAndSettler{},
    57  		&mockAddressProvider{},
    58  		fac.Get,
    59  		&mockHermesURLGetter{},
    60  		&mockHermesChannelProvider{},
    61  		&mockProviderChannelStatusProvider{},
    62  		mrsp,
    63  		ks,
    64  		&settlementHistoryStorageMock{},
    65  		&mockPublisher{},
    66  		&mockObserver{},
    67  		lbs,
    68  		cfg)
    69  
    70  	settler.currentState[mockID] = settlementState{}
    71  
    72  	// check if existing gets skipped
    73  	err := settler.loadInitialState(0, mockID)
    74  	assert.NoError(t, err)
    75  
    76  	v := settler.currentState[mockID]
    77  	assert.EqualValues(t, settlementState{}, v)
    78  
    79  	// check if unregistered gets skipped
    80  	delete(settler.currentState, mockID)
    81  
    82  	mrsp.identities[mockChainIdentity] = mockRegistrationStatus{
    83  		status: registry.Registered,
    84  	}
    85  
    86  	err = settler.loadInitialState(0, mockID)
    87  	assert.NoError(t, err)
    88  
    89  	v = settler.currentState[mockID]
    90  	assert.EqualValues(t, settlementState{
    91  		registered:       true,
    92  		settleInProgress: map[common.Address]struct{}{},
    93  	}, v)
    94  
    95  	// check if will resync
    96  	delete(settler.currentState, mockID)
    97  
    98  	mrsp.identities[mockChainIdentity] = mockRegistrationStatus{
    99  		status: registry.Registered,
   100  	}
   101  
   102  	err = settler.loadInitialState(0, mockID)
   103  	assert.NoError(t, err)
   104  
   105  	v = settler.currentState[mockID]
   106  	assert.True(t, v.registered)
   107  
   108  	// check if will bubble registration status errors
   109  	delete(settler.currentState, mockID)
   110  
   111  	mrsp.identities[mockChainIdentity] = mockRegistrationStatus{
   112  		status: registry.Registered,
   113  		err:    errMock,
   114  	}
   115  
   116  	err = settler.loadInitialState(0, mockID)
   117  	assert.Equal(t, fmt.Sprintf("could not check registration status for %v: %v", mockID, errMock.Error()), err.Error())
   118  }
   119  
   120  func TestPromiseSettler_handleRegistrationEvent(t *testing.T) {
   121  	mrsp := &mockRegistrationStatusProvider{
   122  		identities: map[string]mockRegistrationStatus{
   123  			mockChainIdentity: {
   124  				status: registry.Registered,
   125  			},
   126  		},
   127  	}
   128  	ks := identity.NewMockKeystore()
   129  	fac := &mockHermesCallerFactory{}
   130  	lbs := newMockAddressStorage()
   131  
   132  	settler := NewHermesPromiseSettler(
   133  		&mockTransactor{},
   134  		&mockHermesPromiseStorage{},
   135  		&mockPayAndSettler{},
   136  		&mockAddressProvider{},
   137  		fac.Get,
   138  		&mockHermesURLGetter{},
   139  		&mockHermesChannelProvider{},
   140  		&mockProviderChannelStatusProvider{},
   141  		mrsp,
   142  		ks,
   143  		&settlementHistoryStorageMock{},
   144  		&mockPublisher{},
   145  		&mockObserver{},
   146  		lbs,
   147  		cfg)
   148  
   149  	statusesWithNoChangeExpected := []registry.RegistrationStatus{registry.Unregistered, registry.InProgress, registry.RegistrationError}
   150  	for _, v := range statusesWithNoChangeExpected {
   151  		settler.handleRegistrationEvent(registry.AppEventIdentityRegistration{
   152  			ID:     mockID,
   153  			Status: v,
   154  		})
   155  
   156  		_, ok := settler.currentState[mockID]
   157  
   158  		assert.False(t, ok)
   159  	}
   160  
   161  	settler.handleRegistrationEvent(registry.AppEventIdentityRegistration{
   162  		ID:     mockID,
   163  		Status: registry.Registered,
   164  	})
   165  
   166  	v, ok := settler.currentState[mockID]
   167  	assert.True(t, ok)
   168  	assert.True(t, v.registered)
   169  }
   170  
   171  func TestPromiseSettler_handleHermesPromiseReceived(t *testing.T) {
   172  	channelProvider := &mockHermesChannelProvider{}
   173  	channelStatusProvider := &mockProviderChannelStatusProvider{}
   174  	mrsp := &mockRegistrationStatusProvider{
   175  		identities: map[string]mockRegistrationStatus{
   176  			mockChainIdentity: {
   177  				status: registry.Registered,
   178  			},
   179  		},
   180  	}
   181  	ks := identity.NewMockKeystore()
   182  	fac := &mockHermesCallerFactory{}
   183  	tm := &mockTransactor{
   184  		feesToReturn: registry.FeesResponse{
   185  			Fee:        units.FloatEthToBigIntWei(0.05),
   186  			ValidUntil: time.Now().Add(30 * time.Minute),
   187  		},
   188  	}
   189  	lbs := newMockAddressStorage()
   190  
   191  	settler := NewHermesPromiseSettler(tm, &mockHermesPromiseStorage{}, &mockPayAndSettler{}, &mockAddressProvider{}, fac.Get, &mockHermesURLGetter{}, channelProvider, channelStatusProvider, mrsp, ks, &settlementHistoryStorageMock{}, &mockPublisher{}, &mockObserver{}, lbs, cfg)
   192  
   193  	// no receive on unknown provider
   194  	channelProvider.channelToReturn = NewHermesChannel("1", mockID, hermesID, mockProviderChannel, HermesPromise{}, beneficiaryID)
   195  	settler.handleHermesPromiseReceived(event.AppEventHermesPromise{
   196  		HermesID:   hermesID,
   197  		ProviderID: mockID,
   198  	})
   199  	assertNoReceive(t, settler.settleQueue)
   200  
   201  	// no receive should be gotten on a non registered provider
   202  	settler.currentState[mockID] = settlementState{
   203  		registered:       false,
   204  		settleInProgress: map[common.Address]struct{}{},
   205  	}
   206  	channelProvider.channelToReturn = NewHermesChannel("1", mockID, hermesID, mockProviderChannel, HermesPromise{}, beneficiaryID)
   207  	settler.handleHermesPromiseReceived(event.AppEventHermesPromise{
   208  		HermesID:   hermesID,
   209  		ProviderID: mockID,
   210  	})
   211  	assertNoReceive(t, settler.settleQueue)
   212  
   213  	// should receive on registered provider. Should also expect a recalculated balance to be added to the settlementState
   214  	expectedChannel := client.ProviderChannel{Stake: big.NewInt(1000)}
   215  	expectedPromise := crypto.Promise{Amount: units.FloatEthToBigIntWei(6)}
   216  	settler.currentState[mockID] = settlementState{
   217  		registered:       true,
   218  		settleInProgress: map[common.Address]struct{}{},
   219  	}
   220  	channelProvider.channelToReturn = NewHermesChannel("1", mockID, hermesID, expectedChannel, HermesPromise{Promise: expectedPromise}, beneficiaryID)
   221  	settler.handleHermesPromiseReceived(event.AppEventHermesPromise{
   222  		HermesID:   hermesID,
   223  		ProviderID: mockID,
   224  		Promise:    expectedPromise,
   225  	})
   226  
   227  	p := <-settler.settleQueue
   228  	assert.Equal(t, mockID, p.provider)
   229  
   230  	// should not receive here due to balance being large and stake being small
   231  	expectedChannel = client.ProviderChannel{
   232  		Stake:   big.NewInt(0),
   233  		Settled: units.FloatEthToBigIntWei(6),
   234  	}
   235  	expectedPromise = crypto.Promise{Amount: units.FloatEthToBigIntWei(8)}
   236  	settler.currentState[mockID] = settlementState{
   237  		registered:       true,
   238  		settleInProgress: map[common.Address]struct{}{},
   239  	}
   240  	channelProvider.channelToReturn = NewHermesChannel("1", mockID, hermesID, expectedChannel, HermesPromise{Promise: expectedPromise}, beneficiaryID)
   241  	settler.handleHermesPromiseReceived(event.AppEventHermesPromise{
   242  		HermesID:   hermesID,
   243  		ProviderID: mockID,
   244  		Promise:    expectedPromise,
   245  	})
   246  	assertNoReceive(t, settler.settleQueue)
   247  }
   248  
   249  func TestPromiseSettler_handleHermesPromiseReceivedWithLocalBeneficiary(t *testing.T) {
   250  	channelProvider := &mockHermesChannelProvider{}
   251  	channelStatusProvider := &mockProviderChannelStatusProvider{}
   252  	mrsp := &mockRegistrationStatusProvider{
   253  		identities: map[string]mockRegistrationStatus{
   254  			mockChainIdentity: {
   255  				status: registry.Registered,
   256  			},
   257  		},
   258  	}
   259  	ks := identity.NewMockKeystore()
   260  	fac := &mockHermesCallerFactory{}
   261  	tm := &mockTransactor{
   262  		feesToReturn: registry.FeesResponse{
   263  			Fee:        units.FloatEthToBigIntWei(0.05),
   264  			ValidUntil: time.Now().Add(30 * time.Minute),
   265  		},
   266  	}
   267  	lbs := newMockAddressStorage()
   268  
   269  	settler := NewHermesPromiseSettler(tm, &mockHermesPromiseStorage{}, &mockPayAndSettler{}, &mockAddressProvider{}, fac.Get, &mockHermesURLGetter{}, channelProvider, channelStatusProvider, mrsp, ks, &settlementHistoryStorageMock{}, &mockPublisher{}, &mockObserver{}, lbs, cfg)
   270  
   271  	expectedChannel := client.ProviderChannel{Stake: big.NewInt(1000)}
   272  	expectedPromise := crypto.Promise{Amount: units.FloatEthToBigIntWei(6)}
   273  	settler.currentState[mockID] = settlementState{
   274  		registered:       true,
   275  		settleInProgress: map[common.Address]struct{}{},
   276  	}
   277  	channelProvider.channelToReturn = NewHermesChannel("1", mockID, hermesID, expectedChannel, HermesPromise{Promise: expectedPromise}, beneficiaryID)
   278  	settler.handleHermesPromiseReceived(event.AppEventHermesPromise{
   279  		HermesID:   hermesID,
   280  		ProviderID: mockID,
   281  		Promise:    expectedPromise,
   282  	})
   283  
   284  	p := <-settler.settleQueue
   285  	assert.Equal(t, mockID, p.provider)
   286  	assert.Equal(t, beneficiaryID, p.beneficiary)
   287  
   288  	localBeneficiary := common.HexToAddress("0x00000000000000000000000000000000000000133")
   289  	err := lbs.Save(mockID.Address, localBeneficiary.Hex())
   290  	assert.NoError(t, err)
   291  
   292  	settler.handleHermesPromiseReceived(event.AppEventHermesPromise{
   293  		HermesID:   hermesID,
   294  		ProviderID: mockID,
   295  		Promise:    expectedPromise,
   296  	})
   297  	p = <-settler.settleQueue
   298  	assert.Equal(t, mockID, p.provider)
   299  }
   300  
   301  func TestPromiseSettler_doNotSettleIfBeneficiaryIsAChannel(t *testing.T) {
   302  	channelProvider := &mockHermesChannelProvider{}
   303  	channelStatusProvider := &mockProviderChannelStatusProvider{}
   304  	mrsp := &mockRegistrationStatusProvider{
   305  		identities: map[string]mockRegistrationStatus{
   306  			mockChainIdentity: {
   307  				status: registry.Registered,
   308  			},
   309  		},
   310  	}
   311  	ks := identity.NewMockKeystore()
   312  	fac := &mockHermesCallerFactory{}
   313  	tm := &mockTransactor{
   314  		feesToReturn: registry.FeesResponse{
   315  			Fee:        units.FloatEthToBigIntWei(0.05),
   316  			ValidUntil: time.Now().Add(30 * time.Minute),
   317  		},
   318  	}
   319  	lbs := newMockAddressStorage()
   320  
   321  	mockAddressProvider := newMockAddressProvider()
   322  	settler := NewHermesPromiseSettler(tm, &mockHermesPromiseStorage{}, &mockPayAndSettler{}, mockAddressProvider, fac.Get, &mockHermesURLGetter{}, channelProvider, channelStatusProvider, mrsp, ks, &settlementHistoryStorageMock{}, &mockPublisher{}, &mockObserver{}, lbs, cfg)
   323  
   324  	expectedChannel := client.ProviderChannel{Stake: big.NewInt(1000)}
   325  	expectedPromise := crypto.Promise{Amount: units.FloatEthToBigIntWei(6)}
   326  	settler.currentState[mockID] = settlementState{
   327  		registered:       true,
   328  		settleInProgress: map[common.Address]struct{}{},
   329  	}
   330  	channelProvider.channelToReturn = NewHermesChannel("1", mockID, hermesID, expectedChannel, HermesPromise{Promise: expectedPromise}, beneficiaryID)
   331  	settler.handleHermesPromiseReceived(event.AppEventHermesPromise{
   332  		HermesID:   hermesID,
   333  		ProviderID: mockID,
   334  		Promise:    expectedPromise,
   335  	})
   336  
   337  	p := <-settler.settleQueue
   338  	assert.Equal(t, mockID, p.provider)
   339  	assert.Equal(t, beneficiaryID, p.beneficiary)
   340  
   341  	mockAddressProvider.setChannelAddress(0, mockID.ToCommonAddress(), beneficiaryID)
   342  	channelProvider.channelToReturn = NewHermesChannel("1", mockID, hermesID, expectedChannel, HermesPromise{Promise: expectedPromise}, beneficiaryID)
   343  	settler.handleHermesPromiseReceived(event.AppEventHermesPromise{
   344  		HermesID:   hermesID,
   345  		ProviderID: mockID,
   346  		Promise:    expectedPromise,
   347  	})
   348  
   349  	p = <-settler.settleQueue
   350  	assert.Equal(t, mockID, p.provider)
   351  	assert.Equal(t, beneficiaryID, p.beneficiary)
   352  }
   353  
   354  func assertNoReceive(t *testing.T, ch chan receivedPromise) {
   355  	// at this point, we should not receive an event on settled queue as we have no info on provider, let's check for that
   356  	select {
   357  	case <-ch:
   358  		assert.Fail(t, "did not expect to receive from settled queue")
   359  	case <-time.After(time.Millisecond * 2):
   360  		// we've not received on the channel, continue
   361  	}
   362  }
   363  
   364  func TestPromiseSettler_handleNodeStart(t *testing.T) {
   365  	ks := identity.NewMockKeystore()
   366  
   367  	acc1, err := ks.NewAccount("")
   368  	assert.NoError(t, err)
   369  	acc2, err := ks.NewAccount("")
   370  	assert.NoError(t, err)
   371  
   372  	lbs := newMockAddressStorage()
   373  
   374  	mrsp := &mockRegistrationStatusProvider{
   375  		identities: map[string]mockRegistrationStatus{
   376  			"0" + strings.ToLower(acc2.Address.Hex()): {
   377  				status: registry.Registered,
   378  			},
   379  			"0" + strings.ToLower(acc1.Address.Hex()): {
   380  				status: registry.Unregistered,
   381  			},
   382  		},
   383  	}
   384  
   385  	fac := &mockHermesCallerFactory{}
   386  	settler := NewHermesPromiseSettler(
   387  		&mockTransactor{},
   388  		&mockHermesPromiseStorage{},
   389  		&mockPayAndSettler{},
   390  		&mockAddressProvider{},
   391  		fac.Get,
   392  		&mockHermesURLGetter{},
   393  		&mockHermesChannelProvider{},
   394  		&mockProviderChannelStatusProvider{},
   395  		mrsp,
   396  		ks,
   397  		&settlementHistoryStorageMock{},
   398  		&mockPublisher{},
   399  		&mockObserver{},
   400  		lbs,
   401  		cfg)
   402  
   403  	settler.handleNodeStart()
   404  
   405  	// since each address is checked on BC in background, we'll need to wait here until that is complete
   406  	time.Sleep(time.Millisecond * 10)
   407  
   408  	// since we're accessing the current state from outside the setller, lock the settler to prevent race conditions
   409  	settler.lock.Lock()
   410  	defer settler.lock.Unlock()
   411  
   412  	assert.True(t, settler.currentState[identity.FromAddress(acc2.Address.Hex())].registered)
   413  	assert.False(t, settler.currentState[identity.FromAddress(acc1.Address.Hex())].registered)
   414  }
   415  
   416  func TestPromiseSettler_RejectsIfFeesExceedSettlementAmount(t *testing.T) {
   417  	fac := &mockHermesCallerFactory{}
   418  	transactorFee := big.NewInt(5000)
   419  	hermesFee := big.NewInt(25000)
   420  
   421  	promiseSettler := hermesPromiseSettler{
   422  		currentState: map[identity.Identity]settlementState{},
   423  		transactor: &mockTransactor{
   424  			feesToReturn: registry.FeesResponse{
   425  				Fee: transactorFee,
   426  			},
   427  		},
   428  		hermesCallerFactory: fac.Get,
   429  		hermesURLGetter:     &mockHermesURLGetter{},
   430  		bc: &mockProviderChannelStatusProvider{
   431  			calculatedFees: hermesFee,
   432  		},
   433  	}
   434  
   435  	mockPromise := crypto.Promise{
   436  		Fee:    transactorFee,
   437  		Amount: big.NewInt(35000),
   438  	}
   439  
   440  	settled := big.NewInt(6000)
   441  
   442  	mockSettler := func(crypto.Promise) (string, error) { return "", nil }
   443  	err := promiseSettler.settle(mockSettler, identity.Identity{}, common.Address{}, mockPromise, common.Address{}, settled, nil)
   444  	assert.Equal(t, "settlement fees exceed earning amount. Please provide more service and try again. Current earnings: 29000, current fees: 30000: fee not covered, cannot continue", err.Error())
   445  }
   446  
   447  func TestPromiseSettler_RejectsIfFeesExceedMaxFee(t *testing.T) {
   448  	fac := &mockHermesCallerFactory{}
   449  	transactorFee := units.FloatEthToBigIntWei(0.8)
   450  	hermesFee := big.NewInt(25000)
   451  
   452  	promiseSettler := hermesPromiseSettler{
   453  		currentState: map[identity.Identity]settlementState{},
   454  		transactor: &mockTransactor{
   455  			feesToReturn: registry.FeesResponse{
   456  				Fee: transactorFee,
   457  			},
   458  		},
   459  		hermesCallerFactory: fac.Get,
   460  		hermesURLGetter:     &mockHermesURLGetter{},
   461  		bc: &mockProviderChannelStatusProvider{
   462  			calculatedFees: hermesFee,
   463  		},
   464  	}
   465  
   466  	mockPromise := crypto.Promise{
   467  		Fee:    transactorFee,
   468  		Amount: big.NewInt(35000),
   469  	}
   470  
   471  	settled := big.NewInt(6000)
   472  
   473  	mockSettler := func(crypto.Promise) (string, error) { return "", nil }
   474  	err := promiseSettler.settle(mockSettler, identity.Identity{}, common.Address{}, mockPromise, common.Address{}, settled, units.FloatEthToBigIntWei(0.6))
   475  	assert.Equal(t, "current fee is more than the max", err.Error())
   476  }
   477  
   478  func TestPromiseSettler_AcceptsIfFeesDoNotExceedSettlementAmount(t *testing.T) {
   479  	fac := &mockHermesCallerFactory{}
   480  	transactorFee := big.NewInt(5000)
   481  	hermesFee := big.NewInt(20000)
   482  	expectedChannel, err := hex.DecodeString("d0bb35eb0e4a0c972f2c154f91cf676b804762bef69c7fe4cef38642c3ac7ffc")
   483  	assert.NoError(t, err)
   484  
   485  	expectedR, err := hex.DecodeString("d56e23228dc2c7d2cc2e0ee08d7d6e5be6aa196c9f95046d83fab06913d2a9c2")
   486  	assert.NoError(t, err)
   487  
   488  	var arr [32]byte
   489  	copy(arr[:], expectedChannel)
   490  
   491  	var r [32]byte
   492  	copy(r[:], expectedR)
   493  	bc := &mockProviderChannelStatusProvider{
   494  		calculatedFees: hermesFee,
   495  		subCancel:      func() {},
   496  		promiseEventsToReturn: []bindings.HermesImplementationPromiseSettled{
   497  			{
   498  				ChannelId: arr,
   499  				Lock:      r,
   500  			},
   501  		},
   502  		headerToReturn: &types.Header{
   503  			Number: big.NewInt(0),
   504  		},
   505  	}
   506  
   507  	publisher := &mockPublisher{
   508  		publicationChan: make(chan testEvent, 10),
   509  	}
   510  	promiseSettler := hermesPromiseSettler{
   511  		currentState: make(map[identity.Identity]settlementState),
   512  		transactor: &mockTransactor{
   513  			idToReturn: "123",
   514  			queueToReturn: registry.QueueResponse{
   515  				State: "done",
   516  			},
   517  			feesToReturn: registry.FeesResponse{
   518  				Fee: transactorFee,
   519  			},
   520  		},
   521  		hermesCallerFactory: fac.Get,
   522  		hermesURLGetter:     &mockHermesURLGetter{},
   523  		bc:                  bc,
   524  		channelProvider:     &mockHermesChannelProvider{},
   525  		config: HermesPromiseSettlerConfig{
   526  			SettlementCheckTimeout: time.Millisecond * 50,
   527  		},
   528  		settlementHistoryStorage: &settlementHistoryStorageMock{},
   529  		publisher:                publisher,
   530  	}
   531  
   532  	mockPromise := crypto.Promise{
   533  		Fee:    transactorFee,
   534  		Amount: big.NewInt(35000),
   535  		R:      r[:],
   536  	}
   537  
   538  	settled := big.NewInt(6000)
   539  
   540  	mockSettler := func(crypto.Promise) (string, error) { return "", nil }
   541  
   542  	err = promiseSettler.settle(mockSettler, identity.Identity{Address: "0x92fE1c838b08dB4c072DDa805FB4292d9b76B5E7"}, common.HexToAddress("0x07b5fD382b5e375F202184052BeF2C50b3B1404F"), mockPromise, common.Address{}, settled, nil)
   543  	assert.NoError(t, err)
   544  	ev := <-publisher.publicationChan
   545  	assert.Equal(t, event.AppTopicSettlementComplete, ev.name)
   546  	_, ok := ev.value.(event.AppEventSettlementComplete)
   547  	assert.True(t, ok)
   548  }
   549  
   550  func TestPromiseSettlerState_needsSettling(t *testing.T) {
   551  	hps := &hermesPromiseSettler{
   552  		transactor: &mockTransactor{
   553  			feesToReturn: registry.FeesResponse{
   554  				Fee:        units.FloatEthToBigIntWei(2.0),
   555  				ValidUntil: time.Now().Add(30 * time.Minute),
   556  			},
   557  		},
   558  	}
   559  	s := settlementState{
   560  		registered:       true,
   561  		settleInProgress: map[common.Address]struct{}{},
   562  	}
   563  	channel := NewHermesChannel(
   564  		"1",
   565  		mockID,
   566  		hermesID,
   567  		client.ProviderChannel{Stake: big.NewInt(0)},
   568  		HermesPromise{Promise: crypto.Promise{Amount: units.FloatEthToBigIntWei(10.1)}},
   569  		beneficiaryID,
   570  	)
   571  	needs, maxFee := hps.needsSettling(s, 0, 0.1, 5, 10, channel, 1)
   572  	assert.True(t, needs, "should be true with balance more than max regardless of fees")
   573  	assert.Nil(t, maxFee, "should be nil")
   574  
   575  	hps = &hermesPromiseSettler{
   576  		transactor: &mockTransactor{
   577  			feesToReturn: registry.FeesResponse{
   578  				Fee:        units.FloatEthToBigIntWei(0.045),
   579  				ValidUntil: time.Now().Add(30 * time.Minute),
   580  			},
   581  		},
   582  	}
   583  	s = settlementState{
   584  		registered:       true,
   585  		settleInProgress: map[common.Address]struct{}{},
   586  	}
   587  	channel = NewHermesChannel(
   588  		"1",
   589  		mockID,
   590  		hermesID,
   591  		client.ProviderChannel{Stake: big.NewInt(0)},
   592  		HermesPromise{Promise: crypto.Promise{Amount: units.FloatEthToBigIntWei(5)}},
   593  		beneficiaryID,
   594  	)
   595  
   596  	needs, maxFee = hps.needsSettling(s, 0, 0.01, 5, 10, channel, 1)
   597  	assert.True(t, needs, "should be true if fees are 1%% of unsettled amount")
   598  	assert.True(t, maxFee.Cmp(units.FloatEthToBigIntWei(0.045)) > 0, "should be bigger than current fee")
   599  
   600  	s.registered = false
   601  	needs, _ = hps.needsSettling(s, 0, 0.01, 5, 10, channel, 1)
   602  	assert.False(t, needs, "should be false with no registration")
   603  
   604  	s.settleInProgress = map[common.Address]struct{}{
   605  		hermesID: {},
   606  	}
   607  	needs, _ = hps.needsSettling(s, 0, 0.01, 5, 10, channel, 1)
   608  	assert.False(t, needs, "should be false with settle in progress")
   609  
   610  	hps = &hermesPromiseSettler{
   611  		transactor: &mockTransactor{
   612  			feesToReturn: registry.FeesResponse{
   613  				Fee:        units.FloatEthToBigIntWei(0.051),
   614  				ValidUntil: time.Now().Add(30 * time.Minute),
   615  			},
   616  		},
   617  	}
   618  	s = settlementState{
   619  		registered:       true,
   620  		settleInProgress: map[common.Address]struct{}{},
   621  	}
   622  	channel = NewHermesChannel(
   623  		"1",
   624  		mockID,
   625  		hermesID,
   626  		client.ProviderChannel{Stake: big.NewInt(0)},
   627  		HermesPromise{Promise: crypto.Promise{Amount: big.NewInt(8999)}},
   628  		beneficiaryID,
   629  	)
   630  	needs, _ = hps.needsSettling(s, 0, 0.01, 5, 10, channel, 1)
   631  	assert.False(t, needs, "should be false with fee more than 1%% of unsettled amount")
   632  
   633  	s = settlementState{
   634  		registered:       true,
   635  		settleInProgress: map[common.Address]struct{}{},
   636  	}
   637  	channel = NewHermesChannel(
   638  		"1",
   639  		mockID,
   640  		hermesID,
   641  		client.ProviderChannel{Stake: big.NewInt(1000)},
   642  		HermesPromise{Promise: crypto.Promise{Amount: big.NewInt(1000)}},
   643  		beneficiaryID,
   644  	)
   645  	needs, maxFee = hps.needsSettling(s, 0.1, 0.01, 5, 10, channel, 1)
   646  	assert.True(t, needs, "should be true with zero balance left")
   647  	assert.Nil(t, maxFee, "should be nil")
   648  
   649  	s = settlementState{
   650  		registered:       true,
   651  		settleInProgress: map[common.Address]struct{}{},
   652  	}
   653  	channel = NewHermesChannel(
   654  		"1",
   655  		mockID,
   656  		hermesID,
   657  		client.ProviderChannel{Stake: big.NewInt(1000)},
   658  		HermesPromise{Promise: crypto.Promise{Amount: big.NewInt(9000)}},
   659  		beneficiaryID,
   660  	)
   661  	needs, maxFee = hps.needsSettling(s, 0.1, 0.01, 5, 10, channel, 1)
   662  	assert.True(t, needs, "should be true with 10% missing")
   663  	assert.Nil(t, maxFee, "should be nil")
   664  
   665  	s = settlementState{
   666  		registered:       true,
   667  		settleInProgress: map[common.Address]struct{}{},
   668  	}
   669  	channel = NewHermesChannel(
   670  		"1",
   671  		mockID,
   672  		hermesID,
   673  		client.ProviderChannel{Stake: big.NewInt(10000)},
   674  		HermesPromise{Promise: crypto.Promise{Amount: big.NewInt(8999)}},
   675  		beneficiaryID,
   676  	)
   677  	needs, _ = hps.needsSettling(s, 0.1, 0.01, 5, 10, channel, 1)
   678  	assert.False(t, needs, "should be false with 10.01% missing")
   679  }
   680  
   681  // mocks start here
   682  type mockProviderChannelStatusProvider struct {
   683  	channelToReturn       client.ProviderChannel
   684  	channelReturnError    error
   685  	sinkToReturn          chan *bindings.HermesImplementationPromiseSettled
   686  	subCancel             func()
   687  	subError              error
   688  	feeToReturn           uint16
   689  	feeError              error
   690  	calculatedFees        *big.Int
   691  	calculationError      error
   692  	balanceToReturn       *big.Int
   693  	headerToReturn        *types.Header
   694  	errorToReturn         error
   695  	promiseEventsToReturn []bindings.HermesImplementationPromiseSettled
   696  	promiseError          error
   697  }
   698  
   699  func (mpcsp *mockProviderChannelStatusProvider) TransactionReceipt(chainID int64, hash common.Hash) (*types.Receipt, error) {
   700  	r := &types.Receipt{}
   701  	r.Status = types.ReceiptStatusSuccessful
   702  	return r, nil
   703  }
   704  
   705  func (mpcsp *mockProviderChannelStatusProvider) GetProviderChannel(chainID int64, hermesAddress common.Address, addressToCheck common.Address, pending bool) (client.ProviderChannel, error) {
   706  	return mpcsp.channelToReturn, mpcsp.channelReturnError
   707  }
   708  
   709  func (mpcsp *mockProviderChannelStatusProvider) GetHermesFee(chainID int64, hermesAddress common.Address) (uint16, error) {
   710  	return mpcsp.feeToReturn, mpcsp.feeError
   711  }
   712  
   713  func (mpcsp *mockProviderChannelStatusProvider) GetBeneficiary(chainID int64, registryAddress, identity common.Address) (common.Address, error) {
   714  	return common.Address{}, nil
   715  }
   716  
   717  func (mpcsp *mockProviderChannelStatusProvider) CalculateHermesFee(chainID int64, hermesAddress common.Address, value *big.Int) (*big.Int, error) {
   718  	return mpcsp.calculatedFees, mpcsp.calculationError
   719  }
   720  
   721  func (mpcsp *mockProviderChannelStatusProvider) GetMystBalance(chainID int64, mystAddress common.Address, address common.Address) (*big.Int, error) {
   722  	return mpcsp.balanceToReturn, nil
   723  }
   724  
   725  func (mpcsp *mockProviderChannelStatusProvider) GetProvidersWithdrawalChannel(chainID int64, hermesAddress common.Address, addressToCheck common.Address, pending bool) (client.ProviderChannel, error) {
   726  	return client.ProviderChannel{}, nil
   727  }
   728  
   729  func (mpcsp *mockProviderChannelStatusProvider) FilterPromiseSettledEventByChannelID(chainID int64, from uint64, to *uint64, hermesID common.Address, providerAddresses [][32]byte) ([]bindings.HermesImplementationPromiseSettled, error) {
   730  	return mpcsp.promiseEventsToReturn, mpcsp.promiseError
   731  }
   732  
   733  func (mpcsp *mockProviderChannelStatusProvider) HeaderByNumber(chainID int64, number *big.Int) (*types.Header, error) {
   734  	return mpcsp.headerToReturn, mpcsp.errorToReturn
   735  }
   736  
   737  var cfg = HermesPromiseSettlerConfig{
   738  	MaxFeeThreshold:         0.01,
   739  	MinAutoSettleAmount:     5,
   740  	MaxUnSettledAmount:      20,
   741  	SettlementCheckTimeout:  time.Millisecond * 10,
   742  	SettlementCheckInterval: time.Millisecond * 1,
   743  }
   744  
   745  type mockHermesChannelProvider struct {
   746  	channelToReturn    HermesChannel
   747  	channelReturnError error
   748  }
   749  
   750  func (mhcp *mockHermesChannelProvider) Get(chainID int64, _ identity.Identity, _ common.Address) (HermesChannel, bool) {
   751  	return mhcp.channelToReturn, true
   752  }
   753  
   754  func (mhcp *mockHermesChannelProvider) Fetch(chainID int64, _ identity.Identity, _ common.Address) (HermesChannel, error) {
   755  	return mhcp.channelToReturn, mhcp.channelReturnError
   756  }
   757  
   758  type mockRegistrationStatus struct {
   759  	status registry.RegistrationStatus
   760  	err    error
   761  }
   762  
   763  type mockRegistrationStatusProvider struct {
   764  	identities map[string]mockRegistrationStatus
   765  }
   766  
   767  func (mrsp *mockRegistrationStatusProvider) GetRegistrationStatus(chainID int64, id identity.Identity) (registry.RegistrationStatus, error) {
   768  	if v, ok := mrsp.identities[fmt.Sprintf("%d%s", chainID, id.Address)]; ok {
   769  		return v.status, v.err
   770  	}
   771  
   772  	return registry.Unregistered, nil
   773  }
   774  
   775  var errMock = errors.New("explosions everywhere")
   776  var mockID = identity.FromAddress("0x0000000000000000000000000000000000000001")
   777  var hermesID = common.HexToAddress("0x00000000000000000000000000000000000000002")
   778  var beneficiaryID = common.HexToAddress("0x00000000000000000000000000000000000000132")
   779  var mockChainIdentity = "0" + mockID.Address
   780  
   781  var mockProviderChannel = client.ProviderChannel{
   782  	Settled: big.NewInt(9000000),
   783  	Stake:   big.NewInt(1000000000000),
   784  }
   785  
   786  type mockTransactor struct {
   787  	feesError    error
   788  	feesToReturn registry.FeesResponse
   789  
   790  	statusToReturn registry.TransactorStatusResponse
   791  	statusError    error
   792  
   793  	queueToReturn registry.QueueResponse
   794  	queueError    error
   795  
   796  	idToReturn  string
   797  	settleError error
   798  }
   799  
   800  func (mt *mockTransactor) FetchSettleFees(chainID int64) (registry.FeesResponse, error) {
   801  	return mt.feesToReturn, mt.feesError
   802  }
   803  
   804  func (mt *mockTransactor) SettleAndRebalance(_, _ string, _ crypto.Promise) (string, error) {
   805  	return mt.idToReturn, mt.settleError
   806  }
   807  
   808  func (mt *mockTransactor) SettleWithBeneficiary(_, _, _ string, _ crypto.Promise) (string, error) {
   809  	return mt.idToReturn, mt.settleError
   810  }
   811  
   812  func (mt *mockTransactor) SettleIntoStake(accountantID, providerID string, promise crypto.Promise) (string, error) {
   813  	return mt.idToReturn, mt.settleError
   814  }
   815  
   816  func (mt *mockTransactor) PayAndSettle(hermesID, providerID string, promise crypto.Promise, beneficiary string, beneficiarySignature string) (string, error) {
   817  	return mt.idToReturn, mt.settleError
   818  }
   819  
   820  func (mt *mockTransactor) FetchRegistrationStatus(id string) ([]registry.TransactorStatusResponse, error) {
   821  	return []registry.TransactorStatusResponse{mt.statusToReturn}, mt.statusError
   822  }
   823  
   824  func (mt *mockTransactor) FetchRegistrationFees(chainID int64) (registry.FeesResponse, error) {
   825  	return mt.feesToReturn, mt.feesError
   826  }
   827  
   828  func (mt *mockTransactor) GetQueueStatus(ID string) (registry.QueueResponse, error) {
   829  	return mt.queueToReturn, mt.queueError
   830  }
   831  
   832  type settlementHistoryStorageMock struct{}
   833  
   834  func (shsm *settlementHistoryStorageMock) Store(_ SettlementHistoryEntry) error {
   835  	return nil
   836  }
   837  
   838  type mockPayAndSettler struct{}
   839  
   840  func (mpas *mockPayAndSettler) PayAndSettle(r []byte, em crypto.ExchangeMessage, providerID identity.Identity, sessionID string) <-chan error {
   841  	return nil
   842  }
   843  
   844  type mockAddressStorage struct {
   845  	data map[string]string
   846  }
   847  
   848  func newMockAddressStorage() *mockAddressStorage {
   849  	return &mockAddressStorage{data: make(map[string]string)}
   850  }
   851  
   852  func (m mockAddressStorage) Address(identity string) (string, error) {
   853  	return m.data[identity], nil
   854  }
   855  
   856  func (m mockAddressStorage) Save(identity, address string) error {
   857  	m.data[identity] = address
   858  	return nil
   859  }