package innerring import ( "errors" "fmt" "strings" "github.com/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/viper" ) type contracts struct { frostfs util.Uint160 // in mainnet netmap util.Uint160 // in morph balance util.Uint160 // in morph container util.Uint160 // in morph audit util.Uint160 // in morph proxy util.Uint160 // in morph processing util.Uint160 // in mainnet reputation util.Uint160 // in morph subnet util.Uint160 // in morph frostfsID util.Uint160 // in morph alphabet alphabetContracts // in morph } func parseContracts(cfg *viper.Viper, morph *client.Client, withoutMainNet, withoutMainNotary, withoutSideNotary bool) (*contracts, error) { var ( result = new(contracts) err error ) if !withoutMainNet { result.frostfs, err = util.Uint160DecodeStringLE(cfg.GetString("contracts.frostfs")) if err != nil { return nil, fmt.Errorf("can't get frostfs script hash: %w", err) } if !withoutMainNotary { result.processing, err = util.Uint160DecodeStringLE(cfg.GetString("contracts.processing")) if err != nil { return nil, fmt.Errorf("can't get processing script hash: %w", err) } } } if !withoutSideNotary { result.proxy, err = parseContract(cfg, morph, "contracts.proxy", client.NNSProxyContractName) if err != nil { return nil, fmt.Errorf("can't get proxy script hash: %w", err) } } targets := [...]struct { cfgName string nnsName string dest *util.Uint160 }{ {"contracts.netmap", client.NNSNetmapContractName, &result.netmap}, {"contracts.balance", client.NNSBalanceContractName, &result.balance}, {"contracts.container", client.NNSContainerContractName, &result.container}, {"contracts.audit", client.NNSAuditContractName, &result.audit}, {"contracts.reputation", client.NNSReputationContractName, &result.reputation}, {"contracts.subnet", client.NNSSubnetworkContractName, &result.subnet}, {"contracts.frostfsid", client.NNSFrostFSIDContractName, &result.frostfsID}, } for _, t := range targets { *t.dest, err = parseContract(cfg, morph, t.cfgName, t.nnsName) if err != nil { name := strings.TrimPrefix(t.cfgName, "contracts.") return nil, fmt.Errorf("can't get %s script hash: %w", name, err) } } result.alphabet, err = parseAlphabetContracts(cfg, morph) if err != nil { return nil, err } return result, nil } func parseAlphabetContracts(cfg *viper.Viper, morph *client.Client) (alphabetContracts, error) { num := GlagoliticLetter(cfg.GetUint("contracts.alphabet.amount")) alpha := newAlphabetContracts() if num > lastLetterNum { return nil, fmt.Errorf("amount of alphabet contracts overflows glagolitsa %d > %d", num, lastLetterNum) } thresholdIsSet := num != 0 if !thresholdIsSet { // try to read maximum alphabet contracts // if threshold has not been set manually num = lastLetterNum } for letter := az; letter < num; letter++ { contractHash, err := parseContract(cfg, morph, "contracts.alphabet."+letter.String(), client.NNSAlphabetContractName(int(letter)), ) if err != nil { if errors.Is(err, client.ErrNNSRecordNotFound) { break } return nil, fmt.Errorf("invalid alphabet %s contract: %w", letter, err) } alpha.set(letter, contractHash) } if thresholdIsSet && len(alpha) != int(num) { return nil, fmt.Errorf("could not read all contracts: required %d, read %d", num, len(alpha)) } return alpha, nil } func parseContract(cfg *viper.Viper, morph *client.Client, cfgName, nnsName string) (res util.Uint160, err error) { contractStr := cfg.GetString(cfgName) if len(contractStr) == 0 { return morph.NNSContractAddress(nnsName) } return util.Uint160DecodeStringLE(contractStr) }