WIP: IR unit tests #279
56 changed files with 3080 additions and 225 deletions
|
@ -104,13 +104,13 @@ func (l GlagoliticLetter) String() string {
|
|||
return "unknown"
|
||||
}
|
||||
|
||||
type alphabetContracts map[GlagoliticLetter]util.Uint160
|
||||
type AlphabetContracts map[GlagoliticLetter]util.Uint160
|
||||
|
||||
func newAlphabetContracts() alphabetContracts {
|
||||
func NewAlphabetContracts() AlphabetContracts {
|
||||
return make(map[GlagoliticLetter]util.Uint160, lastLetterNum)
|
||||
}
|
||||
|
||||
func (a alphabetContracts) GetByIndex(ind int) (util.Uint160, bool) {
|
||||
func (a AlphabetContracts) GetByIndex(ind int) (util.Uint160, bool) {
|
||||
if ind < 0 || ind >= int(lastLetterNum) {
|
||||
return util.Uint160{}, false
|
||||
}
|
||||
|
@ -120,16 +120,16 @@ func (a alphabetContracts) GetByIndex(ind int) (util.Uint160, bool) {
|
|||
return contract, ok
|
||||
}
|
||||
|
||||
func (a alphabetContracts) indexOutOfRange(ind int) bool {
|
||||
func (a AlphabetContracts) indexOutOfRange(ind int) bool {
|
||||
return ind < 0 && ind >= len(a)
|
||||
}
|
||||
|
||||
func (a alphabetContracts) iterate(f func(GlagoliticLetter, util.Uint160)) {
|
||||
func (a AlphabetContracts) iterate(f func(GlagoliticLetter, util.Uint160)) {
|
||||
for letter, contract := range a {
|
||||
f(letter, contract)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *alphabetContracts) set(l GlagoliticLetter, h util.Uint160) {
|
||||
func (a *AlphabetContracts) set(l GlagoliticLetter, h util.Uint160) {
|
||||
(*a)[l] = h
|
||||
}
|
||||
|
|
|
@ -33,6 +33,10 @@ type (
|
|||
|
||||
newEpochHandler func()
|
||||
|
||||
containerEstimationStopper interface {
|
||||
StopEstimation(p container.StopEstimationPrm) error
|
||||
}
|
||||
|
||||
epochTimerArgs struct {
|
||||
l *logger.Logger
|
||||
|
||||
|
@ -40,8 +44,8 @@ type (
|
|||
|
||||
newEpochHandlers []newEpochHandler
|
||||
|
||||
cnrWrapper *container.Client // to invoke stop container estimation
|
||||
epoch epochState // to specify which epoch to stop, and epoch duration
|
||||
cnrWrapper containerEstimationStopper // to invoke stop container estimation
|
||||
epoch epochState // to specify which epoch to stop, and epoch duration
|
||||
|
||||
stopEstimationDMul uint32 // X: X/Y of epoch in blocks
|
||||
stopEstimationDDiv uint32 // Y: X/Y of epoch in blocks
|
||||
|
|
167
pkg/innerring/blocktimer_test.go
Normal file
167
pkg/innerring/blocktimer_test.go
Normal file
|
@ -0,0 +1,167 @@
|
|||
package innerring
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEpochTimer(t *testing.T) {
|
||||
t.Parallel()
|
||||
alphaState := &testAlphabetState{isAlphabet: true}
|
||||
neh := &testNewEpochHandler{}
|
||||
cnrStopper := &testContainerEstStopper{}
|
||||
epochState := &testEpochState{
|
||||
counter: 99,
|
||||
duration: 10,
|
||||
}
|
||||
collectHandler := &testEventHandler{}
|
||||
distributeHandler := &testEventHandler{}
|
||||
|
||||
args := &epochTimerArgs{
|
||||
l: test.NewLogger(t, true),
|
||||
alphabetState: alphaState,
|
||||
newEpochHandlers: []newEpochHandler{neh.Handle},
|
||||
cnrWrapper: cnrStopper,
|
||||
epoch: epochState,
|
||||
stopEstimationDMul: 2,
|
||||
stopEstimationDDiv: 10,
|
||||
collectBasicIncome: subEpochEventHandler{
|
||||
handler: collectHandler.Handle,
|
||||
durationMul: 3,
|
||||
durationDiv: 10,
|
||||
},
|
||||
distributeBasicIncome: subEpochEventHandler{
|
||||
handler: distributeHandler.Handle,
|
||||
durationMul: 4,
|
||||
durationDiv: 10,
|
||||
},
|
||||
}
|
||||
et := newEpochTimer(args)
|
||||
err := et.Reset()
|
||||
require.NoError(t, err, "failed to reset timer")
|
||||
|
||||
et.Tick(100)
|
||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 0, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 0, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 0, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
et.Tick(101)
|
||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 0, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 0, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
et.Tick(102)
|
||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 1, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 0, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
et.Tick(103)
|
||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 1, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 1, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
var h uint32
|
||||
for h = 104; h < 109; h++ {
|
||||
et.Tick(h)
|
||||
require.Equal(t, 0, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 1, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 1, distributeHandler.called, "invalid distribute basic income calls")
|
||||
}
|
||||
|
||||
et.Tick(109)
|
||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 1, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 1, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
et.Tick(110)
|
||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 1, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 1, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
et.Tick(111)
|
||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 1, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 1, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
et.Tick(112)
|
||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 2, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 1, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
et.Tick(113)
|
||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 2, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 2, distributeHandler.called, "invalid distribute basic income calls")
|
||||
|
||||
for h = 114; h < 119; h++ {
|
||||
et.Tick(h)
|
||||
require.Equal(t, 1, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 2, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 2, distributeHandler.called, "invalid distribute basic income calls")
|
||||
}
|
||||
et.Tick(120)
|
||||
require.Equal(t, 2, neh.called, "invalid new epoch handler calls")
|
||||
require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls")
|
||||
require.Equal(t, 2, collectHandler.called, "invalid collect basic income calls")
|
||||
require.Equal(t, 2, distributeHandler.called, "invalid distribute basic income calls")
|
||||
}
|
||||
|
||||
type testAlphabetState struct {
|
||||
isAlphabet bool
|
||||
}
|
||||
|
||||
func (s *testAlphabetState) IsAlphabet() bool {
|
||||
return s.isAlphabet
|
||||
}
|
||||
|
||||
type testNewEpochHandler struct {
|
||||
called int
|
||||
}
|
||||
|
||||
func (h *testNewEpochHandler) Handle() {
|
||||
h.called++
|
||||
}
|
||||
|
||||
type testContainerEstStopper struct {
|
||||
called int
|
||||
}
|
||||
|
||||
func (s *testContainerEstStopper) StopEstimation(_ container.StopEstimationPrm) error {
|
||||
s.called++
|
||||
return nil
|
||||
}
|
||||
|
||||
type testEpochState struct {
|
||||
counter uint64
|
||||
duration uint64
|
||||
}
|
||||
|
||||
func (s *testEpochState) EpochCounter() uint64 {
|
||||
return s.counter
|
||||
}
|
||||
func (s *testEpochState) EpochDuration() uint64 {
|
||||
return s.duration
|
||||
}
|
||||
|
||||
type testEventHandler struct {
|
||||
called int
|
||||
}
|
||||
|
||||
func (h *testEventHandler) Handle(e event.Event) {
|
||||
h.called++
|
||||
}
|
68
pkg/innerring/config/fee_test.go
Normal file
68
pkg/innerring/config/fee_test.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("all set", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := strings.NewReader(
|
||||
`
|
||||
fee:
|
||||
main_chain: 50000000
|
||||
side_chain: 200000000
|
||||
named_container_register: 2500000000
|
||||
`,
|
||||
)
|
||||
v := viper.New()
|
||||
v.SetConfigType("yaml")
|
||||
err := v.ReadConfig(file)
|
||||
require.NoError(t, err, "read config file failed")
|
||||
|
||||
config := NewFeeConfig(v)
|
||||
require.Equal(t, fixedn.Fixed8(50000000), config.MainChainFee(), "main chain fee invalid")
|
||||
require.Equal(t, fixedn.Fixed8(200000000), config.SideChainFee(), "side chain fee invalid")
|
||||
require.Equal(t, fixedn.Fixed8(2500000000), config.NamedContainerRegistrationFee(), "named container register fee invalid")
|
||||
})
|
||||
|
||||
t.Run("nothing set", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := strings.NewReader("")
|
||||
v := viper.New()
|
||||
v.SetConfigType("yaml")
|
||||
err := v.ReadConfig(file)
|
||||
require.NoError(t, err, "read config file failed")
|
||||
|
||||
config := NewFeeConfig(v)
|
||||
require.Equal(t, fixedn.Fixed8(0), config.MainChainFee(), "main chain fee invalid")
|
||||
require.Equal(t, fixedn.Fixed8(0), config.SideChainFee(), "side chain fee invalid")
|
||||
require.Equal(t, fixedn.Fixed8(0), config.NamedContainerRegistrationFee(), "named container register fee invalid")
|
||||
})
|
||||
|
||||
t.Run("partially set", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := strings.NewReader(
|
||||
`
|
||||
fee:
|
||||
main_chain: 10
|
||||
`,
|
||||
)
|
||||
v := viper.New()
|
||||
v.SetConfigType("yaml")
|
||||
err := v.ReadConfig(file)
|
||||
require.NoError(t, err, "read config file failed")
|
||||
|
||||
config := NewFeeConfig(v)
|
||||
require.Equal(t, fixedn.Fixed8(10), config.MainChainFee(), "main chain fee invalid")
|
||||
require.Equal(t, fixedn.Fixed8(0), config.SideChainFee(), "side chain fee invalid")
|
||||
require.Equal(t, fixedn.Fixed8(0), config.NamedContainerRegistrationFee(), "named container register fee invalid")
|
||||
})
|
||||
|
||||
}
|
|
@ -20,10 +20,10 @@ type contracts struct {
|
|||
processing util.Uint160 // in mainnet
|
||||
frostfsID util.Uint160 // in morph
|
||||
|
||||
alphabet alphabetContracts // in morph
|
||||
alphabet AlphabetContracts // in morph
|
||||
}
|
||||
|
||||
func parseContracts(cfg *viper.Viper, morph *client.Client, withoutMainNet, withoutMainNotary, withoutSideNotary bool) (*contracts, error) {
|
||||
func parseContracts(cfg *viper.Viper, morph nnsResolver, withoutMainNet, withoutMainNotary, withoutSideNotary bool) (*contracts, error) {
|
||||
var (
|
||||
result = new(contracts)
|
||||
err error
|
||||
|
@ -78,9 +78,9 @@ func parseContracts(cfg *viper.Viper, morph *client.Client, withoutMainNet, with
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func parseAlphabetContracts(cfg *viper.Viper, morph *client.Client) (alphabetContracts, error) {
|
||||
func parseAlphabetContracts(cfg *viper.Viper, morph nnsResolver) (AlphabetContracts, error) {
|
||||
num := GlagoliticLetter(cfg.GetUint("contracts.alphabet.amount"))
|
||||
alpha := newAlphabetContracts()
|
||||
alpha := NewAlphabetContracts()
|
||||
|
||||
if num > lastLetterNum {
|
||||
return nil, fmt.Errorf("amount of alphabet contracts overflows glagolitsa %d > %d", num, lastLetterNum)
|
||||
|
@ -117,7 +117,7 @@ func parseAlphabetContracts(cfg *viper.Viper, morph *client.Client) (alphabetCon
|
|||
return alpha, nil
|
||||
}
|
||||
|
||||
func parseContract(cfg *viper.Viper, morph *client.Client, cfgName, nnsName string) (res util.Uint160, err error) {
|
||||
func parseContract(cfg *viper.Viper, morph nnsResolver, cfgName, nnsName string) (res util.Uint160, err error) {
|
||||
contractStr := cfg.GetString(cfgName)
|
||||
if len(contractStr) == 0 {
|
||||
return morph.NNSContractAddress(nnsName)
|
||||
|
@ -125,3 +125,7 @@ func parseContract(cfg *viper.Viper, morph *client.Client, cfgName, nnsName stri
|
|||
|
||||
return util.Uint160DecodeStringLE(contractStr)
|
||||
}
|
||||
|
||||
type nnsResolver interface {
|
||||
NNSContractAddress(name string) (sh util.Uint160, err error)
|
||||
}
|
||||
|
|
222
pkg/innerring/contracts_test.go
Normal file
222
pkg/innerring/contracts_test.go
Normal file
|
@ -0,0 +1,222 @@
|
|||
package innerring
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseContractsSuccess(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := strings.NewReader(`
|
||||
contracts:
|
||||
frostfs: ee3dee6d05dc79c24a5b8f6985e10d68b7cacc62
|
||||
processing: 597f5894867113a41e192801709c02497f611de8
|
||||
audit: 219e37aed2180b87e7fe945dbf97d67125e8d73f
|
||||
balance: d2aa48d14b17b11bc4c68205027884a96706dd16
|
||||
container: ed4a7a66fe3f9bfe50f214b49be8f215a3c886b6
|
||||
frostfsid: 9f5866decbc751a099e74c7c7bc89f609201755a
|
||||
netmap: 83c600c81d47a1b1b7cf58eb49ae7ee7240dc742
|
||||
proxy: abc8794bb40a21f2db5f21ae62741eb46c8cad1c
|
||||
alphabet:
|
||||
amount: 2
|
||||
az: c1d211fceeb4b1dc76b8e4054d11fdf887e418ea
|
||||
buky: e2ba789320899658b100f331bdebb74474757920
|
||||
`)
|
||||
|
||||
v := viper.New()
|
||||
v.SetConfigType("yaml")
|
||||
err := v.ReadConfig(file)
|
||||
require.NoError(t, err, "read config file failed")
|
||||
|
||||
t.Run("all enabled", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, err := parseContracts(v, nil, false, false, false)
|
||||
require.NoError(t, err, "failed to parse contracts")
|
||||
|
||||
frostfsExp, _ := util.Uint160DecodeStringLE("ee3dee6d05dc79c24a5b8f6985e10d68b7cacc62")
|
||||
require.Equal(t, frostfsExp, c.frostfs, "invalid frostfs")
|
||||
|
||||
processingExp, _ := util.Uint160DecodeStringLE("597f5894867113a41e192801709c02497f611de8")
|
||||
require.Equal(t, processingExp, c.processing, "invalid processing")
|
||||
|
||||
auditExp, _ := util.Uint160DecodeStringLE("219e37aed2180b87e7fe945dbf97d67125e8d73f")
|
||||
require.Equal(t, auditExp, c.audit, "invalid audit")
|
||||
|
||||
balanceExp, _ := util.Uint160DecodeStringLE("d2aa48d14b17b11bc4c68205027884a96706dd16")
|
||||
require.Equal(t, balanceExp, c.balance, "invalid balance")
|
||||
|
||||
containerExp, _ := util.Uint160DecodeStringLE("ed4a7a66fe3f9bfe50f214b49be8f215a3c886b6")
|
||||
require.Equal(t, containerExp, c.container, "invalid container")
|
||||
|
||||
frostfsIDExp, _ := util.Uint160DecodeStringLE("9f5866decbc751a099e74c7c7bc89f609201755a")
|
||||
require.Equal(t, frostfsIDExp, c.frostfsID, "invalid frostfsID")
|
||||
|
||||
netmapIDExp, _ := util.Uint160DecodeStringLE("83c600c81d47a1b1b7cf58eb49ae7ee7240dc742")
|
||||
require.Equal(t, netmapIDExp, c.netmap, "invalid netmap")
|
||||
|
||||
proxyExp, _ := util.Uint160DecodeStringLE("abc8794bb40a21f2db5f21ae62741eb46c8cad1c")
|
||||
require.Equal(t, proxyExp, c.proxy, "invalid proxy")
|
||||
|
||||
require.Equal(t, 2, len(c.alphabet), "invalid alphabet contracts length")
|
||||
|
||||
azExp, _ := util.Uint160DecodeStringLE("c1d211fceeb4b1dc76b8e4054d11fdf887e418ea")
|
||||
require.Equal(t, azExp, c.alphabet[az], "invalid az")
|
||||
|
||||
bukyExp, _ := util.Uint160DecodeStringLE("e2ba789320899658b100f331bdebb74474757920")
|
||||
require.Equal(t, bukyExp, c.alphabet[buky], "invalid buky")
|
||||
})
|
||||
|
||||
t.Run("all disabled", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, err := parseContracts(v, nil, true, true, true)
|
||||
require.NoError(t, err, "failed to parse contracts")
|
||||
|
||||
require.Equal(t, util.Uint160{}, c.frostfs, "invalid frostfs")
|
||||
|
||||
require.Equal(t, util.Uint160{}, c.processing, "invalid processing")
|
||||
|
||||
auditExp, _ := util.Uint160DecodeStringLE("219e37aed2180b87e7fe945dbf97d67125e8d73f")
|
||||
require.Equal(t, auditExp, c.audit, "invalid audit")
|
||||
|
||||
balanceExp, _ := util.Uint160DecodeStringLE("d2aa48d14b17b11bc4c68205027884a96706dd16")
|
||||
require.Equal(t, balanceExp, c.balance, "invalid balance")
|
||||
|
||||
containerExp, _ := util.Uint160DecodeStringLE("ed4a7a66fe3f9bfe50f214b49be8f215a3c886b6")
|
||||
require.Equal(t, containerExp, c.container, "invalid container")
|
||||
|
||||
frostfsIDExp, _ := util.Uint160DecodeStringLE("9f5866decbc751a099e74c7c7bc89f609201755a")
|
||||
require.Equal(t, frostfsIDExp, c.frostfsID, "invalid frostfsID")
|
||||
|
||||
netmapIDExp, _ := util.Uint160DecodeStringLE("83c600c81d47a1b1b7cf58eb49ae7ee7240dc742")
|
||||
require.Equal(t, netmapIDExp, c.netmap, "invalid netmap")
|
||||
|
||||
require.Equal(t, util.Uint160{}, c.proxy, "invalid proxy")
|
||||
|
||||
require.Equal(t, 2, len(c.alphabet), "invalid alphabet contracts length")
|
||||
|
||||
azExp, _ := util.Uint160DecodeStringLE("c1d211fceeb4b1dc76b8e4054d11fdf887e418ea")
|
||||
require.Equal(t, azExp, c.alphabet[az], "invalid az")
|
||||
|
||||
bukyExp, _ := util.Uint160DecodeStringLE("e2ba789320899658b100f331bdebb74474757920")
|
||||
require.Equal(t, bukyExp, c.alphabet[buky], "invalid buky")
|
||||
})
|
||||
|
||||
t.Run("main notary & side notary disabled", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, err := parseContracts(v, nil, false, true, true)
|
||||
require.NoError(t, err, "failed to parse contracts")
|
||||
|
||||
frostfsExp, _ := util.Uint160DecodeStringLE("ee3dee6d05dc79c24a5b8f6985e10d68b7cacc62")
|
||||
require.Equal(t, frostfsExp, c.frostfs, "invalid frostfs")
|
||||
|
||||
require.Equal(t, util.Uint160{}, c.processing, "invalid processing")
|
||||
|
||||
auditExp, _ := util.Uint160DecodeStringLE("219e37aed2180b87e7fe945dbf97d67125e8d73f")
|
||||
require.Equal(t, auditExp, c.audit, "invalid audit")
|
||||
|
||||
balanceExp, _ := util.Uint160DecodeStringLE("d2aa48d14b17b11bc4c68205027884a96706dd16")
|
||||
require.Equal(t, balanceExp, c.balance, "invalid balance")
|
||||
|
||||
containerExp, _ := util.Uint160DecodeStringLE("ed4a7a66fe3f9bfe50f214b49be8f215a3c886b6")
|
||||
require.Equal(t, containerExp, c.container, "invalid container")
|
||||
|
||||
frostfsIDExp, _ := util.Uint160DecodeStringLE("9f5866decbc751a099e74c7c7bc89f609201755a")
|
||||
require.Equal(t, frostfsIDExp, c.frostfsID, "invalid frostfsID")
|
||||
|
||||
netmapIDExp, _ := util.Uint160DecodeStringLE("83c600c81d47a1b1b7cf58eb49ae7ee7240dc742")
|
||||
require.Equal(t, netmapIDExp, c.netmap, "invalid netmap")
|
||||
|
||||
require.Equal(t, util.Uint160{}, c.proxy, "invalid proxy")
|
||||
|
||||
require.Equal(t, 2, len(c.alphabet), "invalid alphabet contracts length")
|
||||
|
||||
azExp, _ := util.Uint160DecodeStringLE("c1d211fceeb4b1dc76b8e4054d11fdf887e418ea")
|
||||
require.Equal(t, azExp, c.alphabet[az], "invalid az")
|
||||
|
||||
bukyExp, _ := util.Uint160DecodeStringLE("e2ba789320899658b100f331bdebb74474757920")
|
||||
require.Equal(t, bukyExp, c.alphabet[buky], "invalid buky")
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseContractsInvalid(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("invalid audit contract", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := strings.NewReader(`
|
||||
contracts:
|
||||
frostfs: invalid_data
|
||||
processing: 597f5894867113a41e192801709c02497f611de8
|
||||
audit: 219e37aed2180b87e7fe945dbf97d67125e8d73f
|
||||
balance: d2aa48d14b17b11bc4c68205027884a96706dd16
|
||||
container: ed4a7a66fe3f9bfe50f214b49be8f215a3c886b6
|
||||
frostfsid: 9f5866decbc751a099e74c7c7bc89f609201755a
|
||||
netmap: 83c600c81d47a1b1b7cf58eb49ae7ee7240dc742
|
||||
proxy: abc8794bb40a21f2db5f21ae62741eb46c8cad1c
|
||||
alphabet:
|
||||
amount: 2
|
||||
az: c1d211fceeb4b1dc76b8e4054d11fdf887e418ea
|
||||
buky: e2ba789320899658b100f331bdebb74474757920
|
||||
`)
|
||||
|
||||
v := viper.New()
|
||||
v.SetConfigType("yaml")
|
||||
err := v.ReadConfig(file)
|
||||
require.NoError(t, err, "read config file failed")
|
||||
|
||||
_, err = parseContracts(v, nil, false, false, false)
|
||||
require.Error(t, err, "unexpected success")
|
||||
})
|
||||
|
||||
t.Run("invalid alphabet count", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := strings.NewReader(`
|
||||
contracts:
|
||||
frostfs: ee3dee6d05dc79c24a5b8f6985e10d68b7cacc62
|
||||
processing: 597f5894867113a41e192801709c02497f611de8
|
||||
audit: 219e37aed2180b87e7fe945dbf97d67125e8d73f
|
||||
balance: d2aa48d14b17b11bc4c68205027884a96706dd16
|
||||
container: ed4a7a66fe3f9bfe50f214b49be8f215a3c886b6
|
||||
frostfsid: 9f5866decbc751a099e74c7c7bc89f609201755a
|
||||
netmap: 83c600c81d47a1b1b7cf58eb49ae7ee7240dc742
|
||||
proxy: abc8794bb40a21f2db5f21ae62741eb46c8cad1c
|
||||
alphabet:
|
||||
amount: 3
|
||||
az: c1d211fceeb4b1dc76b8e4054d11fdf887e418ea
|
||||
buky: e2ba789320899658b100f331bdebb74474757920
|
||||
`)
|
||||
|
||||
v := viper.New()
|
||||
v.SetConfigType("yaml")
|
||||
err := v.ReadConfig(file)
|
||||
require.NoError(t, err, "read config file failed")
|
||||
|
||||
azExp, _ := util.Uint160DecodeStringLE("c1d211fceeb4b1dc76b8e4054d11fdf887e418ea")
|
||||
bukyExp, _ := util.Uint160DecodeStringLE("e2ba789320899658b100f331bdebb74474757920")
|
||||
|
||||
morph := &testParserMorph{
|
||||
values: map[string]util.Uint160{
|
||||
"az": azExp,
|
||||
"buky": bukyExp,
|
||||
},
|
||||
}
|
||||
|
||||
_, err = parseContracts(v, morph, false, false, false)
|
||||
require.ErrorContains(t, err, "could not read all contracts: required 3, read 2", "unexpected success")
|
||||
})
|
||||
}
|
||||
|
||||
type testParserMorph struct {
|
||||
values map[string]util.Uint160
|
||||
}
|
||||
|
||||
func (m *testParserMorph) NNSContractAddress(name string) (sh util.Uint160, err error) {
|
||||
if value, found := m.values[name]; found {
|
||||
return value, nil
|
||||
}
|
||||
return util.Uint160{}, client.ErrNNSRecordNotFound
|
||||
}
|
225
pkg/innerring/indexer_test.go
Normal file
225
pkg/innerring/indexer_test.go
Normal file
|
@ -0,0 +1,225 @@
|
|||
package innerring
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/atomic"
|
||||
)
|
||||
|
||||
func TestIndexerReturnsIndexes(t *testing.T) {
|
||||
t.Parallel()
|
||||
commiteeKeys, err := keys.NewPublicKeysFromStrings([]string{
|
||||
"03ff65b6ae79134a4dce9d0d39d3851e9bab4ee97abf86e81e1c5bbc50cd2826ae",
|
||||
"022bb4041c50d607ff871dec7e4cd7778388e0ea6849d84ccbd9aa8f32e16a8131",
|
||||
})
|
||||
require.NoError(t, err, "convert string to commitee public keys failed")
|
||||
cf := &testCommiteeFetcher{
|
||||
keys: commiteeKeys,
|
||||
}
|
||||
|
||||
irKeys, err := keys.NewPublicKeysFromStrings([]string{
|
||||
"038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35",
|
||||
"02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3",
|
||||
"022bb4041c50d607ff871dec7e4cd7778388e0ea6849d84ccbd9aa8f32e16a8131",
|
||||
})
|
||||
require.NoError(t, err, "convert string to IR public keys failed")
|
||||
irf := &testIRFetcher{
|
||||
keys: irKeys,
|
||||
}
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
key := irKeys[2]
|
||||
|
||||
indexer := newInnerRingIndexer(cf, irf, key, time.Second)
|
||||
|
||||
idx, err := indexer.AlphabetIndex()
|
||||
require.NoError(t, err, "failed to get alphabet index")
|
||||
require.Equal(t, int32(1), idx, "invalid alphabet index")
|
||||
|
||||
idx, err = indexer.InnerRingIndex()
|
||||
require.NoError(t, err, "failed to get IR index")
|
||||
require.Equal(t, int32(2), idx, "invalid IR index")
|
||||
|
||||
size, err := indexer.InnerRingSize()
|
||||
require.NoError(t, err, "failed to get IR size")
|
||||
require.Equal(t, int32(3), size, "invalid IR size")
|
||||
})
|
||||
|
||||
t.Run("not found alphabet", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
key := irKeys[0]
|
||||
|
||||
indexer := newInnerRingIndexer(cf, irf, key, time.Second)
|
||||
|
||||
idx, err := indexer.AlphabetIndex()
|
||||
require.NoError(t, err, "failed to get alphabet index")
|
||||
require.Equal(t, int32(-1), idx, "invalid alphabet index")
|
||||
|
||||
idx, err = indexer.InnerRingIndex()
|
||||
require.NoError(t, err, "failed to get IR index")
|
||||
require.Equal(t, int32(0), idx, "invalid IR index")
|
||||
})
|
||||
|
||||
t.Run("not found IR", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
key := commiteeKeys[0]
|
||||
|
||||
indexer := newInnerRingIndexer(cf, irf, key, time.Second)
|
||||
|
||||
idx, err := indexer.AlphabetIndex()
|
||||
require.NoError(t, err, "failed to get alphabet index")
|
||||
require.Equal(t, int32(0), idx, "invalid alphabet index")
|
||||
|
||||
idx, err = indexer.InnerRingIndex()
|
||||
require.NoError(t, err, "failed to get IR index")
|
||||
require.Equal(t, int32(-1), idx, "invalid IR index")
|
||||
})
|
||||
}
|
||||
|
||||
func TestIndexerCachesIndexes(t *testing.T) {
|
||||
t.Parallel()
|
||||
commiteeKeys, err := keys.NewPublicKeysFromStrings([]string{})
|
||||
require.NoError(t, err, "convert string to commitee public keys failed")
|
||||
cf := &testCommiteeFetcher{
|
||||
keys: commiteeKeys,
|
||||
}
|
||||
|
||||
irKeys, err := keys.NewPublicKeysFromStrings([]string{})
|
||||
require.NoError(t, err, "convert string to IR public keys failed")
|
||||
irf := &testIRFetcher{
|
||||
keys: irKeys,
|
||||
}
|
||||
|
||||
key, err := keys.NewPublicKeyFromString("022bb4041c50d607ff871dec7e4cd7778388e0ea6849d84ccbd9aa8f32e16a8131")
|
||||
require.NoError(t, err, "convert string to public key failed")
|
||||
|
||||
indexer := newInnerRingIndexer(cf, irf, key, time.Second)
|
||||
|
||||
idx, err := indexer.AlphabetIndex()
|
||||
require.NoError(t, err, "failed to get alphabet index")
|
||||
require.Equal(t, int32(-1), idx, "invalid alphabet index")
|
||||
|
||||
idx, err = indexer.InnerRingIndex()
|
||||
require.NoError(t, err, "failed to get IR index")
|
||||
require.Equal(t, int32(-1), idx, "invalid IR index")
|
||||
|
||||
size, err := indexer.InnerRingSize()
|
||||
require.NoError(t, err, "failed to get IR size")
|
||||
require.Equal(t, int32(0), size, "invalid IR size")
|
||||
|
||||
require.Equal(t, int32(1), cf.calls.Load(), "invalid commitee calls count")
|
||||
require.Equal(t, int32(1), irf.calls.Load(), "invalid IR calls count")
|
||||
|
||||
idx, err = indexer.AlphabetIndex()
|
||||
require.NoError(t, err, "failed to get alphabet index")
|
||||
require.Equal(t, int32(-1), idx, "invalid alphabet index")
|
||||
|
||||
idx, err = indexer.InnerRingIndex()
|
||||
require.NoError(t, err, "failed to get IR index")
|
||||
require.Equal(t, int32(-1), idx, "invalid IR index")
|
||||
|
||||
size, err = indexer.InnerRingSize()
|
||||
require.NoError(t, err, "failed to get IR size")
|
||||
require.Equal(t, int32(0), size, "invalid IR size")
|
||||
|
||||
require.Equal(t, int32(1), cf.calls.Load(), "invalid commitee calls count")
|
||||
require.Equal(t, int32(1), irf.calls.Load(), "invalid IR calls count")
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
idx, err = indexer.AlphabetIndex()
|
||||
require.NoError(t, err, "failed to get alphabet index")
|
||||
require.Equal(t, int32(-1), idx, "invalid alphabet index")
|
||||
|
||||
idx, err = indexer.InnerRingIndex()
|
||||
require.NoError(t, err, "failed to get IR index")
|
||||
require.Equal(t, int32(-1), idx, "invalid IR index")
|
||||
|
||||
size, err = indexer.InnerRingSize()
|
||||
require.NoError(t, err, "failed to get IR size")
|
||||
require.Equal(t, int32(0), size, "invalid IR size")
|
||||
|
||||
require.Equal(t, int32(2), cf.calls.Load(), "invalid commitee calls count")
|
||||
require.Equal(t, int32(2), irf.calls.Load(), "invalid IR calls count")
|
||||
}
|
||||
|
||||
func TestIndexerThrowsErrors(t *testing.T) {
|
||||
t.Parallel()
|
||||
cf := &testCommiteeFetcher{
|
||||
err: fmt.Errorf("test commitee error"),
|
||||
}
|
||||
|
||||
irKeys, err := keys.NewPublicKeysFromStrings([]string{})
|
||||
require.NoError(t, err, "convert string to IR public keys failed")
|
||||
irf := &testIRFetcher{
|
||||
keys: irKeys,
|
||||
}
|
||||
|
||||
key, err := keys.NewPublicKeyFromString("022bb4041c50d607ff871dec7e4cd7778388e0ea6849d84ccbd9aa8f32e16a8131")
|
||||
require.NoError(t, err, "convert string to public key failed")
|
||||
|
||||
indexer := newInnerRingIndexer(cf, irf, key, time.Second)
|
||||
|
||||
idx, err := indexer.AlphabetIndex()
|
||||
require.ErrorContains(t, err, "test commitee error", "error from commitee not throwed")
|
||||
require.Equal(t, int32(0), idx, "invalid alphabet index")
|
||||
|
||||
idx, err = indexer.InnerRingIndex()
|
||||
require.ErrorContains(t, err, "test commitee error", "error from IR not throwed")
|
||||
require.Equal(t, int32(0), idx, "invalid IR index")
|
||||
|
||||
size, err := indexer.InnerRingSize()
|
||||
require.ErrorContains(t, err, "test commitee error", "error from IR not throwed")
|
||||
require.Equal(t, int32(0), size, "invalid IR size")
|
||||
|
||||
commiteeKeys, err := keys.NewPublicKeysFromStrings([]string{})
|
||||
require.NoError(t, err, "convert string to commitee public keys failed")
|
||||
cf = &testCommiteeFetcher{
|
||||
keys: commiteeKeys,
|
||||
}
|
||||
|
||||
irf = &testIRFetcher{
|
||||
err: fmt.Errorf("test IR error"),
|
||||
}
|
||||
|
||||
indexer = newInnerRingIndexer(cf, irf, key, time.Second)
|
||||
|
||||
idx, err = indexer.AlphabetIndex()
|
||||
require.ErrorContains(t, err, "test IR error", "error from commitee not throwed")
|
||||
require.Equal(t, int32(0), idx, "invalid alphabet index")
|
||||
|
||||
idx, err = indexer.InnerRingIndex()
|
||||
require.ErrorContains(t, err, "test IR error", "error from IR not throwed")
|
||||
require.Equal(t, int32(0), idx, "invalid IR index")
|
||||
|
||||
size, err = indexer.InnerRingSize()
|
||||
require.ErrorContains(t, err, "test IR error", "error from IR not throwed")
|
||||
require.Equal(t, int32(0), size, "invalid IR size")
|
||||
}
|
||||
|
||||
type testCommiteeFetcher struct {
|
||||
keys keys.PublicKeys
|
||||
err error
|
||||
calls atomic.Int32
|
||||
}
|
||||
|
||||
func (f *testCommiteeFetcher) Committee() (keys.PublicKeys, error) {
|
||||
f.calls.Inc()
|
||||
return f.keys, f.err
|
||||
}
|
||||
|
||||
type testIRFetcher struct {
|
||||
keys keys.PublicKeys
|
||||
err error
|
||||
calls atomic.Int32
|
||||
}
|
||||
|
||||
func (f *testIRFetcher) InnerRingKeys() (keys.PublicKeys, error) {
|
||||
f.calls.Inc()
|
||||
return f.keys, f.err
|
||||
}
|
|
@ -63,7 +63,7 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper,
|
|||
s.netmapProcessor, err = netmap.New(&netmap.Params{
|
||||
Log: s.log,
|
||||
PoolSize: cfg.GetInt("workers.netmap"),
|
||||
NetmapClient: s.netmapClient,
|
||||
NetmapClient: netmap.NewNetmapClient(s.netmapClient),
|
||||
EpochTimer: s,
|
||||
EpochState: s,
|
||||
AlphabetState: s,
|
||||
|
|
282
pkg/innerring/processors/alphabet/handlers_test.go
Normal file
282
pkg/innerring/processors/alphabet/handlers_test.go
Normal file
|
@ -0,0 +1,282 @@
|
|||
package alphabet_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestProcessorEmitsGasToNetmapAndAlphabet(t *testing.T) {
|
||||
t.Parallel()
|
||||
var emission uint64 = 100_000
|
||||
var index int = 5
|
||||
var parsedWallets []util.Uint160 = []util.Uint160{{20}, {25}}
|
||||
|
||||
alphabetContracts := innerring.NewAlphabetContracts()
|
||||
for i := 0; i <= index; i++ {
|
||||
alphabetContracts[innerring.GlagoliticLetter(i)] = util.Uint160{uint8(i)}
|
||||
}
|
||||
|
||||
morphClient := &testMorphClient{}
|
||||
|
||||
var node1 netmap.NodeInfo
|
||||
key1, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35")
|
||||
require.NoError(t, err, "failed to parse key1")
|
||||
node1.SetPublicKey(key1.Bytes())
|
||||
|
||||
var node2 netmap.NodeInfo
|
||||
key2, err := keys.NewPublicKeyFromString("02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3")
|
||||
require.NoError(t, err, "failed to parse key2")
|
||||
node2.SetPublicKey(key2.Bytes())
|
||||
|
||||
nodes := []netmap.NodeInfo{node1, node2}
|
||||
|
||||
network := &netmap.NetMap{}
|
||||
network.SetNodes(nodes)
|
||||
|
||||
netmapClient := &testNetmapClient{
|
||||
netmap: network,
|
||||
}
|
||||
|
||||
params := &alphabet.Params{
|
||||
ParsedWallets: parsedWallets,
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 2,
|
||||
StorageEmission: emission,
|
||||
IRList: &testIndexer{index: index},
|
||||
AlphabetContracts: alphabetContracts,
|
||||
MorphClient: morphClient,
|
||||
NetmapClient: netmapClient,
|
||||
}
|
||||
|
||||
processor, err := alphabet.New(params)
|
||||
require.NoError(t, err, "failed to create processor instance")
|
||||
|
||||
processor.HandleGasEmission(timers.NewAlphabetEmitTick{})
|
||||
|
||||
processor.WaitPoolRunning()
|
||||
|
||||
require.EqualValues(t, []invokedMethod{
|
||||
{
|
||||
contract: alphabetContracts[innerring.GlagoliticLetter(index)],
|
||||
fee: 0,
|
||||
method: "emit",
|
||||
},
|
||||
}, morphClient.invokedMethods, "invalid invoked morph methods")
|
||||
|
||||
require.EqualValues(t, []transferGas{
|
||||
{
|
||||
receiver: key1.GetScriptHash(),
|
||||
amount: fixedn.Fixed8(25_000),
|
||||
},
|
||||
{
|
||||
receiver: key2.GetScriptHash(),
|
||||
amount: fixedn.Fixed8(25_000),
|
||||
},
|
||||
}, morphClient.transferedGas, "invalid transfered Gas")
|
||||
|
||||
require.EqualValues(t, []batchTransferGas{
|
||||
{
|
||||
receivers: parsedWallets,
|
||||
amount: fixedn.Fixed8(25_000),
|
||||
},
|
||||
}, morphClient.batchTransferedGas, "invalid batch transfered Gas")
|
||||
}
|
||||
|
||||
func TestProcessorEmitsGasToNetmapIfNoParsedWallets(t *testing.T) {
|
||||
t.Parallel()
|
||||
var emission uint64 = 100_000
|
||||
var index int = 5
|
||||
var parsedWallets []util.Uint160 = []util.Uint160{}
|
||||
|
||||
alphabetContracts := innerring.NewAlphabetContracts()
|
||||
for i := 0; i <= index; i++ {
|
||||
alphabetContracts[innerring.GlagoliticLetter(i)] = util.Uint160{uint8(i)}
|
||||
}
|
||||
|
||||
morphClient := &testMorphClient{}
|
||||
|
||||
var node1 netmap.NodeInfo
|
||||
key1, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35")
|
||||
require.NoError(t, err, "failed to parse key1")
|
||||
node1.SetPublicKey(key1.Bytes())
|
||||
|
||||
var node2 netmap.NodeInfo
|
||||
key2, err := keys.NewPublicKeyFromString("02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3")
|
||||
require.NoError(t, err, "failed to parse key2")
|
||||
node2.SetPublicKey(key2.Bytes())
|
||||
|
||||
nodes := []netmap.NodeInfo{node1, node2}
|
||||
|
||||
network := &netmap.NetMap{}
|
||||
network.SetNodes(nodes)
|
||||
|
||||
netmapClient := &testNetmapClient{
|
||||
netmap: network,
|
||||
}
|
||||
|
||||
params := &alphabet.Params{
|
||||
ParsedWallets: parsedWallets,
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 2,
|
||||
StorageEmission: emission,
|
||||
IRList: &testIndexer{index: index},
|
||||
AlphabetContracts: alphabetContracts,
|
||||
MorphClient: morphClient,
|
||||
NetmapClient: netmapClient,
|
||||
}
|
||||
|
||||
processor, err := alphabet.New(params)
|
||||
require.NoError(t, err, "failed to create processor instance")
|
||||
|
||||
processor.HandleGasEmission(timers.NewAlphabetEmitTick{})
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
require.EqualValues(t, []invokedMethod{
|
||||
{
|
||||
contract: alphabetContracts[innerring.GlagoliticLetter(index)],
|
||||
fee: 0,
|
||||
method: "emit",
|
||||
},
|
||||
}, morphClient.invokedMethods, "invalid invoked morph methods")
|
||||
|
||||
require.EqualValues(t, []transferGas{
|
||||
{
|
||||
receiver: key1.GetScriptHash(),
|
||||
amount: fixedn.Fixed8(50_000),
|
||||
},
|
||||
{
|
||||
receiver: key2.GetScriptHash(),
|
||||
amount: fixedn.Fixed8(50_000),
|
||||
},
|
||||
}, morphClient.transferedGas, "invalid transfered Gas")
|
||||
|
||||
require.Equal(t, 0, len(morphClient.batchTransferedGas), "invalid batch transfered Gas")
|
||||
}
|
||||
|
||||
func TestProcessorDoesntEmitGasIfNoNetmapOrParsedWallets(t *testing.T) {
|
||||
t.Parallel()
|
||||
var emission uint64 = 100_000
|
||||
var index int = 5
|
||||
var parsedWallets []util.Uint160 = []util.Uint160{}
|
||||
|
||||
alphabetContracts := innerring.NewAlphabetContracts()
|
||||
for i := 0; i <= index; i++ {
|
||||
alphabetContracts[innerring.GlagoliticLetter(i)] = util.Uint160{uint8(i)}
|
||||
}
|
||||
|
||||
morphClient := &testMorphClient{}
|
||||
|
||||
nodes := []netmap.NodeInfo{}
|
||||
network := &netmap.NetMap{}
|
||||
network.SetNodes(nodes)
|
||||
|
||||
netmapClient := &testNetmapClient{
|
||||
netmap: network,
|
||||
}
|
||||
|
||||
params := &alphabet.Params{
|
||||
ParsedWallets: parsedWallets,
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 2,
|
||||
StorageEmission: emission,
|
||||
IRList: &testIndexer{index: index},
|
||||
AlphabetContracts: alphabetContracts,
|
||||
MorphClient: morphClient,
|
||||
NetmapClient: netmapClient,
|
||||
}
|
||||
|
||||
processor, err := alphabet.New(params)
|
||||
require.NoError(t, err, "failed to create processor instance")
|
||||
|
||||
processor.HandleGasEmission(timers.NewAlphabetEmitTick{})
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
require.EqualValues(t, []invokedMethod{
|
||||
{
|
||||
contract: alphabetContracts[innerring.GlagoliticLetter(index)],
|
||||
fee: 0,
|
||||
method: "emit",
|
||||
},
|
||||
}, morphClient.invokedMethods, "invalid invoked morph methods")
|
||||
|
||||
require.Equal(t, 0, len(morphClient.transferedGas), "invalid transfered Gas")
|
||||
|
||||
require.Equal(t, 0, len(morphClient.batchTransferedGas), "invalid batch transfered Gas")
|
||||
}
|
||||
|
||||
type testIndexer struct {
|
||||
index int
|
||||
}
|
||||
|
||||
func (i *testIndexer) AlphabetIndex() int {
|
||||
return i.index
|
||||
}
|
||||
|
||||
type invokedMethod struct {
|
||||
contract util.Uint160
|
||||
fee fixedn.Fixed8
|
||||
method string
|
||||
args []any
|
||||
}
|
||||
|
||||
type transferGas struct {
|
||||
receiver util.Uint160
|
||||
amount fixedn.Fixed8
|
||||
}
|
||||
|
||||
type batchTransferGas struct {
|
||||
receivers []util.Uint160
|
||||
amount fixedn.Fixed8
|
||||
}
|
||||
|
||||
type testMorphClient struct {
|
||||
invokedMethods []invokedMethod
|
||||
transferedGas []transferGas
|
||||
batchTransferedGas []batchTransferGas
|
||||
}
|
||||
|
||||
func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error {
|
||||
c.invokedMethods = append(c.invokedMethods,
|
||||
invokedMethod{
|
||||
contract: contract,
|
||||
fee: fee,
|
||||
method: method,
|
||||
args: args,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error {
|
||||
c.transferedGas = append(c.transferedGas, transferGas{
|
||||
receiver: receiver,
|
||||
amount: amount,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testMorphClient) BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8) error {
|
||||
c.batchTransferedGas = append(c.batchTransferedGas, batchTransferGas{
|
||||
receivers: receivers,
|
||||
amount: amount,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
type testNetmapClient struct {
|
||||
netmap *netmap.NetMap
|
||||
}
|
||||
|
||||
func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) {
|
||||
return c.netmap, nil
|
||||
}
|
|
@ -3,12 +3,13 @@ package alphabet
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/panjf2000/ants/v2"
|
||||
"go.uber.org/zap"
|
||||
|
@ -32,14 +33,24 @@ type (
|
|||
GetByIndex(int) (util.Uint160, bool)
|
||||
}
|
||||
|
||||
netmapClient interface {
|
||||
NetMap() (*netmap.NetMap, error)
|
||||
}
|
||||
|
||||
morphClient interface {
|
||||
Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error
|
||||
TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error
|
||||
BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8) error
|
||||
}
|
||||
|
||||
// Processor of events produced for alphabet contracts in the sidechain.
|
||||
Processor struct {
|
||||
parsedWallets []util.Uint160
|
||||
log *logger.Logger
|
||||
pool *ants.Pool
|
||||
alphabetContracts Contracts
|
||||
netmapClient *nmClient.Client
|
||||
morphClient *client.Client
|
||||
netmapClient netmapClient
|
||||
morphClient morphClient
|
||||
irList Indexer
|
||||
storageEmission uint64
|
||||
}
|
||||
|
@ -50,8 +61,8 @@ type (
|
|||
Log *logger.Logger
|
||||
PoolSize int
|
||||
AlphabetContracts Contracts
|
||||
NetmapClient *nmClient.Client
|
||||
MorphClient *client.Client
|
||||
NetmapClient netmapClient
|
||||
MorphClient morphClient
|
||||
IRList Indexer
|
||||
StorageEmission uint64
|
||||
}
|
||||
|
@ -106,3 +117,11 @@ func (ap *Processor) ListenerNotaryParsers() []event.NotaryParserInfo {
|
|||
func (ap *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitPoolRunning waits while pool has running tasks
|
||||
// For use in test only.
|
||||
func (ap *Processor) WaitPoolRunning() {
|
||||
for ap.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
|
90
pkg/innerring/processors/balance/handlers_test.go
Normal file
90
pkg/innerring/processors/balance/handlers_test.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
package balance
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
frostfscontract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs"
|
||||
balanceEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/balance"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestProcessorCallsFrostFSContractForLockEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
as := &testAlphabetState{
|
||||
isAlphabet: true,
|
||||
}
|
||||
conv := &testPresicionConverter{}
|
||||
cl := &testFrostFSContractClient{}
|
||||
bsc := util.Uint160{100}
|
||||
|
||||
processor, err := New(&Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 2,
|
||||
FrostFSClient: cl,
|
||||
BalanceSC: bsc,
|
||||
AlphabetState: as,
|
||||
Converter: conv,
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
processor.handleLock(balanceEvent.Lock{})
|
||||
|
||||
for processor.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
require.Equal(t, 1, cl.chequeCalls, "invalid Cheque calls")
|
||||
}
|
||||
|
||||
func TestProcessorDoesntCallFrostFSContractIfNotAlphabet(t *testing.T) {
|
||||
t.Parallel()
|
||||
as := &testAlphabetState{}
|
||||
conv := &testPresicionConverter{}
|
||||
cl := &testFrostFSContractClient{}
|
||||
bsc := util.Uint160{100}
|
||||
|
||||
processor, err := New(&Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 2,
|
||||
FrostFSClient: cl,
|
||||
BalanceSC: bsc,
|
||||
AlphabetState: as,
|
||||
Converter: conv,
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
processor.handleLock(balanceEvent.Lock{})
|
||||
|
||||
for processor.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
require.Equal(t, 0, cl.chequeCalls, "invalid Cheque calls")
|
||||
}
|
||||
|
||||
type testAlphabetState struct {
|
||||
isAlphabet bool
|
||||
}
|
||||
|
||||
func (s *testAlphabetState) IsAlphabet() bool {
|
||||
return s.isAlphabet
|
||||
}
|
||||
|
||||
type testPresicionConverter struct {
|
||||
}
|
||||
|
||||
func (c *testPresicionConverter) ToFixed8(v int64) int64 {
|
||||
return v
|
||||
}
|
||||
|
||||
type testFrostFSContractClient struct {
|
||||
chequeCalls int
|
||||
}
|
||||
|
||||
func (c *testFrostFSContractClient) Cheque(p frostfscontract.ChequePrm) error {
|
||||
c.chequeCalls++
|
||||
return nil
|
||||
}
|
|
@ -25,11 +25,15 @@ type (
|
|||
ToFixed8(int64) int64
|
||||
}
|
||||
|
||||
FrostFSClient interface {
|
||||
Cheque(p frostfscontract.ChequePrm) error
|
||||
}
|
||||
|
||||
// Processor of events produced by balance contract in the morphchain.
|
||||
Processor struct {
|
||||
log *logger.Logger
|
||||
pool *ants.Pool
|
||||
frostfsClient *frostfscontract.Client
|
||||
frostfsClient FrostFSClient
|
||||
balanceSC util.Uint160
|
||||
alphabetState AlphabetState
|
||||
converter PrecisionConverter
|
||||
|
@ -39,7 +43,7 @@ type (
|
|||
Params struct {
|
||||
Log *logger.Logger
|
||||
PoolSize int
|
||||
FrostFSClient *frostfscontract.Client
|
||||
FrostFSClient FrostFSClient
|
||||
BalanceSC util.Uint160
|
||||
AlphabetState AlphabetState
|
||||
Converter PrecisionConverter
|
||||
|
|
|
@ -36,7 +36,7 @@ func (cp *Processor) handleDelete(ev event.Event) {
|
|||
|
||||
// send an event to the worker pool
|
||||
|
||||
err := cp.pool.Submit(func() { cp.processContainerDelete(&del) })
|
||||
err := cp.pool.Submit(func() { cp.processContainerDelete(del) })
|
||||
if err != nil {
|
||||
// there system can be moved into controlled degradation stage
|
||||
cp.log.Warn(logs.ContainerContainerProcessorWorkerPoolDrained,
|
||||
|
|
337
pkg/innerring/processors/container/handlers_test.go
Normal file
337
pkg/innerring/processors/container/handlers_test.go
Normal file
|
@ -0,0 +1,337 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid"
|
||||
containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/network/payload"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPutEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
nst := &testNetworkState{
|
||||
homHashDisabled: true,
|
||||
epoch: 100,
|
||||
}
|
||||
cc := &testContainerClient{
|
||||
get: make(map[string]*containercore.Container),
|
||||
}
|
||||
|
||||
proc, err := New(&Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 2,
|
||||
AlphabetState: &testAlphabetState{isAlphabet: true},
|
||||
FrostFSIDClient: &testIDClient{},
|
||||
NotaryDisabled: true,
|
||||
NetworkState: nst,
|
||||
ContainerClient: cc,
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
p, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
var usr user.ID
|
||||
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
|
||||
|
||||
var pp netmap.PlacementPolicy
|
||||
pp.AddReplicas(netmap.ReplicaDescriptor{})
|
||||
|
||||
var cnr containerSDK.Container
|
||||
cnr.Init()
|
||||
cnr.SetOwner(usr)
|
||||
cnr.SetPlacementPolicy(pp)
|
||||
cnr.SetBasicACL(acl.Private)
|
||||
containerSDK.DisableHomomorphicHashing(&cnr)
|
||||
|
||||
event := &testPutEvent{
|
||||
cnr: &cnr,
|
||||
pk: p,
|
||||
st: nil,
|
||||
}
|
||||
|
||||
proc.handlePut(event)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var expectedPut cntClient.PutPrm
|
||||
expectedPut.SetContainer(cnr.Marshal())
|
||||
expectedPut.SetKey(p.PublicKey().Bytes())
|
||||
expectedPut.SetSignature(p.Sign(cnr.Marshal()))
|
||||
expectedPut.SetZone("container")
|
||||
|
||||
require.EqualValues(t, []cntClient.PutPrm{expectedPut}, cc.put, "invalid put requests")
|
||||
}
|
||||
|
||||
func TestDeleteEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
nst := &testNetworkState{
|
||||
homHashDisabled: true,
|
||||
epoch: 100,
|
||||
}
|
||||
cc := &testContainerClient{
|
||||
get: make(map[string]*containercore.Container),
|
||||
}
|
||||
|
||||
p, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
idc := &testIDClient{
|
||||
publicKeys: []*keys.PublicKey{
|
||||
p.PublicKey(),
|
||||
},
|
||||
}
|
||||
|
||||
proc, err := New(&Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 2,
|
||||
AlphabetState: &testAlphabetState{isAlphabet: true},
|
||||
FrostFSIDClient: idc,
|
||||
NotaryDisabled: true,
|
||||
NetworkState: nst,
|
||||
ContainerClient: cc,
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
var usr user.ID
|
||||
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
|
||||
|
||||
var pp netmap.PlacementPolicy
|
||||
pp.AddReplicas(netmap.ReplicaDescriptor{})
|
||||
|
||||
var cnr containerSDK.Container
|
||||
cnr.Init()
|
||||
cnr.SetOwner(usr)
|
||||
cnr.SetPlacementPolicy(pp)
|
||||
cnr.SetBasicACL(acl.Private)
|
||||
containerSDK.DisableHomomorphicHashing(&cnr)
|
||||
|
||||
var cid cid.ID
|
||||
containerSDK.CalculateID(&cid, cnr)
|
||||
cidBin := make([]byte, 32)
|
||||
cid.Encode(cidBin)
|
||||
|
||||
ev := containerEvent.Delete{
|
||||
ContainerIDValue: cidBin,
|
||||
SignatureValue: p.Sign(cidBin),
|
||||
}
|
||||
|
||||
var signature frostfscrypto.Signature
|
||||
signer := frostfsecdsa.Signer(p.PrivateKey)
|
||||
require.NoError(t, signature.Calculate(signer, ev.ContainerID()), "failed to calculate signature")
|
||||
cc.get[hex.EncodeToString(ev.ContainerID())] = &containercore.Container{
|
||||
Value: cnr,
|
||||
Signature: signature,
|
||||
}
|
||||
|
||||
proc.handleDelete(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var expectedDelete cntClient.DeletePrm
|
||||
expectedDelete.SetCID(ev.ContainerID())
|
||||
expectedDelete.SetSignature(ev.Signature())
|
||||
|
||||
require.EqualValues(t, []cntClient.DeletePrm{expectedDelete}, cc.delete, "invalid delete requests")
|
||||
}
|
||||
|
||||
func TestSetEACLEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
nst := &testNetworkState{
|
||||
homHashDisabled: true,
|
||||
epoch: 100,
|
||||
}
|
||||
cc := &testContainerClient{
|
||||
get: make(map[string]*containercore.Container),
|
||||
}
|
||||
|
||||
proc, err := New(&Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 2,
|
||||
AlphabetState: &testAlphabetState{isAlphabet: true},
|
||||
FrostFSIDClient: &testIDClient{},
|
||||
NotaryDisabled: true,
|
||||
NetworkState: nst,
|
||||
ContainerClient: cc,
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
p, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
var usr user.ID
|
||||
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
|
||||
|
||||
var pp netmap.PlacementPolicy
|
||||
pp.AddReplicas(netmap.ReplicaDescriptor{})
|
||||
|
||||
var cnr containerSDK.Container
|
||||
cnr.Init()
|
||||
cnr.SetOwner(usr)
|
||||
cnr.SetPlacementPolicy(pp)
|
||||
cnr.SetBasicACL(acl.PrivateExtended)
|
||||
containerSDK.DisableHomomorphicHashing(&cnr)
|
||||
|
||||
var cid cid.ID
|
||||
containerSDK.CalculateID(&cid, cnr)
|
||||
cidBytes := make([]byte, 32)
|
||||
cid.Encode(cidBytes)
|
||||
|
||||
var signature frostfscrypto.Signature
|
||||
signer := frostfsecdsa.Signer(p.PrivateKey)
|
||||
require.NoError(t, signature.Calculate(signer, cidBytes), "failed to calculate signature")
|
||||
|
||||
cc.get[hex.EncodeToString(cidBytes)] = &containercore.Container{
|
||||
Value: cnr,
|
||||
Signature: signature,
|
||||
}
|
||||
|
||||
table := eacl.NewTable()
|
||||
table.SetCID(cid)
|
||||
table.SetVersion(version.Current())
|
||||
|
||||
r := &eacl.Record{}
|
||||
r.AddObjectContainerIDFilter(eacl.MatchStringEqual, cid)
|
||||
|
||||
table.AddRecord(r)
|
||||
|
||||
event := containerEvent.SetEACL{
|
||||
TableValue: table.ToV2().StableMarshal(nil),
|
||||
PublicKeyValue: p.PublicKey().Bytes(),
|
||||
SignatureValue: p.Sign(table.ToV2().StableMarshal(nil)),
|
||||
}
|
||||
|
||||
proc.handleSetEACL(event)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var expectedPutEACL cntClient.PutEACLPrm
|
||||
expectedPutEACL.SetTable(table.ToV2().StableMarshal(nil))
|
||||
expectedPutEACL.SetKey(p.PublicKey().Bytes())
|
||||
expectedPutEACL.SetSignature(p.Sign(table.ToV2().StableMarshal(nil)))
|
||||
|
||||
require.EqualValues(t, []cntClient.PutEACLPrm{expectedPutEACL}, cc.putEACL, "invalid set EACL requests")
|
||||
}
|
||||
|
||||
type testAlphabetState struct {
|
||||
isAlphabet bool
|
||||
}
|
||||
|
||||
func (s *testAlphabetState) IsAlphabet() bool {
|
||||
return s.isAlphabet
|
||||
}
|
||||
|
||||
type testNetworkState struct {
|
||||
homHashDisabled bool
|
||||
epoch uint64
|
||||
}
|
||||
|
||||
func (s *testNetworkState) HomomorphicHashDisabled() (bool, error) {
|
||||
return s.homHashDisabled, nil
|
||||
}
|
||||
|
||||
func (s *testNetworkState) Epoch() (uint64, error) {
|
||||
return s.epoch, nil
|
||||
}
|
||||
|
||||
type testContainerClient struct {
|
||||
contractAddress util.Uint160
|
||||
put []cntClient.PutPrm
|
||||
get map[string]*containercore.Container
|
||||
delete []cntClient.DeletePrm
|
||||
putEACL []cntClient.PutEACLPrm
|
||||
}
|
||||
|
||||
func (c *testContainerClient) ContractAddress() util.Uint160 {
|
||||
return c.contractAddress
|
||||
}
|
||||
|
||||
func (c *testContainerClient) Morph() *client.Client {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testContainerClient) Put(p cntClient.PutPrm) error {
|
||||
c.put = append(c.put, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testContainerClient) Get(cid []byte) (*containercore.Container, error) {
|
||||
key := hex.EncodeToString(cid)
|
||||
if cont, found := c.get[key]; found {
|
||||
return cont, nil
|
||||
}
|
||||
return nil, apistatus.ContainerNotFound{}
|
||||
}
|
||||
|
||||
func (c *testContainerClient) Delete(p cntClient.DeletePrm) error {
|
||||
c.delete = append(c.delete, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testContainerClient) PutEACL(p cntClient.PutEACLPrm) error {
|
||||
c.putEACL = append(c.putEACL, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
type testIDClient struct {
|
||||
publicKeys keys.PublicKeys
|
||||
}
|
||||
|
||||
func (c *testIDClient) AccountKeys(p frostfsid.AccountKeysPrm) (keys.PublicKeys, error) {
|
||||
return c.publicKeys, nil
|
||||
}
|
||||
|
||||
var _ putEvent = &testPutEvent{}
|
||||
|
||||
type testPutEvent struct {
|
||||
cnr *containerSDK.Container
|
||||
pk *keys.PrivateKey
|
||||
st []byte
|
||||
}
|
||||
|
||||
func (e *testPutEvent) MorphEvent() {}
|
||||
|
||||
func (e *testPutEvent) Container() []byte {
|
||||
return e.cnr.Marshal()
|
||||
}
|
||||
|
||||
func (e *testPutEvent) PublicKey() []byte {
|
||||
return e.pk.PublicKey().Bytes()
|
||||
}
|
||||
|
||||
func (e *testPutEvent) Signature() []byte {
|
||||
return e.pk.Sign(e.cnr.Marshal())
|
||||
}
|
||||
|
||||
func (e *testPutEvent) SessionToken() []byte {
|
||||
return e.st
|
||||
}
|
||||
func (e *testPutEvent) NotaryRequest() *payload.P2PNotaryRequest {
|
||||
return nil
|
||||
}
|
|
@ -120,7 +120,7 @@ func (cp *Processor) approvePutContainer(ctx *putContainerContext) {
|
|||
|
||||
// Process delete container operation from the user by checking container sanity
|
||||
// and sending approve tx back to morph.
|
||||
func (cp *Processor) processContainerDelete(e *containerEvent.Delete) {
|
||||
func (cp *Processor) processContainerDelete(e containerEvent.Delete) {
|
||||
if !cp.alphabetState.IsAlphabet() {
|
||||
cp.log.Info(logs.ContainerNonAlphabetModeIgnoreContainerDelete)
|
||||
return
|
||||
|
@ -138,7 +138,7 @@ func (cp *Processor) processContainerDelete(e *containerEvent.Delete) {
|
|||
cp.approveDeleteContainer(e)
|
||||
}
|
||||
|
||||
func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
|
||||
func (cp *Processor) checkDeleteContainer(e containerEvent.Delete) error {
|
||||
binCnr := e.ContainerID()
|
||||
|
||||
var idCnr cid.ID
|
||||
|
@ -170,7 +170,7 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cp *Processor) approveDeleteContainer(e *containerEvent.Delete) {
|
||||
func (cp *Processor) approveDeleteContainer(e containerEvent.Delete) {
|
||||
var err error
|
||||
|
||||
prm := cntClient.DeletePrm{}
|
||||
|
|
|
@ -6,13 +6,13 @@ import (
|
|||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container"
|
||||
containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (cp *Processor) processSetEACL(e container.SetEACL) {
|
||||
func (cp *Processor) processSetEACL(e containerEvent.SetEACL) {
|
||||
if !cp.alphabetState.IsAlphabet() {
|
||||
cp.log.Info(logs.ContainerNonAlphabetModeIgnoreSetEACL)
|
||||
return
|
||||
|
@ -30,7 +30,7 @@ func (cp *Processor) processSetEACL(e container.SetEACL) {
|
|||
cp.approveSetEACL(e)
|
||||
}
|
||||
|
||||
func (cp *Processor) checkSetEACL(e container.SetEACL) error {
|
||||
func (cp *Processor) checkSetEACL(e containerEvent.SetEACL) error {
|
||||
binTable := e.Table()
|
||||
|
||||
// unmarshal table
|
||||
|
@ -74,7 +74,7 @@ func (cp *Processor) checkSetEACL(e container.SetEACL) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cp *Processor) approveSetEACL(e container.SetEACL) {
|
||||
func (cp *Processor) approveSetEACL(e containerEvent.SetEACL) {
|
||||
var err error
|
||||
|
||||
prm := cntClient.PutEACLPrm{}
|
||||
|
|
|
@ -5,12 +5,16 @@ import (
|
|||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
||||
containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/panjf2000/ants/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -21,13 +25,26 @@ type (
|
|||
IsAlphabet() bool
|
||||
}
|
||||
|
||||
ContClient interface {
|
||||
ContractAddress() util.Uint160
|
||||
Morph() *client.Client
|
||||
Put(p cntClient.PutPrm) error
|
||||
Get(cid []byte) (*containercore.Container, error)
|
||||
Delete(p cntClient.DeletePrm) error
|
||||
PutEACL(p cntClient.PutEACLPrm) error
|
||||
}
|
||||
|
||||
IDClient interface {
|
||||
AccountKeys(p frostfsid.AccountKeysPrm) (keys.PublicKeys, error)
|
||||
}
|
||||
|
||||
// Processor of events produced by container contract in the sidechain.
|
||||
Processor struct {
|
||||
log *logger.Logger
|
||||
pool *ants.Pool
|
||||
alphabetState AlphabetState
|
||||
cnrClient *container.Client // notary must be enabled
|
||||
idClient *frostfsid.Client
|
||||
cnrClient ContClient // notary must be enabled
|
||||
idClient IDClient
|
||||
netState NetworkState
|
||||
notaryDisabled bool
|
||||
}
|
||||
|
@ -37,8 +54,8 @@ type (
|
|||
Log *logger.Logger
|
||||
PoolSize int
|
||||
AlphabetState AlphabetState
|
||||
ContainerClient *container.Client
|
||||
FrostFSIDClient *frostfsid.Client
|
||||
ContainerClient ContClient
|
||||
FrostFSIDClient IDClient
|
||||
NetworkState NetworkState
|
||||
NotaryDisabled bool
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ func (np *Processor) handleDeposit(ev event.Event) {
|
|||
|
||||
// send event to the worker pool
|
||||
|
||||
err := np.pool.Submit(func() { np.processDeposit(&deposit) })
|
||||
err := np.pool.Submit(func() { np.processDeposit(deposit) })
|
||||
if err != nil {
|
||||
// there system can be moved into controlled degradation stage
|
||||
np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
|
||||
|
@ -34,7 +34,7 @@ func (np *Processor) handleWithdraw(ev event.Event) {
|
|||
|
||||
// send event to the worker pool
|
||||
|
||||
err := np.pool.Submit(func() { np.processWithdraw(&withdraw) })
|
||||
err := np.pool.Submit(func() { np.processWithdraw(withdraw) })
|
||||
if err != nil {
|
||||
// there system can be moved into controlled degradation stage
|
||||
np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
|
||||
|
@ -50,7 +50,7 @@ func (np *Processor) handleCheque(ev event.Event) {
|
|||
|
||||
// send event to the worker pool
|
||||
|
||||
err := np.pool.Submit(func() { np.processCheque(&cheque) })
|
||||
err := np.pool.Submit(func() { np.processCheque(cheque) })
|
||||
if err != nil {
|
||||
// there system can be moved into controlled degradation stage
|
||||
np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
|
||||
|
@ -67,7 +67,7 @@ func (np *Processor) handleConfig(ev event.Event) {
|
|||
|
||||
// send event to the worker pool
|
||||
|
||||
err := np.pool.Submit(func() { np.processConfig(&cfg) })
|
||||
err := np.pool.Submit(func() { np.processConfig(cfg) })
|
||||
if err != nil {
|
||||
// there system can be moved into controlled degradation stage
|
||||
np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
|
||||
|
@ -83,7 +83,7 @@ func (np *Processor) handleBind(ev event.Event) {
|
|||
|
||||
// send event to the worker pool
|
||||
|
||||
err := np.pool.Submit(func() { np.processBind(e) })
|
||||
err := np.pool.Submit(func() { np.processBind(e, true) })
|
||||
if err != nil {
|
||||
// there system can be moved into controlled degradation stage
|
||||
np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
|
||||
|
@ -99,7 +99,7 @@ func (np *Processor) handleUnbind(ev event.Event) {
|
|||
|
||||
// send event to the worker pool
|
||||
|
||||
err := np.pool.Submit(func() { np.processBind(e) })
|
||||
err := np.pool.Submit(func() { np.processBind(e, false) })
|
||||
if err != nil {
|
||||
// there system can be moved into controlled degradation stage
|
||||
np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained,
|
||||
|
|
371
pkg/innerring/processors/frostfs/handlers_test.go
Normal file
371
pkg/innerring/processors/frostfs/handlers_test.go
Normal file
|
@ -0,0 +1,371 @@
|
|||
package frostfs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid"
|
||||
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHandleDeposit(t *testing.T) {
|
||||
t.Parallel()
|
||||
es := &testEpochState{
|
||||
epochCounter: 100,
|
||||
}
|
||||
b := &testBalaceClient{}
|
||||
m := &testMorphClient{
|
||||
balance: 150,
|
||||
}
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.EpochState = es
|
||||
p.BalanceClient = b
|
||||
p.MorphClient = m
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
ev := frostfsEvent.Deposit{
|
||||
IDValue: []byte{1, 2, 3, 4, 5},
|
||||
FromValue: util.Uint160{100},
|
||||
ToValue: util.Uint160{200},
|
||||
AmountValue: 1000,
|
||||
}
|
||||
|
||||
proc.handleDeposit(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var expMint balance.MintPrm
|
||||
expMint.SetAmount(ev.AmountValue)
|
||||
expMint.SetID(ev.IDValue)
|
||||
expMint.SetTo(ev.ToValue)
|
||||
|
||||
require.EqualValues(t, []balance.MintPrm{expMint}, b.mint, "invalid mint value")
|
||||
require.EqualValues(t, []transferGas{
|
||||
{
|
||||
receiver: ev.ToValue,
|
||||
amount: fixedn.Fixed8(50),
|
||||
},
|
||||
}, m.transferGas, "invalid transfer gas")
|
||||
|
||||
es.epochCounter = 109
|
||||
|
||||
proc.handleDeposit(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
expMint.SetAmount(ev.AmountValue)
|
||||
expMint.SetID(ev.IDValue)
|
||||
expMint.SetTo(ev.ToValue)
|
||||
|
||||
require.EqualValues(t, []balance.MintPrm{expMint, expMint}, b.mint, "invalid mint value")
|
||||
require.EqualValues(t, []transferGas{
|
||||
{
|
||||
receiver: ev.ToValue,
|
||||
amount: fixedn.Fixed8(50),
|
||||
},
|
||||
}, m.transferGas, "invalid transfer gas")
|
||||
}
|
||||
|
||||
func TestHandleWithdraw(t *testing.T) {
|
||||
t.Parallel()
|
||||
es := &testEpochState{
|
||||
epochCounter: 100,
|
||||
}
|
||||
b := &testBalaceClient{}
|
||||
m := &testMorphClient{
|
||||
balance: 150,
|
||||
}
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.EpochState = es
|
||||
p.BalanceClient = b
|
||||
p.MorphClient = m
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
ev := frostfsEvent.Withdraw{
|
||||
IDValue: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
UserValue: util.Uint160{100},
|
||||
AmountValue: 1000,
|
||||
}
|
||||
|
||||
proc.handleWithdraw(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
lock, err := util.Uint160DecodeBytesBE(ev.ID()[:util.Uint160Size])
|
||||
require.NoError(t, err, "failed to decode ID")
|
||||
var expLock balance.LockPrm
|
||||
expLock.SetAmount(ev.AmountValue)
|
||||
expLock.SetID(ev.IDValue)
|
||||
expLock.SetDueEpoch(int64(es.epochCounter) + int64(lockAccountLifetime))
|
||||
expLock.SetLock(lock)
|
||||
expLock.SetUser(ev.UserValue)
|
||||
|
||||
require.EqualValues(t, []balance.LockPrm{expLock}, b.lock, "invalid lock value")
|
||||
}
|
||||
|
||||
func TestHandleCheque(t *testing.T) {
|
||||
t.Parallel()
|
||||
es := &testEpochState{
|
||||
epochCounter: 100,
|
||||
}
|
||||
b := &testBalaceClient{}
|
||||
m := &testMorphClient{
|
||||
balance: 150,
|
||||
}
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.BalanceClient = b
|
||||
p.MorphClient = m
|
||||
p.EpochState = es
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
ev := frostfsEvent.Cheque{
|
||||
IDValue: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
UserValue: util.Uint160{100},
|
||||
AmountValue: 1000,
|
||||
LockValue: util.Uint160{200},
|
||||
}
|
||||
|
||||
proc.handleCheque(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var expBurn balance.BurnPrm
|
||||
expBurn.SetAmount(ev.AmountValue)
|
||||
expBurn.SetID(ev.IDValue)
|
||||
expBurn.SetTo(util.Uint160{200})
|
||||
|
||||
require.EqualValues(t, []balance.BurnPrm{expBurn}, b.burn, "invalid burn value")
|
||||
}
|
||||
|
||||
func TestHandleConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
es := &testEpochState{
|
||||
epochCounter: 100,
|
||||
}
|
||||
nm := &testNetmapClient{}
|
||||
m := &testMorphClient{
|
||||
balance: 150,
|
||||
}
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.NetmapClient = nm
|
||||
p.MorphClient = m
|
||||
p.EpochState = es
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
ev := frostfsEvent.Config{
|
||||
IDValue: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
|
||||
KeyValue: []byte{1, 2, 3, 4, 5},
|
||||
ValueValue: []byte{6, 7, 8, 9, 0},
|
||||
TxHashValue: util.Uint256{100},
|
||||
}
|
||||
|
||||
proc.handleConfig(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var expConfig nmClient.SetConfigPrm
|
||||
expConfig.SetHash(ev.TxHashValue)
|
||||
expConfig.SetID(ev.IDValue)
|
||||
expConfig.SetKey(ev.KeyValue)
|
||||
expConfig.SetValue(ev.ValueValue)
|
||||
|
||||
require.EqualValues(t, []nmClient.SetConfigPrm{expConfig}, nm.config, "invalid config value")
|
||||
}
|
||||
|
||||
func TestHandleUnbind(t *testing.T) {
|
||||
t.Parallel()
|
||||
es := &testEpochState{
|
||||
epochCounter: 100,
|
||||
}
|
||||
m := &testMorphClient{
|
||||
balance: 150,
|
||||
}
|
||||
id := &testIDClient{}
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.EpochState = es
|
||||
p.MorphClient = m
|
||||
p.FrostFSIDClient = id
|
||||
})
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
p, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
evUnbind := frostfsEvent.Unbind{
|
||||
BindCommon: frostfsEvent.BindCommon{
|
||||
UserValue: util.Uint160{49}.BytesBE(),
|
||||
KeysValue: [][]byte{
|
||||
p.PublicKey().Bytes(),
|
||||
},
|
||||
TxHashValue: util.Uint256{100},
|
||||
},
|
||||
}
|
||||
|
||||
proc.handleUnbind(evUnbind)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var userID user.ID
|
||||
userID.SetScriptHash(util.Uint160{49})
|
||||
|
||||
var expBind frostfsid.CommonBindPrm
|
||||
expBind.SetOwnerID(userID.WalletBytes())
|
||||
expBind.SetKeys(evUnbind.BindCommon.KeysValue)
|
||||
expBind.SetHash(evUnbind.BindCommon.TxHashValue)
|
||||
|
||||
var expNilSlice []frostfsid.CommonBindPrm
|
||||
|
||||
require.EqualValues(t, []frostfsid.CommonBindPrm{expBind}, id.remove, "invalid remove keys value")
|
||||
require.EqualValues(t, expNilSlice, id.add, "invalid add keys value")
|
||||
|
||||
evBind := frostfsEvent.Bind{
|
||||
BindCommon: frostfsEvent.BindCommon{
|
||||
UserValue: util.Uint160{49}.BytesBE(),
|
||||
KeysValue: [][]byte{
|
||||
p.PublicKey().Bytes(),
|
||||
},
|
||||
TxHashValue: util.Uint256{100},
|
||||
},
|
||||
}
|
||||
|
||||
proc.handleBind(evBind)
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
require.EqualValues(t, []frostfsid.CommonBindPrm{expBind}, id.remove, "invalid remove keys value")
|
||||
require.EqualValues(t, []frostfsid.CommonBindPrm{expBind}, id.add, "invalid add keys value")
|
||||
}
|
||||
|
||||
func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) {
|
||||
p := &Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 1,
|
||||
FrostFSContract: util.Uint160{0},
|
||||
FrostFSIDClient: &testIDClient{},
|
||||
BalanceClient: &testBalaceClient{},
|
||||
NetmapClient: &testNetmapClient{},
|
||||
MorphClient: &testMorphClient{},
|
||||
EpochState: &testEpochState{},
|
||||
AlphabetState: &testAlphabetState{isAlphabet: true},
|
||||
Converter: &testPrecisionConverter{},
|
||||
MintEmitCacheSize: 100,
|
||||
MintEmitThreshold: 10,
|
||||
MintEmitValue: fixedn.Fixed8(50),
|
||||
GasBalanceThreshold: 50,
|
||||
}
|
||||
|
||||
nonDefault(p)
|
||||
|
||||
return New(p)
|
||||
}
|
||||
|
||||
type testEpochState struct {
|
||||
epochCounter uint64
|
||||
}
|
||||
|
||||
func (s *testEpochState) EpochCounter() uint64 {
|
||||
return s.epochCounter
|
||||
}
|
||||
|
||||
type testAlphabetState struct {
|
||||
isAlphabet bool
|
||||
}
|
||||
|
||||
func (s *testAlphabetState) IsAlphabet() bool {
|
||||
return s.isAlphabet
|
||||
}
|
||||
|
||||
type testPrecisionConverter struct {
|
||||
}
|
||||
|
||||
func (c *testPrecisionConverter) ToBalancePrecision(v int64) int64 {
|
||||
return v
|
||||
}
|
||||
|
||||
type testBalaceClient struct {
|
||||
mint []balance.MintPrm
|
||||
lock []balance.LockPrm
|
||||
burn []balance.BurnPrm
|
||||
}
|
||||
|
||||
func (c *testBalaceClient) Mint(p balance.MintPrm) error {
|
||||
c.mint = append(c.mint, p)
|
||||
return nil
|
||||
}
|
||||
func (c *testBalaceClient) Lock(p balance.LockPrm) error {
|
||||
c.lock = append(c.lock, p)
|
||||
return nil
|
||||
}
|
||||
func (c *testBalaceClient) Burn(p balance.BurnPrm) error {
|
||||
c.burn = append(c.burn, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
type testNetmapClient struct {
|
||||
config []nmClient.SetConfigPrm
|
||||
}
|
||||
|
||||
func (c *testNetmapClient) SetConfig(p nmClient.SetConfigPrm) error {
|
||||
c.config = append(c.config, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
type transferGas struct {
|
||||
receiver util.Uint160
|
||||
amount fixedn.Fixed8
|
||||
}
|
||||
|
||||
type testMorphClient struct {
|
||||
balance int64
|
||||
transferGas []transferGas
|
||||
}
|
||||
|
||||
func (c *testMorphClient) GasBalance() (res int64, err error) {
|
||||
return c.balance, nil
|
||||
}
|
||||
func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error {
|
||||
c.transferGas = append(c.transferGas, transferGas{
|
||||
receiver: receiver,
|
||||
amount: amount,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
type testIDClient struct {
|
||||
add []frostfsid.CommonBindPrm
|
||||
remove []frostfsid.CommonBindPrm
|
||||
}
|
||||
|
||||
func (c *testIDClient) AddKeys(p frostfsid.CommonBindPrm) error {
|
||||
c.add = append(c.add, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testIDClient) RemoveKeys(args frostfsid.CommonBindPrm) error {
|
||||
c.remove = append(c.remove, args)
|
||||
return nil
|
||||
}
|
|
@ -15,7 +15,7 @@ const (
|
|||
|
||||
// Process deposit event by invoking a balance contract and sending native
|
||||
// gas in the sidechain.
|
||||
func (np *Processor) processDeposit(deposit *frostfsEvent.Deposit) {
|
||||
func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) {
|
||||
if !np.alphabetState.IsAlphabet() {
|
||||
np.log.Info(logs.FrostFSNonAlphabetModeIgnoreDeposit)
|
||||
return
|
||||
|
@ -80,7 +80,7 @@ func (np *Processor) processDeposit(deposit *frostfsEvent.Deposit) {
|
|||
}
|
||||
|
||||
// Process withdraw event by locking assets in the balance account.
|
||||
func (np *Processor) processWithdraw(withdraw *frostfsEvent.Withdraw) {
|
||||
func (np *Processor) processWithdraw(withdraw frostfsEvent.Withdraw) {
|
||||
if !np.alphabetState.IsAlphabet() {
|
||||
np.log.Info(logs.FrostFSNonAlphabetModeIgnoreWithdraw)
|
||||
return
|
||||
|
@ -111,7 +111,7 @@ func (np *Processor) processWithdraw(withdraw *frostfsEvent.Withdraw) {
|
|||
|
||||
// Process cheque event by transferring assets from the lock account back to
|
||||
// the reserve account.
|
||||
func (np *Processor) processCheque(cheque *frostfsEvent.Cheque) {
|
||||
func (np *Processor) processCheque(cheque frostfsEvent.Cheque) {
|
||||
if !np.alphabetState.IsAlphabet() {
|
||||
np.log.Info(logs.FrostFSNonAlphabetModeIgnoreCheque)
|
||||
return
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -19,7 +18,7 @@ type bindCommon interface {
|
|||
TxHash() util.Uint256
|
||||
}
|
||||
|
||||
func (np *Processor) processBind(e bindCommon) {
|
||||
func (np *Processor) processBind(e bindCommon, bind bool) {
|
||||
if !np.alphabetState.IsAlphabet() {
|
||||
np.log.Info(logs.FrostFSNonAlphabetModeIgnoreBind)
|
||||
return
|
||||
|
@ -27,10 +26,9 @@ func (np *Processor) processBind(e bindCommon) {
|
|||
|
||||
c := &bindCommonContext{
|
||||
bindCommon: e,
|
||||
bind: bind,
|
||||
}
|
||||
|
||||
_, c.bind = e.(frostfs.Bind)
|
||||
|
||||
err := np.checkBindCommon(c)
|
||||
if err != nil {
|
||||
np.log.Error(logs.FrostFSInvalidManageKeyEvent,
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
// Process config event by setting configuration value from the mainchain in
|
||||
// the sidechain.
|
||||
func (np *Processor) processConfig(config *frostfsEvent.Config) {
|
||||
func (np *Processor) processConfig(config frostfsEvent.Config) {
|
||||
if !np.alphabetState.IsAlphabet() {
|
||||
np.log.Info(logs.FrostFSNonAlphabetModeIgnoreConfig)
|
||||
return
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"sync"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid"
|
||||
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
|
@ -36,14 +35,34 @@ type (
|
|||
ToBalancePrecision(int64) int64
|
||||
}
|
||||
|
||||
BalanceClient interface {
|
||||
Mint(p balance.MintPrm) error
|
||||
Lock(p balance.LockPrm) error
|
||||
Burn(p balance.BurnPrm) error
|
||||
}
|
||||
|
||||
NetmapClient interface {
|
||||
SetConfig(p nmClient.SetConfigPrm) error
|
||||
}
|
||||
|
||||
MorphClient interface {
|
||||
GasBalance() (res int64, err error)
|
||||
TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error
|
||||
}
|
||||
|
||||
IDClient interface {
|
||||
AddKeys(p frostfsid.CommonBindPrm) error
|
||||
RemoveKeys(args frostfsid.CommonBindPrm) error
|
||||
}
|
||||
|
||||
// Processor of events produced by frostfs contract in main net.
|
||||
Processor struct {
|
||||
log *logger.Logger
|
||||
pool *ants.Pool
|
||||
frostfsContract util.Uint160
|
||||
balanceClient *balance.Client
|
||||
netmapClient *nmClient.Client
|
||||
morphClient *client.Client
|
||||
balanceClient BalanceClient
|
||||
netmapClient NetmapClient
|
||||
morphClient MorphClient
|
||||
epochState EpochState
|
||||
alphabetState AlphabetState
|
||||
converter PrecisionConverter
|
||||
|
@ -52,8 +71,7 @@ type (
|
|||
mintEmitThreshold uint64
|
||||
mintEmitValue fixedn.Fixed8
|
||||
gasBalanceThreshold int64
|
||||
|
||||
frostfsIDClient *frostfsid.Client
|
||||
frostfsIDClient IDClient
|
||||
}
|
||||
|
||||
// Params of the processor constructor.
|
||||
|
@ -61,10 +79,10 @@ type (
|
|||
Log *logger.Logger
|
||||
PoolSize int
|
||||
FrostFSContract util.Uint160
|
||||
FrostFSIDClient *frostfsid.Client
|
||||
BalanceClient *balance.Client
|
||||
NetmapClient *nmClient.Client
|
||||
MorphClient *client.Client
|
||||
FrostFSIDClient IDClient
|
||||
BalanceClient BalanceClient
|
||||
NetmapClient NetmapClient
|
||||
MorphClient MorphClient
|
||||
EpochState EpochState
|
||||
AlphabetState AlphabetState
|
||||
Converter PrecisionConverter
|
||||
|
|
304
pkg/innerring/processors/governance/handlers_test.go
Normal file
304
pkg/innerring/processors/governance/handlers_test.go
Normal file
|
@ -0,0 +1,304 @@
|
|||
package governance
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||
frostfscontract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs"
|
||||
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/rolemanagement"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHandleAlphabetSyncEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
testKeys := generateTestKeys(t)
|
||||
|
||||
es := &testEpochState{
|
||||
epoch: 100,
|
||||
}
|
||||
as := &testAlphabetState{
|
||||
isAlphabet: true,
|
||||
}
|
||||
v := &testVoter{}
|
||||
irf := &testIRFetcher{
|
||||
publicKeys: testKeys.sidechainKeys,
|
||||
}
|
||||
m := &testMorphClient{
|
||||
commiteeKeys: testKeys.sidechainKeys,
|
||||
}
|
||||
mn := &testMainnetClient{
|
||||
alphabetKeys: testKeys.mainnetKeys,
|
||||
}
|
||||
f := &testFrostFSClient{}
|
||||
nm := &testNetmapClient{}
|
||||
|
||||
proc, err := New(
|
||||
&Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
EpochState: es,
|
||||
AlphabetState: as,
|
||||
Voter: v,
|
||||
IRFetcher: irf,
|
||||
NotaryDisabled: true,
|
||||
MorphClient: m,
|
||||
MainnetClient: mn,
|
||||
FrostFSClient: f,
|
||||
NetmapClient: nm,
|
||||
},
|
||||
)
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
ev := Sync{
|
||||
txHash: util.Uint256{100},
|
||||
}
|
||||
|
||||
proc.HandleAlphabetSync(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
require.EqualValues(t, []VoteValidatorPrm{
|
||||
{
|
||||
Validators: testKeys.newAlphabetExp,
|
||||
Hash: &ev.txHash,
|
||||
},
|
||||
}, v.votes, "invalid vote calls")
|
||||
|
||||
var irUpdateExp nmClient.UpdateIRPrm
|
||||
irUpdateExp.SetKeys(testKeys.newInnerRingExp)
|
||||
irUpdateExp.SetHash(ev.txHash)
|
||||
|
||||
require.EqualValues(t, []nmClient.UpdateIRPrm{irUpdateExp}, nm.updates, "invalid IR updates")
|
||||
|
||||
var expAlphabetUpdates []client.UpdateAlphabetListPrm
|
||||
require.EqualValues(t, expAlphabetUpdates, m.alphabetUpdates, "invalid alphabet updates")
|
||||
|
||||
var expNotaryUpdates []client.UpdateNotaryListPrm
|
||||
require.EqualValues(t, expNotaryUpdates, m.notaryUpdates, "invalid notary list updates")
|
||||
|
||||
buf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(buf, es.epoch)
|
||||
|
||||
id := append([]byte(alphabetUpdateIDPrefix), buf...)
|
||||
var expFrostFSAlphabetUpd frostfscontract.AlphabetUpdatePrm
|
||||
expFrostFSAlphabetUpd.SetID(id)
|
||||
expFrostFSAlphabetUpd.SetPubs(testKeys.newAlphabetExp)
|
||||
|
||||
require.EqualValues(t, []frostfscontract.AlphabetUpdatePrm{expFrostFSAlphabetUpd}, f.updates, "invalid FrostFS alphabet updates")
|
||||
}
|
||||
|
||||
func TestHandleAlphabetDesignateEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
testKeys := generateTestKeys(t)
|
||||
|
||||
es := &testEpochState{
|
||||
epoch: 100,
|
||||
}
|
||||
as := &testAlphabetState{
|
||||
isAlphabet: true,
|
||||
}
|
||||
v := &testVoter{}
|
||||
irf := &testIRFetcher{
|
||||
publicKeys: testKeys.sidechainKeys,
|
||||
}
|
||||
m := &testMorphClient{
|
||||
commiteeKeys: testKeys.sidechainKeys,
|
||||
}
|
||||
mn := &testMainnetClient{
|
||||
alphabetKeys: testKeys.mainnetKeys,
|
||||
}
|
||||
f := &testFrostFSClient{}
|
||||
nm := &testNetmapClient{}
|
||||
|
||||
proc, err := New(
|
||||
&Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
EpochState: es,
|
||||
AlphabetState: as,
|
||||
Voter: v,
|
||||
IRFetcher: irf,
|
||||
NotaryDisabled: false,
|
||||
MorphClient: m,
|
||||
MainnetClient: mn,
|
||||
FrostFSClient: f,
|
||||
NetmapClient: nm,
|
||||
},
|
||||
)
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
ev := rolemanagement.Designate{
|
||||
TxHash: util.Uint256{100},
|
||||
Role: noderoles.NeoFSAlphabet,
|
||||
}
|
||||
|
||||
proc.HandleAlphabetSync(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
require.EqualValues(t, []VoteValidatorPrm{
|
||||
{
|
||||
Validators: testKeys.newAlphabetExp,
|
||||
Hash: &ev.TxHash,
|
||||
},
|
||||
}, v.votes, "invalid vote calls")
|
||||
|
||||
var irUpdatesExp []nmClient.UpdateIRPrm
|
||||
require.EqualValues(t, irUpdatesExp, nm.updates, "invalid IR updates")
|
||||
|
||||
var alpabetUpdExp client.UpdateAlphabetListPrm
|
||||
alpabetUpdExp.SetList(testKeys.newInnerRingExp)
|
||||
alpabetUpdExp.SetHash(ev.TxHash)
|
||||
require.EqualValues(t, []client.UpdateAlphabetListPrm{alpabetUpdExp}, m.alphabetUpdates, "invalid alphabet updates")
|
||||
|
||||
var expNotaryUpdate client.UpdateNotaryListPrm
|
||||
expNotaryUpdate.SetList(testKeys.newAlphabetExp)
|
||||
expNotaryUpdate.SetHash(ev.TxHash)
|
||||
require.EqualValues(t, []client.UpdateNotaryListPrm{expNotaryUpdate}, m.notaryUpdates, "invalid notary list updates")
|
||||
|
||||
buf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(buf, es.epoch)
|
||||
|
||||
id := append([]byte(alphabetUpdateIDPrefix), buf...)
|
||||
var expFrostFSAlphabetUpd frostfscontract.AlphabetUpdatePrm
|
||||
expFrostFSAlphabetUpd.SetID(id)
|
||||
expFrostFSAlphabetUpd.SetPubs(testKeys.newAlphabetExp)
|
||||
|
||||
require.EqualValues(t, []frostfscontract.AlphabetUpdatePrm{expFrostFSAlphabetUpd}, f.updates, "invalid FrostFS alphabet updates")
|
||||
}
|
||||
|
||||
type testKeys struct {
|
||||
sidechainKeys keys.PublicKeys
|
||||
mainnetKeys keys.PublicKeys
|
||||
newAlphabetExp keys.PublicKeys
|
||||
newInnerRingExp keys.PublicKeys
|
||||
}
|
||||
|
||||
func generateTestKeys(t *testing.T) testKeys {
|
||||
for {
|
||||
var result testKeys
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
pk, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err, "failed to create private key")
|
||||
result.sidechainKeys = append(result.sidechainKeys, pk.PublicKey())
|
||||
}
|
||||
|
||||
result.mainnetKeys = append(result.mainnetKeys, result.sidechainKeys...)
|
||||
pk, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err, "failed to create private key")
|
||||
result.mainnetKeys = append(result.mainnetKeys, pk.PublicKey())
|
||||
|
||||
result.newAlphabetExp, err = newAlphabetList(result.sidechainKeys, result.mainnetKeys)
|
||||
require.NoError(t, err, "failed to create expected new alphabet")
|
||||
|
||||
if len(result.newAlphabetExp) == 0 {
|
||||
continue //can be happen because of random and sort
|
||||
}
|
||||
|
||||
var irKeys keys.PublicKeys
|
||||
irKeys = append(irKeys, result.sidechainKeys...)
|
||||
result.newInnerRingExp, err = updateInnerRing(irKeys, result.sidechainKeys, result.newAlphabetExp)
|
||||
require.NoError(t, err, "failed to create expected new IR")
|
||||
sort.Sort(result.newInnerRingExp)
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
type testEpochState struct {
|
||||
epoch uint64
|
||||
}
|
||||
|
||||
func (s *testEpochState) EpochCounter() uint64 {
|
||||
return s.epoch
|
||||
}
|
||||
|
||||
type testAlphabetState struct {
|
||||
isAlphabet bool
|
||||
}
|
||||
|
||||
func (s *testAlphabetState) IsAlphabet() bool {
|
||||
return s.isAlphabet
|
||||
}
|
||||
|
||||
type testVoter struct {
|
||||
votes []VoteValidatorPrm
|
||||
}
|
||||
|
||||
func (v *testVoter) VoteForSidechainValidator(prm VoteValidatorPrm) error {
|
||||
v.votes = append(v.votes, prm)
|
||||
return nil
|
||||
}
|
||||
|
||||
type testIRFetcher struct {
|
||||
publicKeys keys.PublicKeys
|
||||
}
|
||||
|
||||
func (f *testIRFetcher) InnerRingKeys() (keys.PublicKeys, error) {
|
||||
return f.publicKeys, nil
|
||||
}
|
||||
|
||||
type testMorphClient struct {
|
||||
commiteeKeys keys.PublicKeys
|
||||
|
||||
alphabetUpdates []client.UpdateAlphabetListPrm
|
||||
notaryUpdates []client.UpdateNotaryListPrm
|
||||
}
|
||||
|
||||
func (c *testMorphClient) Committee() (res keys.PublicKeys, err error) {
|
||||
return c.commiteeKeys, nil
|
||||
}
|
||||
|
||||
func (c *testMorphClient) UpdateNeoFSAlphabetList(prm client.UpdateAlphabetListPrm) error {
|
||||
c.alphabetUpdates = append(c.alphabetUpdates, prm)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testMorphClient) UpdateNotaryList(prm client.UpdateNotaryListPrm) error {
|
||||
c.notaryUpdates = append(c.notaryUpdates, prm)
|
||||
return nil
|
||||
}
|
||||
|
||||
type testMainnetClient struct {
|
||||
alphabetKeys keys.PublicKeys
|
||||
designateHash util.Uint160
|
||||
}
|
||||
|
||||
func (c *testMainnetClient) NeoFSAlphabetList() (res keys.PublicKeys, err error) {
|
||||
return c.alphabetKeys, nil
|
||||
}
|
||||
|
||||
func (c *testMainnetClient) GetDesignateHash() util.Uint160 {
|
||||
return c.designateHash
|
||||
}
|
||||
|
||||
type testFrostFSClient struct {
|
||||
updates []frostfscontract.AlphabetUpdatePrm
|
||||
}
|
||||
|
||||
func (c *testFrostFSClient) AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) error {
|
||||
c.updates = append(c.updates, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
type testNetmapClient struct {
|
||||
updates []nmClient.UpdateIRPrm
|
||||
}
|
||||
|
||||
func (c *testNetmapClient) UpdateInnerRing(p nmClient.UpdateIRPrm) error {
|
||||
c.updates = append(c.updates, p)
|
||||
return nil
|
||||
}
|
|
@ -53,20 +53,39 @@ type (
|
|||
InnerRingKeys() (keys.PublicKeys, error)
|
||||
}
|
||||
|
||||
FrostFSClient interface {
|
||||
AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) error
|
||||
}
|
||||
|
||||
NetmapClient interface {
|
||||
UpdateInnerRing(p nmClient.UpdateIRPrm) error
|
||||
}
|
||||
|
||||
MainnetClient interface {
|
||||
NeoFSAlphabetList() (res keys.PublicKeys, err error)
|
||||
GetDesignateHash() util.Uint160
|
||||
}
|
||||
|
||||
MorphClient interface {
|
||||
Committee() (res keys.PublicKeys, err error)
|
||||
UpdateNeoFSAlphabetList(prm client.UpdateAlphabetListPrm) error
|
||||
UpdateNotaryList(prm client.UpdateNotaryListPrm) error
|
||||
}
|
||||
|
||||
// Processor of events related to governance in the network.
|
||||
Processor struct {
|
||||
log *logger.Logger
|
||||
pool *ants.Pool
|
||||
frostfsClient *frostfscontract.Client
|
||||
netmapClient *nmClient.Client
|
||||
frostfsClient FrostFSClient
|
||||
netmapClient NetmapClient
|
||||
|
||||
alphabetState AlphabetState
|
||||
epochState EpochState
|
||||
voter Voter
|
||||
irFetcher IRFetcher
|
||||
|
||||
mainnetClient *client.Client
|
||||
morphClient *client.Client
|
||||
mainnetClient MainnetClient
|
||||
morphClient MorphClient
|
||||
|
||||
notaryDisabled bool
|
||||
|
||||
|
@ -82,10 +101,10 @@ type (
|
|||
Voter Voter
|
||||
IRFetcher IRFetcher
|
||||
|
||||
MorphClient *client.Client
|
||||
MainnetClient *client.Client
|
||||
FrostFSClient *frostfscontract.Client
|
||||
NetmapClient *nmClient.Client
|
||||
MorphClient MorphClient
|
||||
MainnetClient MainnetClient
|
||||
FrostFSClient FrostFSClient
|
||||
NetmapClient NetmapClient
|
||||
|
||||
NotaryDisabled bool
|
||||
}
|
||||
|
|
570
pkg/innerring/processors/netmap/handlers_test.go
Normal file
570
pkg/innerring/processors/netmap/handlers_test.go
Normal file
|
@ -0,0 +1,570 @@
|
|||
package netmap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/audit"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/settlement"
|
||||
timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
|
||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
||||
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/network/payload"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewEpochTick(t *testing.T) {
|
||||
t.Parallel()
|
||||
es := &testEpochState{
|
||||
counter: 100,
|
||||
}
|
||||
nc := &testNetmapClient{}
|
||||
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.NotaryDisabled = true
|
||||
p.CleanupEnabled = true
|
||||
p.EpochState = es
|
||||
p.NetmapClient = nc
|
||||
})
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
ev := timerEvent.NewEpochTick{}
|
||||
proc.HandleNewEpochTick(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
require.EqualValues(t, []uint64{101}, nc.newEpochs, "invalid epochs")
|
||||
}
|
||||
|
||||
func TestNewEpoch(t *testing.T) {
|
||||
t.Parallel()
|
||||
var node1 netmap.NodeInfo
|
||||
key1, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35")
|
||||
require.NoError(t, err, "failed to parse key1")
|
||||
node1.SetPublicKey(key1.Bytes())
|
||||
|
||||
var node2 netmap.NodeInfo
|
||||
key2, err := keys.NewPublicKeyFromString("02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3")
|
||||
require.NoError(t, err, "failed to parse key2")
|
||||
node2.SetPublicKey(key2.Bytes())
|
||||
|
||||
network := &netmap.NetMap{}
|
||||
network.SetNodes([]netmap.NodeInfo{node1, node2})
|
||||
|
||||
es := &testEpochState{
|
||||
counter: 100,
|
||||
duration: 10,
|
||||
}
|
||||
r := &testEpochResetter{}
|
||||
cc := &testContainerClient{}
|
||||
nc := &testNetmapClient{
|
||||
epochDuration: 20,
|
||||
txHeights: map[util.Uint256]uint32{
|
||||
{101}: 10_000,
|
||||
},
|
||||
netmap: network,
|
||||
}
|
||||
eh := &testEventHandler{}
|
||||
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.NotaryDisabled = true
|
||||
p.NotaryDepositHandler = eh.Handle
|
||||
p.HandleAudit = eh.Handle
|
||||
p.AuditSettlementsHandler = eh.Handle
|
||||
p.AlphabetSyncHandler = eh.Handle
|
||||
p.NetmapClient = nc
|
||||
p.ContainerWrapper = cc
|
||||
p.EpochTimer = r
|
||||
p.EpochState = es
|
||||
})
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
ev := netmapEvent.NewEpoch{
|
||||
Num: 101,
|
||||
Hash: util.Uint256{101},
|
||||
}
|
||||
proc.handleNewEpoch(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
require.Equal(t, nc.epochDuration, es.duration, "invalid epoch duration")
|
||||
require.Equal(t, ev.Num, es.counter, "invalid epoch counter")
|
||||
require.EqualValues(t, []uint32{nc.txHeights[ev.Hash]}, r.timers, "invalid epoch timer resets")
|
||||
|
||||
var expEstimation cntClient.StartEstimationPrm
|
||||
expEstimation.SetEpoch(ev.Num - 1)
|
||||
expEstimation.SetHash(ev.Hash)
|
||||
require.EqualValues(t, []cntClient.StartEstimationPrm{expEstimation}, cc.estimations, "invalid estimations")
|
||||
|
||||
require.EqualValues(t, []event.Event{
|
||||
audit.NewAuditStartEvent(ev.Num),
|
||||
settlement.NewAuditEvent(ev.Num),
|
||||
governance.NewSyncEvent(ev.TxHash()),
|
||||
ev,
|
||||
}, eh.handledEvents, "invalid handled events")
|
||||
}
|
||||
|
||||
func TestAddPeer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("with notary", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
nc := &testNetmapClient{
|
||||
contractAddress: util.Uint160{47},
|
||||
}
|
||||
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.NotaryDisabled = true
|
||||
p.NetmapClient = nc
|
||||
})
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
var node netmap.NodeInfo
|
||||
key, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35")
|
||||
require.NoError(t, err, "failed to parse key1")
|
||||
node.SetPublicKey(key.Bytes())
|
||||
|
||||
ev := netmapEvent.AddPeer{
|
||||
NodeBytes: node.Marshal(),
|
||||
Request: &payload.P2PNotaryRequest{
|
||||
MainTransaction: &transaction.Transaction{
|
||||
Nonce: 100,
|
||||
},
|
||||
},
|
||||
}
|
||||
proc.handleAddPeer(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
require.EqualValues(t, []notaryInvoke{
|
||||
{
|
||||
contract: nc.contractAddress,
|
||||
fee: 0,
|
||||
nonce: ev.Request.MainTransaction.Nonce,
|
||||
vub: nil,
|
||||
method: "addPeerIR",
|
||||
args: []any{ev.Node()},
|
||||
},
|
||||
}, nc.notaryInvokes, "invalid notary invokes")
|
||||
})
|
||||
|
||||
t.Run("without notary", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nc := &testNetmapClient{
|
||||
contractAddress: util.Uint160{47},
|
||||
}
|
||||
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.NotaryDisabled = true
|
||||
p.NetmapClient = nc
|
||||
})
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
var node netmap.NodeInfo
|
||||
key, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35")
|
||||
require.NoError(t, err, "failed to parse key")
|
||||
node.SetPublicKey(key.Bytes())
|
||||
|
||||
ev := netmapEvent.AddPeer{
|
||||
NodeBytes: node.Marshal(),
|
||||
}
|
||||
proc.handleAddPeer(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var addPeerExp netmapclient.AddPeerPrm
|
||||
addPeerExp.SetNodeInfo(node)
|
||||
require.EqualValues(t, []netmapclient.AddPeerPrm{addPeerExp}, nc.addPeers, "invalid peers")
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateState(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("with notary", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ns := &testNodeStateSettings{
|
||||
maintAllowed: true,
|
||||
}
|
||||
nc := &testNetmapClient{}
|
||||
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.NotaryDisabled = true
|
||||
p.NodeStateSettings = ns
|
||||
p.NetmapClient = nc
|
||||
})
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
key, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35")
|
||||
require.NoError(t, err, "failed to parse key")
|
||||
|
||||
ev := netmapEvent.UpdatePeer{
|
||||
State: netmapContract.NodeStateOnline,
|
||||
PubKey: key,
|
||||
Request: &payload.P2PNotaryRequest{
|
||||
MainTransaction: &transaction.Transaction{
|
||||
Nonce: 100,
|
||||
},
|
||||
},
|
||||
}
|
||||
proc.handleUpdateState(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
require.EqualValues(t, []*transaction.Transaction{
|
||||
ev.Request.MainTransaction,
|
||||
}, nc.invokedTxs, "invalid invoked transactions")
|
||||
})
|
||||
|
||||
t.Run("without notary", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ns := &testNodeStateSettings{
|
||||
maintAllowed: true,
|
||||
}
|
||||
nc := &testNetmapClient{}
|
||||
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.NetmapClient = nc
|
||||
p.NodeStateSettings = ns
|
||||
})
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
key, err := keys.NewPublicKeyFromString("038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35")
|
||||
require.NoError(t, err, "failed to parse key")
|
||||
|
||||
ev := netmapEvent.UpdatePeer{
|
||||
State: netmapContract.NodeStateOnline,
|
||||
PubKey: key,
|
||||
}
|
||||
proc.handleUpdateState(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
var expUpdPeer netmapclient.UpdatePeerPrm
|
||||
expUpdPeer.SetMaintenance()
|
||||
expUpdPeer.SetOnline()
|
||||
expUpdPeer.SetKey(ev.PubKey.Bytes())
|
||||
|
||||
require.EqualValues(t, []netmapclient.UpdatePeerPrm{expUpdPeer}, nc.peerStateUpdates, "invalid peer state updates")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCleanupTick(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("notary disabled", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nc := &testNetmapClient{}
|
||||
|
||||
proc, err := newTestProc(t, func(p *Params) {
|
||||
p.NetmapClient = nc
|
||||
p.NotaryDisabled = true
|
||||
p.CleanupEnabled = true
|
||||
})
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
key1Str := "038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35"
|
||||
proc.netmapSnapshot.lastAccess[key1Str] = epochStampWithNodeInfo{
|
||||
epochStamp: epochStamp{
|
||||
epoch: 95,
|
||||
removeFlag: false,
|
||||
},
|
||||
}
|
||||
key2Str := "02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3"
|
||||
proc.netmapSnapshot.lastAccess[key2Str] = epochStampWithNodeInfo{
|
||||
epochStamp: epochStamp{
|
||||
epoch: 98,
|
||||
removeFlag: false,
|
||||
},
|
||||
}
|
||||
|
||||
ev := netmapCleanupTick{
|
||||
epoch: 100,
|
||||
txHash: util.Uint256{123},
|
||||
}
|
||||
|
||||
proc.handleCleanupTick(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
keyExp, err := keys.NewPublicKeyFromString(key1Str)
|
||||
require.NoError(t, err, "failed to parse expired key")
|
||||
|
||||
updExp := netmapclient.UpdatePeerPrm{}
|
||||
updExp.SetKey(keyExp.Bytes())
|
||||
updExp.SetHash(ev.TxHash())
|
||||
|
||||
require.EqualValues(t, []netmapclient.UpdatePeerPrm{updExp}, nc.peerStateUpdates, "invalid peer updates")
|
||||
require.True(t, proc.netmapSnapshot.lastAccess[key1Str].removeFlag, "invalid expired removed flag")
|
||||
require.False(t, proc.netmapSnapshot.lastAccess[key2Str].removeFlag, "invalid non expired removed flag")
|
||||
})
|
||||
|
||||
t.Run("notary enabled", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nc := &testNetmapClient{
|
||||
contractAddress: util.Uint160{111},
|
||||
}
|
||||
proc, err := newTestProc(t,
|
||||
func(p *Params) {
|
||||
p.NetmapClient = nc
|
||||
p.CleanupEnabled = true
|
||||
},
|
||||
)
|
||||
|
||||
require.NoError(t, err, "failed to create processor")
|
||||
|
||||
key1Str := "038c862959e56b43e20f79187c4fe9e0bc7c8c66c1603e6cf0ec7f87ab6b08dc35"
|
||||
proc.netmapSnapshot.lastAccess[key1Str] = epochStampWithNodeInfo{
|
||||
epochStamp: epochStamp{
|
||||
epoch: 95,
|
||||
removeFlag: false,
|
||||
},
|
||||
}
|
||||
key2Str := "02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3"
|
||||
proc.netmapSnapshot.lastAccess[key2Str] = epochStampWithNodeInfo{
|
||||
epochStamp: epochStamp{
|
||||
epoch: 98,
|
||||
removeFlag: false,
|
||||
},
|
||||
}
|
||||
|
||||
ev := netmapCleanupTick{
|
||||
epoch: 100,
|
||||
txHash: util.Uint256{123},
|
||||
}
|
||||
|
||||
proc.handleCleanupTick(ev)
|
||||
|
||||
for proc.pool.Running() > 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
keyExp, err := keys.NewPublicKeyFromString(key1Str)
|
||||
require.NoError(t, err, "failed to parse expired key")
|
||||
|
||||
updExp := netmapclient.UpdatePeerPrm{}
|
||||
updExp.SetKey(keyExp.Bytes())
|
||||
updExp.SetHash(ev.TxHash())
|
||||
|
||||
require.EqualValues(t, []notaryInvoke{
|
||||
{
|
||||
contract: nc.contractAddress,
|
||||
fee: 0,
|
||||
nonce: uint32(ev.epoch),
|
||||
vub: nil,
|
||||
method: "updateStateIR",
|
||||
args: []any{int64(v2netmap.Offline), keyExp.Bytes()},
|
||||
},
|
||||
}, nc.notaryInvokes, "invalid notary invokes")
|
||||
require.True(t, proc.netmapSnapshot.lastAccess[key1Str].removeFlag, "invalid expired removed flag")
|
||||
require.False(t, proc.netmapSnapshot.lastAccess[key2Str].removeFlag, "invalid non expired removed flag")
|
||||
})
|
||||
}
|
||||
|
||||
func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) {
|
||||
ns := &testNodeStateSettings{}
|
||||
es := &testEpochState{}
|
||||
r := &testEpochResetter{}
|
||||
as := &testAlphabetState{
|
||||
isAlphabet: true,
|
||||
}
|
||||
cc := &testContainerClient{}
|
||||
nc := &testNetmapClient{}
|
||||
eh := &testEventHandler{}
|
||||
|
||||
p := &Params{
|
||||
Log: test.NewLogger(t, true),
|
||||
PoolSize: 1,
|
||||
CleanupEnabled: false,
|
||||
CleanupThreshold: 3,
|
||||
NotaryDisabled: false,
|
||||
NodeStateSettings: ns,
|
||||
NodeValidator: &testValidator{},
|
||||
EpochState: es,
|
||||
EpochTimer: r,
|
||||
AlphabetState: as,
|
||||
ContainerWrapper: cc,
|
||||
NetmapClient: nc,
|
||||
NotaryDepositHandler: eh.Handle,
|
||||
HandleAudit: eh.Handle,
|
||||
AuditSettlementsHandler: eh.Handle,
|
||||
AlphabetSyncHandler: eh.Handle,
|
||||
}
|
||||
|
||||
nonDefault(p)
|
||||
|
||||
return New(p)
|
||||
}
|
||||
|
||||
type testNodeStateSettings struct {
|
||||
maintAllowed bool
|
||||
}
|
||||
|
||||
func (s *testNodeStateSettings) MaintenanceModeAllowed() error {
|
||||
if s.maintAllowed {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("maintenance mode not allowed")
|
||||
}
|
||||
|
||||
type testValidator struct{}
|
||||
|
||||
func (v *testValidator) VerifyAndUpdate(*netmap.NodeInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type testEpochState struct {
|
||||
counter uint64
|
||||
duration uint64
|
||||
}
|
||||
|
||||
func (s *testEpochState) SetEpochCounter(c uint64) {
|
||||
s.counter = c
|
||||
}
|
||||
func (s *testEpochState) EpochCounter() uint64 {
|
||||
return s.counter
|
||||
}
|
||||
func (s *testEpochState) SetEpochDuration(d uint64) {
|
||||
s.duration = d
|
||||
}
|
||||
func (s *testEpochState) EpochDuration() uint64 {
|
||||
return s.duration
|
||||
}
|
||||
|
||||
type testEpochResetter struct {
|
||||
timers []uint32
|
||||
}
|
||||
|
||||
func (r *testEpochResetter) ResetEpochTimer(t uint32) error {
|
||||
r.timers = append(r.timers, t)
|
||||
return nil
|
||||
}
|
||||
|
||||
type testAlphabetState struct {
|
||||
isAlphabet bool
|
||||
}
|
||||
|
||||
func (s *testAlphabetState) IsAlphabet() bool {
|
||||
return s.isAlphabet
|
||||
}
|
||||
|
||||
type testContainerClient struct {
|
||||
estimations []cntClient.StartEstimationPrm
|
||||
}
|
||||
|
||||
func (c *testContainerClient) StartEstimation(p cntClient.StartEstimationPrm) error {
|
||||
c.estimations = append(c.estimations, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
type notaryInvoke struct {
|
||||
contract util.Uint160
|
||||
fee fixedn.Fixed8
|
||||
nonce uint32
|
||||
vub *uint32
|
||||
method string
|
||||
args []any
|
||||
}
|
||||
|
||||
type testNetmapClient struct {
|
||||
contractAddress util.Uint160
|
||||
epochDuration uint64
|
||||
netmap *netmap.NetMap
|
||||
txHeights map[util.Uint256]uint32
|
||||
|
||||
peerStateUpdates []netmapclient.UpdatePeerPrm
|
||||
notaryInvokes []notaryInvoke
|
||||
newEpochs []uint64
|
||||
addPeers []netmapclient.AddPeerPrm
|
||||
invokedTxs []*transaction.Transaction
|
||||
}
|
||||
|
||||
func (c *testNetmapClient) UpdatePeerState(p netmapclient.UpdatePeerPrm) error {
|
||||
c.peerStateUpdates = append(c.peerStateUpdates, p)
|
||||
return nil
|
||||
}
|
||||
func (c *testNetmapClient) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error {
|
||||
c.notaryInvokes = append(c.notaryInvokes, notaryInvoke{
|
||||
contract: contract,
|
||||
fee: fee,
|
||||
nonce: nonce,
|
||||
vub: vub,
|
||||
method: method,
|
||||
args: args,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
func (c *testNetmapClient) ContractAddress() util.Uint160 {
|
||||
return c.contractAddress
|
||||
}
|
||||
func (c *testNetmapClient) EpochDuration() (uint64, error) {
|
||||
return c.epochDuration, nil
|
||||
}
|
||||
func (c *testNetmapClient) MorphTxHeight(h util.Uint256) (uint32, error) {
|
||||
if res, found := c.txHeights[h]; found {
|
||||
return res, nil
|
||||
}
|
||||
return 0, fmt.Errorf("not found")
|
||||
}
|
||||
func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) {
|
||||
return c.netmap, nil
|
||||
}
|
||||
func (c *testNetmapClient) NewEpoch(epoch uint64, force bool) error {
|
||||
c.newEpochs = append(c.newEpochs, epoch)
|
||||
return nil
|
||||
}
|
||||
func (c *testNetmapClient) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) {
|
||||
return true, nil
|
||||
}
|
||||
func (c *testNetmapClient) AddPeer(p netmapclient.AddPeerPrm) error {
|
||||
c.addPeers = append(c.addPeers, p)
|
||||
return nil
|
||||
}
|
||||
func (c *testNetmapClient) MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error {
|
||||
c.invokedTxs = append(c.invokedTxs, mainTx)
|
||||
return nil
|
||||
}
|
||||
|
||||
type testEventHandler struct {
|
||||
handledEvents []event.Event
|
||||
}
|
||||
|
||||
func (h *testEventHandler) Handle(e event.Event) {
|
||||
h.handledEvents = append(h.handledEvents, e)
|
||||
}
|
|
@ -39,7 +39,7 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) {
|
|||
|
||||
err = np.netmapClient.UpdatePeerState(prm)
|
||||
} else {
|
||||
err = np.netmapClient.Morph().NotaryInvoke(
|
||||
err = np.netmapClient.MorphNotaryInvoke(
|
||||
np.netmapClient.ContractAddress(),
|
||||
0,
|
||||
uint32(ev.epoch),
|
||||
|
|
|
@ -25,7 +25,7 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) {
|
|||
|
||||
np.epochState.SetEpochCounter(epoch)
|
||||
|
||||
h, err := np.netmapClient.Morph().TxHeight(ev.TxHash())
|
||||
h, err := np.netmapClient.MorphTxHeight(ev.TxHash())
|
||||
if err != nil {
|
||||
np.log.Warn(logs.NetmapCantGetTransactionHeight,
|
||||
zap.String("hash", ev.TxHash().StringLE()),
|
||||
|
|
|
@ -21,7 +21,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) {
|
|||
// check if notary transaction is valid, see #976
|
||||
if originalRequest := ev.NotaryRequest(); originalRequest != nil {
|
||||
tx := originalRequest.MainTransaction
|
||||
ok, err := np.netmapClient.Morph().IsValidScript(tx.Script, tx.Signers)
|
||||
ok, err := np.netmapClient.MorphIsValidScript(tx.Script, tx.Signers)
|
||||
if err != nil || !ok {
|
||||
np.log.Warn(logs.NetmapNonhaltNotaryTransaction,
|
||||
zap.String("method", "netmap.AddPeer"),
|
||||
|
@ -73,7 +73,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) {
|
|||
|
||||
if nr := ev.NotaryRequest(); nr != nil {
|
||||
// create new notary request with the original nonce
|
||||
err = np.netmapClient.Morph().NotaryInvoke(
|
||||
err = np.netmapClient.MorphNotaryInvoke(
|
||||
np.netmapClient.ContractAddress(),
|
||||
0,
|
||||
nr.MainTransaction.Nonce,
|
||||
|
@ -117,7 +117,7 @@ func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) {
|
|||
}
|
||||
|
||||
if nr := ev.NotaryRequest(); nr != nil {
|
||||
err = np.netmapClient.Morph().NotarySignAndInvokeTX(nr.MainTransaction)
|
||||
err = np.netmapClient.MorphNotarySignAndInvokeTX(nr.MainTransaction)
|
||||
} else {
|
||||
prm := netmapclient.UpdatePeerPrm{}
|
||||
|
||||
|
|
|
@ -6,13 +6,16 @@ import (
|
|||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
||||
netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event"
|
||||
netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/panjf2000/ants/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -51,6 +54,23 @@ type (
|
|||
VerifyAndUpdate(*netmap.NodeInfo) error
|
||||
}
|
||||
|
||||
Client interface {
|
||||
UpdatePeerState(p netmapclient.UpdatePeerPrm) error
|
||||
MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error
|
||||
ContractAddress() util.Uint160
|
||||
EpochDuration() (uint64, error)
|
||||
MorphTxHeight(h util.Uint256) (res uint32, err error)
|
||||
NetMap() (*netmap.NetMap, error)
|
||||
NewEpoch(epoch uint64, force bool) error
|
||||
MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error)
|
||||
AddPeer(p netmapclient.AddPeerPrm) error
|
||||
MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error
|
||||
}
|
||||
|
||||
ContainerClient interface {
|
||||
StartEstimation(p cntClient.StartEstimationPrm) error
|
||||
}
|
||||
|
||||
// Processor of events produced by network map contract
|
||||
// and new epoch ticker, because it is related to contract.
|
||||
Processor struct {
|
||||
|
@ -60,8 +80,8 @@ type (
|
|||
epochState EpochState
|
||||
alphabetState AlphabetState
|
||||
|
||||
netmapClient *nmClient.Client
|
||||
containerWrp *container.Client
|
||||
netmapClient Client
|
||||
containerWrp ContainerClient
|
||||
|
||||
netmapSnapshot cleanupTable
|
||||
|
||||
|
@ -81,13 +101,13 @@ type (
|
|||
Params struct {
|
||||
Log *logger.Logger
|
||||
PoolSize int
|
||||
NetmapClient *nmClient.Client
|
||||
NetmapClient Client
|
||||
EpochTimer EpochTimerReseter
|
||||
EpochState EpochState
|
||||
AlphabetState AlphabetState
|
||||
CleanupEnabled bool
|
||||
CleanupThreshold uint64 // in epochs
|
||||
ContainerWrapper *container.Client
|
||||
ContainerWrapper ContainerClient
|
||||
|
||||
HandleAudit event.Handler
|
||||
AuditSettlementsHandler event.Handler
|
||||
|
|
59
pkg/innerring/processors/netmap/wrappers.go
Normal file
59
pkg/innerring/processors/netmap/wrappers.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package netmap
|
||||
|
||||
import (
|
||||
netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
)
|
||||
|
||||
func NewNetmapClient(netmapClient *netmapclient.Client) Client {
|
||||
return &netmapClientWrapper{
|
||||
netmapClient: netmapClient,
|
||||
}
|
||||
}
|
||||
|
||||
type netmapClientWrapper struct {
|
||||
netmapClient *netmapclient.Client
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) UpdatePeerState(p netmapclient.UpdatePeerPrm) error {
|
||||
return w.netmapClient.UpdatePeerState(p)
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error {
|
||||
return w.netmapClient.Morph().NotaryInvoke(contract, fee, nonce, vub, method, args...)
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) ContractAddress() util.Uint160 {
|
||||
return w.netmapClient.ContractAddress()
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) EpochDuration() (uint64, error) {
|
||||
return w.netmapClient.EpochDuration()
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) MorphTxHeight(h util.Uint256) (res uint32, err error) {
|
||||
return w.netmapClient.Morph().TxHeight(h)
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) NetMap() (*netmap.NetMap, error) {
|
||||
return w.netmapClient.NetMap()
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) NewEpoch(epoch uint64, force bool) error {
|
||||
return w.netmapClient.NewEpoch(epoch, force)
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) {
|
||||
return w.netmapClient.Morph().IsValidScript(script, signers)
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) AddPeer(p netmapclient.AddPeerPrm) error {
|
||||
return w.netmapClient.AddPeer(p)
|
||||
}
|
||||
|
||||
func (w *netmapClientWrapper) MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error {
|
||||
return w.netmapClient.Morph().NotarySignAndInvokeTX(mainTx)
|
||||
}
|
53
pkg/innerring/state_test.go
Normal file
53
pkg/innerring/state_test.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package innerring
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
||||
control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestServerState(t *testing.T) {
|
||||
keyStr := "03ff65b6ae79134a4dce9d0d39d3851e9bab4ee97abf86e81e1c5bbc50cd2826ae"
|
||||
commiteeKeys, err := keys.NewPublicKeysFromStrings([]string{keyStr})
|
||||
require.NoError(t, err, "convert string to commitee public keys failed")
|
||||
cf := &testCommiteeFetcher{
|
||||
keys: commiteeKeys,
|
||||
}
|
||||
|
||||
irKeys, err := keys.NewPublicKeysFromStrings([]string{keyStr})
|
||||
require.NoError(t, err, "convert string to IR public keys failed")
|
||||
irf := &testIRFetcher{
|
||||
keys: irKeys,
|
||||
}
|
||||
|
||||
key, err := keys.NewPublicKeyFromString(keyStr)
|
||||
require.NoError(t, err, "convert string to public key failed")
|
||||
|
||||
require.NoError(t, err, "failed to create morph client")
|
||||
srv := &Server{
|
||||
statusIndex: newInnerRingIndexer(cf, irf, key, time.Second),
|
||||
morphClient: &client.Client{},
|
||||
}
|
||||
|
||||
var epoch uint64 = 100
|
||||
srv.SetEpochCounter(epoch)
|
||||
require.Equal(t, epoch, srv.EpochCounter(), "invalid epoch counter")
|
||||
|
||||
var epochDuration uint64 = 15
|
||||
srv.SetEpochDuration(epochDuration)
|
||||
require.Equal(t, epochDuration, srv.EpochDuration(), "invalid epoch duration")
|
||||
|
||||
var healthStatus control.HealthStatus = control.HealthStatus_READY
|
||||
srv.setHealthStatus(healthStatus)
|
||||
require.Equal(t, healthStatus, srv.HealthStatus(), "invalid health status")
|
||||
|
||||
require.True(t, srv.IsActive(), "invalid IsActive result")
|
||||
require.True(t, srv.IsAlphabet(), "invalid IsAlphabet result")
|
||||
require.Equal(t, 0, srv.InnerRingIndex(), "invalid IR index")
|
||||
require.Equal(t, 1, srv.InnerRingSize(), "invalid IR index")
|
||||
require.Equal(t, 0, srv.AlphabetIndex(), "invalid alphabet index")
|
||||
}
|
|
@ -26,8 +26,12 @@ func AsContainerSource(w *Client) containercore.Source {
|
|||
return (*containerSource)(w)
|
||||
}
|
||||
|
||||
type getContainer interface {
|
||||
Get(cid []byte) (*containercore.Container, error)
|
||||
}
|
||||
|
||||
// Get marshals container ID, and passes it to Wrapper's Get method.
|
||||
func Get(c *Client, cnr cid.ID) (*containercore.Container, error) {
|
||||
func Get(c getContainer, cnr cid.ID) (*containercore.Container, error) {
|
||||
binCnr := make([]byte, sha256.Size)
|
||||
cnr.Encode(binCnr)
|
||||
|
||||
|
|
|
@ -12,34 +12,34 @@ import (
|
|||
|
||||
// Delete structure of container.Delete notification from morph chain.
|
||||
type Delete struct {
|
||||
containerID []byte
|
||||
signature []byte
|
||||
token []byte
|
||||
ContainerIDValue []byte
|
||||
SignatureValue []byte
|
||||
TokenValue []byte
|
||||
|
||||
// For notary notifications only.
|
||||
// Contains raw transactions of notary request.
|
||||
notaryRequest *payload.P2PNotaryRequest
|
||||
NotaryRequestValue *payload.P2PNotaryRequest
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
func (Delete) MorphEvent() {}
|
||||
|
||||
// ContainerID is a marshalled container structure, defined in API.
|
||||
func (d Delete) ContainerID() []byte { return d.containerID }
|
||||
func (d Delete) ContainerID() []byte { return d.ContainerIDValue }
|
||||
|
||||
// Signature of marshalled container by container owner.
|
||||
func (d Delete) Signature() []byte { return d.signature }
|
||||
func (d Delete) Signature() []byte { return d.SignatureValue }
|
||||
|
||||
// SessionToken returns binary token of the session
|
||||
// within which the eACL was set.
|
||||
func (d Delete) SessionToken() []byte {
|
||||
return d.token
|
||||
return d.TokenValue
|
||||
}
|
||||
|
||||
// NotaryRequest returns raw notary request if notification
|
||||
// was received via notary service. Otherwise, returns nil.
|
||||
func (d Delete) NotaryRequest() *payload.P2PNotaryRequest {
|
||||
return d.notaryRequest
|
||||
return d.NotaryRequestValue
|
||||
}
|
||||
|
||||
const expectedItemNumDelete = 3
|
||||
|
@ -63,19 +63,19 @@ func ParseDelete(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
}
|
||||
|
||||
// parse container
|
||||
ev.containerID, err = client.BytesFromStackItem(params[0])
|
||||
ev.ContainerIDValue, err = client.BytesFromStackItem(params[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get container: %w", err)
|
||||
}
|
||||
|
||||
// parse signature
|
||||
ev.signature, err = client.BytesFromStackItem(params[1])
|
||||
ev.SignatureValue, err = client.BytesFromStackItem(params[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get signature: %w", err)
|
||||
}
|
||||
|
||||
// parse session token
|
||||
ev.token, err = client.BytesFromStackItem(params[2])
|
||||
ev.TokenValue, err = client.BytesFromStackItem(params[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get session token: %w", err)
|
||||
}
|
||||
|
|
|
@ -7,19 +7,19 @@ import (
|
|||
|
||||
func (d *Delete) setContainerID(v []byte) {
|
||||
if v != nil {
|
||||
d.containerID = v
|
||||
d.ContainerIDValue = v
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Delete) setSignature(v []byte) {
|
||||
if v != nil {
|
||||
d.signature = v
|
||||
d.SignatureValue = v
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Delete) setToken(v []byte) {
|
||||
if v != nil {
|
||||
d.token = v
|
||||
d.TokenValue = v
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ func ParseDeleteNotary(ne event.NotaryEvent) (event.Event, error) {
|
|||
}
|
||||
}
|
||||
|
||||
ev.notaryRequest = ne.Raw()
|
||||
ev.NotaryRequestValue = ne.Raw()
|
||||
|
||||
return ev, nil
|
||||
}
|
||||
|
|
|
@ -63,9 +63,9 @@ func TestParseDelete(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, Delete{
|
||||
containerID: containerID,
|
||||
signature: signature,
|
||||
token: token,
|
||||
ContainerIDValue: containerID,
|
||||
SignatureValue: signature,
|
||||
TokenValue: token,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@ import (
|
|||
// SetEACL represents structure of notification about
|
||||
// modified eACL table coming from FrostFS Container contract.
|
||||
type SetEACL struct {
|
||||
table []byte
|
||||
signature []byte
|
||||
publicKey []byte
|
||||
token []byte
|
||||
TableValue []byte
|
||||
SignatureValue []byte
|
||||
PublicKeyValue []byte
|
||||
TokenValue []byte
|
||||
|
||||
// For notary notifications only.
|
||||
// Contains raw transactions of notary request.
|
||||
notaryRequest *payload.P2PNotaryRequest
|
||||
NotaryRequestValue *payload.P2PNotaryRequest
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
|
@ -27,30 +27,30 @@ func (SetEACL) MorphEvent() {}
|
|||
|
||||
// Table returns returns eACL table in a binary FrostFS API format.
|
||||
func (x SetEACL) Table() []byte {
|
||||
return x.table
|
||||
return x.TableValue
|
||||
}
|
||||
|
||||
// Signature returns signature of the binary table.
|
||||
func (x SetEACL) Signature() []byte {
|
||||
return x.signature
|
||||
return x.SignatureValue
|
||||
}
|
||||
|
||||
// PublicKey returns public keys of container
|
||||
// owner in a binary format.
|
||||
func (x SetEACL) PublicKey() []byte {
|
||||
return x.publicKey
|
||||
return x.PublicKeyValue
|
||||
}
|
||||
|
||||
// SessionToken returns binary token of the session
|
||||
// within which the eACL was set.
|
||||
func (x SetEACL) SessionToken() []byte {
|
||||
return x.token
|
||||
return x.TokenValue
|
||||
}
|
||||
|
||||
// NotaryRequest returns raw notary request if notification
|
||||
// was received via notary service. Otherwise, returns nil.
|
||||
func (x SetEACL) NotaryRequest() *payload.P2PNotaryRequest {
|
||||
return x.notaryRequest
|
||||
return x.NotaryRequestValue
|
||||
}
|
||||
|
||||
const expectedItemNumEACL = 4
|
||||
|
@ -74,25 +74,25 @@ func ParseSetEACL(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
}
|
||||
|
||||
// parse table
|
||||
ev.table, err = client.BytesFromStackItem(params[0])
|
||||
ev.TableValue, err = client.BytesFromStackItem(params[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse binary table: %w", err)
|
||||
}
|
||||
|
||||
// parse signature
|
||||
ev.signature, err = client.BytesFromStackItem(params[1])
|
||||
ev.SignatureValue, err = client.BytesFromStackItem(params[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse table signature: %w", err)
|
||||
}
|
||||
|
||||
// parse public key
|
||||
ev.publicKey, err = client.BytesFromStackItem(params[2])
|
||||
ev.PublicKeyValue, err = client.BytesFromStackItem(params[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse binary public key: %w", err)
|
||||
}
|
||||
|
||||
// parse session token
|
||||
ev.token, err = client.BytesFromStackItem(params[3])
|
||||
ev.TokenValue, err = client.BytesFromStackItem(params[3])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get session token: %w", err)
|
||||
}
|
||||
|
|
|
@ -7,25 +7,25 @@ import (
|
|||
|
||||
func (x *SetEACL) setTable(v []byte) {
|
||||
if v != nil {
|
||||
x.table = v
|
||||
x.TableValue = v
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SetEACL) setSignature(v []byte) {
|
||||
if v != nil {
|
||||
x.signature = v
|
||||
x.SignatureValue = v
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SetEACL) setPublicKey(v []byte) {
|
||||
if v != nil {
|
||||
x.publicKey = v
|
||||
x.PublicKeyValue = v
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SetEACL) setToken(v []byte) {
|
||||
if v != nil {
|
||||
x.token = v
|
||||
x.TokenValue = v
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ func ParseSetEACLNotary(ne event.NotaryEvent) (event.Event, error) {
|
|||
}
|
||||
}
|
||||
|
||||
ev.notaryRequest = ne.Raw()
|
||||
ev.NotaryRequestValue = ne.Raw()
|
||||
|
||||
return ev, nil
|
||||
}
|
||||
|
|
|
@ -11,31 +11,31 @@ import (
|
|||
)
|
||||
|
||||
type Bind struct {
|
||||
bindCommon
|
||||
BindCommon
|
||||
}
|
||||
|
||||
type bindCommon struct {
|
||||
user []byte
|
||||
keys [][]byte
|
||||
type BindCommon struct {
|
||||
UserValue []byte
|
||||
KeysValue [][]byte
|
||||
|
||||
// txHash is used in notary environmental
|
||||
// TxHashValue is used in notary environmental
|
||||
// for calculating unique but same for
|
||||
// all notification receivers values.
|
||||
txHash util.Uint256
|
||||
TxHashValue util.Uint256
|
||||
}
|
||||
|
||||
// TxHash returns hash of the TX with new epoch
|
||||
// notification.
|
||||
func (b bindCommon) TxHash() util.Uint256 {
|
||||
return b.txHash
|
||||
func (b BindCommon) TxHash() util.Uint256 {
|
||||
return b.TxHashValue
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
func (bindCommon) MorphEvent() {}
|
||||
func (BindCommon) MorphEvent() {}
|
||||
|
||||
func (b bindCommon) Keys() [][]byte { return b.keys }
|
||||
func (b BindCommon) Keys() [][]byte { return b.KeysValue }
|
||||
|
||||
func (b bindCommon) User() []byte { return b.user }
|
||||
func (b BindCommon) User() []byte { return b.UserValue }
|
||||
|
||||
func ParseBind(e *state.ContainedNotificationEvent) (event.Event, error) {
|
||||
var (
|
||||
|
@ -48,17 +48,17 @@ func ParseBind(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not parse stack items from notify event: %w", err)
|
||||
}
|
||||
|
||||
err = parseBind(&ev.bindCommon, params)
|
||||
err = parseBind(&ev.BindCommon, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ev.txHash = e.Container
|
||||
ev.TxHashValue = e.Container
|
||||
|
||||
return ev, nil
|
||||
}
|
||||
|
||||
func parseBind(dst *bindCommon, params []stackitem.Item) error {
|
||||
func parseBind(dst *BindCommon, params []stackitem.Item) error {
|
||||
if ln := len(params); ln != 2 {
|
||||
return event.WrongNumberOfParameters(2, ln)
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ func parseBind(dst *bindCommon, params []stackitem.Item) error {
|
|||
var err error
|
||||
|
||||
// parse user
|
||||
dst.user, err = client.BytesFromStackItem(params[0])
|
||||
dst.UserValue, err = client.BytesFromStackItem(params[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get bind user: %w", err)
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ func parseBind(dst *bindCommon, params []stackitem.Item) error {
|
|||
return fmt.Errorf("could not get bind keys: %w", err)
|
||||
}
|
||||
|
||||
dst.keys = make([][]byte, 0, len(bindKeys))
|
||||
dst.KeysValue = make([][]byte, 0, len(bindKeys))
|
||||
|
||||
for i := range bindKeys {
|
||||
rawKey, err := client.BytesFromStackItem(bindKeys[i])
|
||||
|
@ -85,7 +85,7 @@ func parseBind(dst *bindCommon, params []stackitem.Item) error {
|
|||
return fmt.Errorf("could not get bind public key: %w", err)
|
||||
}
|
||||
|
||||
dst.keys = append(dst.keys, rawKey)
|
||||
dst.KeysValue = append(dst.KeysValue, rawKey)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -11,26 +11,26 @@ import (
|
|||
|
||||
// Cheque structure of frostfs.Cheque notification from mainnet chain.
|
||||
type Cheque struct {
|
||||
id []byte
|
||||
amount int64 // Fixed8
|
||||
user util.Uint160
|
||||
lock util.Uint160
|
||||
IDValue []byte
|
||||
AmountValue int64 // Fixed8
|
||||
UserValue util.Uint160
|
||||
LockValue util.Uint160
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
func (Cheque) MorphEvent() {}
|
||||
|
||||
// ID is a withdraw transaction hash.
|
||||
func (c Cheque) ID() []byte { return c.id }
|
||||
func (c Cheque) ID() []byte { return c.IDValue }
|
||||
|
||||
// User returns withdraw receiver script hash from main net.
|
||||
func (c Cheque) User() util.Uint160 { return c.user }
|
||||
func (c Cheque) User() util.Uint160 { return c.UserValue }
|
||||
|
||||
// Amount of the sent assets.
|
||||
func (c Cheque) Amount() int64 { return c.amount }
|
||||
func (c Cheque) Amount() int64 { return c.AmountValue }
|
||||
|
||||
// LockAccount return script hash for balance contract wallet.
|
||||
func (c Cheque) LockAccount() util.Uint160 { return c.lock }
|
||||
func (c Cheque) LockAccount() util.Uint160 { return c.LockValue }
|
||||
|
||||
// ParseCheque from notification into cheque structure.
|
||||
func ParseCheque(e *state.ContainedNotificationEvent) (event.Event, error) {
|
||||
|
@ -49,7 +49,7 @@ func ParseCheque(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
}
|
||||
|
||||
// parse id
|
||||
ev.id, err = client.BytesFromStackItem(params[0])
|
||||
ev.IDValue, err = client.BytesFromStackItem(params[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get cheque id: %w", err)
|
||||
}
|
||||
|
@ -60,13 +60,13 @@ func ParseCheque(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not get cheque user: %w", err)
|
||||
}
|
||||
|
||||
ev.user, err = util.Uint160DecodeBytesBE(user)
|
||||
ev.UserValue, err = util.Uint160DecodeBytesBE(user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert cheque user to uint160: %w", err)
|
||||
}
|
||||
|
||||
// parse amount
|
||||
ev.amount, err = client.IntFromStackItem(params[2])
|
||||
ev.AmountValue, err = client.IntFromStackItem(params[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get cheque amount: %w", err)
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ func ParseCheque(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not get cheque lock account: %w", err)
|
||||
}
|
||||
|
||||
ev.lock, err = util.Uint160DecodeBytesBE(lock)
|
||||
ev.LockValue, err = util.Uint160DecodeBytesBE(lock)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert cheque lock account to uint160: %w", err)
|
||||
}
|
||||
|
|
|
@ -77,10 +77,10 @@ func TestParseCheque(t *testing.T) {
|
|||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, Cheque{
|
||||
id: id,
|
||||
amount: amount,
|
||||
user: user,
|
||||
lock: lock,
|
||||
IDValue: id,
|
||||
AmountValue: amount,
|
||||
UserValue: user,
|
||||
LockValue: lock,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,30 +10,30 @@ import (
|
|||
)
|
||||
|
||||
type Config struct {
|
||||
key []byte
|
||||
value []byte
|
||||
id []byte
|
||||
KeyValue []byte
|
||||
ValueValue []byte
|
||||
IDValue []byte
|
||||
|
||||
// txHash is used in notary environmental
|
||||
// TxHashValue is used in notary environmental
|
||||
// for calculating unique but same for
|
||||
// all notification receivers values.
|
||||
txHash util.Uint256
|
||||
TxHashValue util.Uint256
|
||||
}
|
||||
|
||||
// TxHash returns hash of the TX with new epoch
|
||||
// notification.
|
||||
func (u Config) TxHash() util.Uint256 {
|
||||
return u.txHash
|
||||
return u.TxHashValue
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
func (Config) MorphEvent() {}
|
||||
|
||||
func (u Config) ID() []byte { return u.id }
|
||||
func (u Config) ID() []byte { return u.IDValue }
|
||||
|
||||
func (u Config) Key() []byte { return u.key }
|
||||
func (u Config) Key() []byte { return u.KeyValue }
|
||||
|
||||
func (u Config) Value() []byte { return u.value }
|
||||
func (u Config) Value() []byte { return u.ValueValue }
|
||||
|
||||
func ParseConfig(e *state.ContainedNotificationEvent) (event.Event, error) {
|
||||
var (
|
||||
|
@ -51,24 +51,24 @@ func ParseConfig(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
}
|
||||
|
||||
// parse id
|
||||
ev.id, err = client.BytesFromStackItem(params[0])
|
||||
ev.IDValue, err = client.BytesFromStackItem(params[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get config update id: %w", err)
|
||||
}
|
||||
|
||||
// parse key
|
||||
ev.key, err = client.BytesFromStackItem(params[1])
|
||||
ev.KeyValue, err = client.BytesFromStackItem(params[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get config key: %w", err)
|
||||
}
|
||||
|
||||
// parse value
|
||||
ev.value, err = client.BytesFromStackItem(params[2])
|
||||
ev.ValueValue, err = client.BytesFromStackItem(params[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get config value: %w", err)
|
||||
}
|
||||
|
||||
ev.txHash = e.Container
|
||||
ev.TxHashValue = e.Container
|
||||
|
||||
return ev, nil
|
||||
}
|
||||
|
|
|
@ -60,9 +60,9 @@ func TestParseConfig(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, Config{
|
||||
id: id,
|
||||
key: key,
|
||||
value: value,
|
||||
IDValue: id,
|
||||
KeyValue: key,
|
||||
ValueValue: value,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,26 +11,26 @@ import (
|
|||
|
||||
// Deposit structure of frostfs.Deposit notification from mainnet chain.
|
||||
type Deposit struct {
|
||||
id []byte
|
||||
amount int64 // Fixed8
|
||||
from util.Uint160
|
||||
to util.Uint160
|
||||
IDValue []byte
|
||||
AmountValue int64 // Fixed8
|
||||
FromValue util.Uint160
|
||||
ToValue util.Uint160
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
func (Deposit) MorphEvent() {}
|
||||
|
||||
// ID is a deposit transaction hash.
|
||||
func (d Deposit) ID() []byte { return d.id }
|
||||
func (d Deposit) ID() []byte { return d.IDValue }
|
||||
|
||||
// From is a script hash of asset sender in main net.
|
||||
func (d Deposit) From() util.Uint160 { return d.from }
|
||||
func (d Deposit) From() util.Uint160 { return d.FromValue }
|
||||
|
||||
// To is a script hash of asset receiver in balance contract.
|
||||
func (d Deposit) To() util.Uint160 { return d.to }
|
||||
func (d Deposit) To() util.Uint160 { return d.ToValue }
|
||||
|
||||
// Amount of transferred assets.
|
||||
func (d Deposit) Amount() int64 { return d.amount }
|
||||
func (d Deposit) Amount() int64 { return d.AmountValue }
|
||||
|
||||
// ParseDeposit notification into deposit structure.
|
||||
func ParseDeposit(e *state.ContainedNotificationEvent) (event.Event, error) {
|
||||
|
@ -51,13 +51,13 @@ func ParseDeposit(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not get deposit sender: %w", err)
|
||||
}
|
||||
|
||||
ev.from, err = util.Uint160DecodeBytesBE(from)
|
||||
ev.FromValue, err = util.Uint160DecodeBytesBE(from)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert deposit sender to uint160: %w", err)
|
||||
}
|
||||
|
||||
// parse amount
|
||||
ev.amount, err = client.IntFromStackItem(params[1])
|
||||
ev.AmountValue, err = client.IntFromStackItem(params[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get deposit amount: %w", err)
|
||||
}
|
||||
|
@ -68,13 +68,13 @@ func ParseDeposit(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not get deposit receiver: %w", err)
|
||||
}
|
||||
|
||||
ev.to, err = util.Uint160DecodeBytesBE(to)
|
||||
ev.ToValue, err = util.Uint160DecodeBytesBE(to)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert deposit receiver to uint160: %w", err)
|
||||
}
|
||||
|
||||
// parse id
|
||||
ev.id, err = client.BytesFromStackItem(params[3])
|
||||
ev.IDValue, err = client.BytesFromStackItem(params[3])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get deposit id: %w", err)
|
||||
}
|
||||
|
|
|
@ -77,10 +77,10 @@ func TestParseDeposit(t *testing.T) {
|
|||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, Deposit{
|
||||
id: id,
|
||||
amount: amount,
|
||||
from: from,
|
||||
to: to,
|
||||
IDValue: id,
|
||||
AmountValue: amount,
|
||||
FromValue: from,
|
||||
ToValue: to,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
type Unbind struct {
|
||||
bindCommon
|
||||
BindCommon
|
||||
}
|
||||
|
||||
func ParseUnbind(e *state.ContainedNotificationEvent) (event.Event, error) {
|
||||
|
@ -22,12 +22,12 @@ func ParseUnbind(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not parse stack items from notify event: %w", err)
|
||||
}
|
||||
|
||||
err = parseBind(&ev.bindCommon, params)
|
||||
err = parseBind(&ev.BindCommon, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ev.txHash = e.Container
|
||||
ev.TxHashValue = e.Container
|
||||
|
||||
return ev, nil
|
||||
}
|
||||
|
|
|
@ -11,22 +11,22 @@ import (
|
|||
|
||||
// Withdraw structure of frostfs.Withdraw notification from mainnet chain.
|
||||
type Withdraw struct {
|
||||
id []byte
|
||||
amount int64 // Fixed8
|
||||
user util.Uint160
|
||||
IDValue []byte
|
||||
AmountValue int64 // Fixed8
|
||||
UserValue util.Uint160
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
func (Withdraw) MorphEvent() {}
|
||||
|
||||
// ID is a withdraw transaction hash.
|
||||
func (w Withdraw) ID() []byte { return w.id }
|
||||
func (w Withdraw) ID() []byte { return w.IDValue }
|
||||
|
||||
// User returns withdraw receiver script hash from main net.
|
||||
func (w Withdraw) User() util.Uint160 { return w.user }
|
||||
func (w Withdraw) User() util.Uint160 { return w.UserValue }
|
||||
|
||||
// Amount of the withdraw assets.
|
||||
func (w Withdraw) Amount() int64 { return w.amount }
|
||||
func (w Withdraw) Amount() int64 { return w.AmountValue }
|
||||
|
||||
// ParseWithdraw notification into withdraw structure.
|
||||
func ParseWithdraw(e *state.ContainedNotificationEvent) (event.Event, error) {
|
||||
|
@ -47,19 +47,19 @@ func ParseWithdraw(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not get withdraw user: %w", err)
|
||||
}
|
||||
|
||||
ev.user, err = util.Uint160DecodeBytesBE(user)
|
||||
ev.UserValue, err = util.Uint160DecodeBytesBE(user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert withdraw user to uint160: %w", err)
|
||||
}
|
||||
|
||||
// parse amount
|
||||
ev.amount, err = client.IntFromStackItem(params[1])
|
||||
ev.AmountValue, err = client.IntFromStackItem(params[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get withdraw amount: %w", err)
|
||||
}
|
||||
|
||||
// parse id
|
||||
ev.id, err = client.BytesFromStackItem(params[2])
|
||||
ev.IDValue, err = client.BytesFromStackItem(params[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get withdraw id: %w", err)
|
||||
}
|
||||
|
|
|
@ -64,9 +64,9 @@ func TestParseWithdraw(t *testing.T) {
|
|||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, Withdraw{
|
||||
id: id,
|
||||
amount: amount,
|
||||
user: user,
|
||||
IDValue: id,
|
||||
AmountValue: amount,
|
||||
UserValue: user,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,24 +10,24 @@ import (
|
|||
)
|
||||
|
||||
type AddPeer struct {
|
||||
node []byte
|
||||
NodeBytes []byte
|
||||
|
||||
// For notary notifications only.
|
||||
// Contains raw transactions of notary request.
|
||||
notaryRequest *payload.P2PNotaryRequest
|
||||
Request *payload.P2PNotaryRequest
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
func (AddPeer) MorphEvent() {}
|
||||
|
||||
func (s AddPeer) Node() []byte {
|
||||
return s.node
|
||||
return s.NodeBytes
|
||||
}
|
||||
|
||||
// NotaryRequest returns raw notary request if notification
|
||||
// was received via notary service. Otherwise, returns nil.
|
||||
func (s AddPeer) NotaryRequest() *payload.P2PNotaryRequest {
|
||||
return s.notaryRequest
|
||||
return s.Request
|
||||
}
|
||||
|
||||
const expectedItemNumAddPeer = 1
|
||||
|
@ -47,7 +47,7 @@ func ParseAddPeer(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, event.WrongNumberOfParameters(expectedItemNumAddPeer, ln)
|
||||
}
|
||||
|
||||
ev.node, err = client.BytesFromStackItem(params[0])
|
||||
ev.NodeBytes, err = client.BytesFromStackItem(params[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get raw nodeinfo: %w", err)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
func (s *AddPeer) setNode(v []byte) {
|
||||
if v != nil {
|
||||
s.node = v
|
||||
s.NodeBytes = v
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ func ParseAddPeerNotary(ne event.NotaryEvent) (event.Event, error) {
|
|||
}
|
||||
}
|
||||
|
||||
ev.notaryRequest = ne.Raw()
|
||||
ev.Request = ne.Raw()
|
||||
|
||||
return ev, nil
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func TestParseAddPeer(t *testing.T) {
|
|||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, AddPeer{
|
||||
node: info,
|
||||
NodeBytes: info,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,12 +11,12 @@ import (
|
|||
|
||||
// NewEpoch is a new epoch Neo:Morph event.
|
||||
type NewEpoch struct {
|
||||
num uint64
|
||||
Num uint64
|
||||
|
||||
// txHash is used in notary environmental
|
||||
// Hash is used in notary environmental
|
||||
// for calculating unique but same for
|
||||
// all notification receivers values.
|
||||
txHash util.Uint256
|
||||
Hash util.Uint256
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
|
@ -24,13 +24,13 @@ func (NewEpoch) MorphEvent() {}
|
|||
|
||||
// EpochNumber returns new epoch number.
|
||||
func (s NewEpoch) EpochNumber() uint64 {
|
||||
return s.num
|
||||
return s.Num
|
||||
}
|
||||
|
||||
// TxHash returns hash of the TX with new epoch
|
||||
// notification.
|
||||
func (s NewEpoch) TxHash() util.Uint256 {
|
||||
return s.txHash
|
||||
return s.Hash
|
||||
}
|
||||
|
||||
// ParseNewEpoch is a parser of new epoch notification event.
|
||||
|
@ -52,7 +52,7 @@ func ParseNewEpoch(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
}
|
||||
|
||||
return NewEpoch{
|
||||
num: uint64(prmEpochNum),
|
||||
txHash: e.Container,
|
||||
Num: uint64(prmEpochNum),
|
||||
Hash: e.Container,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func TestParseNewEpoch(t *testing.T) {
|
|||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, NewEpoch{
|
||||
num: epochNum,
|
||||
Num: epochNum,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -13,13 +13,13 @@ import (
|
|||
)
|
||||
|
||||
type UpdatePeer struct {
|
||||
publicKey *keys.PublicKey
|
||||
PubKey *keys.PublicKey
|
||||
|
||||
state netmap.NodeState
|
||||
State netmap.NodeState
|
||||
|
||||
// For notary notifications only.
|
||||
// Contains raw transactions of notary request.
|
||||
notaryRequest *payload.P2PNotaryRequest
|
||||
Request *payload.P2PNotaryRequest
|
||||
}
|
||||
|
||||
// MorphEvent implements Neo:Morph Event interface.
|
||||
|
@ -28,27 +28,27 @@ func (UpdatePeer) MorphEvent() {}
|
|||
// Online returns true if node's state is requested to be switched
|
||||
// to "online".
|
||||
func (s UpdatePeer) Online() bool {
|
||||
return s.state == netmap.NodeStateOnline
|
||||
return s.State == netmap.NodeStateOnline
|
||||
}
|
||||
|
||||
// Maintenance returns true if node's state is requested to be switched
|
||||
// to "maintenance".
|
||||
func (s UpdatePeer) Maintenance() bool {
|
||||
return s.state == netmap.NodeStateMaintenance
|
||||
return s.State == netmap.NodeStateMaintenance
|
||||
}
|
||||
|
||||
func (s UpdatePeer) PublicKey() *keys.PublicKey {
|
||||
return s.publicKey
|
||||
return s.PubKey
|
||||
}
|
||||
|
||||
// NotaryRequest returns raw notary request if notification
|
||||
// was received via notary service. Otherwise, returns nil.
|
||||
func (s UpdatePeer) NotaryRequest() *payload.P2PNotaryRequest {
|
||||
return s.notaryRequest
|
||||
return s.Request
|
||||
}
|
||||
|
||||
func (s *UpdatePeer) decodeState(state int64) error {
|
||||
switch s.state = netmap.NodeState(state); s.state {
|
||||
switch s.State = netmap.NodeState(state); s.State {
|
||||
default:
|
||||
return fmt.Errorf("unsupported node state %d", state)
|
||||
case
|
||||
|
@ -82,7 +82,7 @@ func ParseUpdatePeer(e *state.ContainedNotificationEvent) (event.Event, error) {
|
|||
return nil, fmt.Errorf("could not get public key: %w", err)
|
||||
}
|
||||
|
||||
ev.publicKey, err = keys.NewPublicKeyFromBytes(key, elliptic.P256())
|
||||
ev.PubKey, err = keys.NewPublicKeyFromBytes(key, elliptic.P256())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse public key: %w", err)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ func (s *UpdatePeer) setPublicKey(v []byte) (err error) {
|
|||
return errNilPubKey
|
||||
}
|
||||
|
||||
s.publicKey, err = keys.NewPublicKeyFromBytes(v, elliptic.P256())
|
||||
s.PubKey, err = keys.NewPublicKeyFromBytes(v, elliptic.P256())
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse public key: %w", err)
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ func ParseUpdatePeerNotary(ne event.NotaryEvent) (event.Event, error) {
|
|||
}
|
||||
}
|
||||
|
||||
ev.notaryRequest = ne.Raw()
|
||||
ev.Request = ne.Raw()
|
||||
|
||||
return ev, nil
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ func TestParseUpdatePeer(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, UpdatePeer{
|
||||
publicKey: publicKey,
|
||||
state: state,
|
||||
PubKey: publicKey,
|
||||
State: state,
|
||||
}, ev)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue