diff --git a/.gitignore b/.gitignore index 19adcc4..accb5f4 100755 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,6 @@ ledger/.data/* oracle/config.*.json # Deploy vendor nebula-address.txt -migration.txt \ No newline at end of file +migration.txt +cmd/gravity/gravity +.vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..537b38b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}/cmd/gravity", + "args": [ + "ledger", + "--home=/home/anaximen/ledger", + "start", + "--bootstrap=" + ] + }, + ] +} \ No newline at end of file diff --git a/cmd/gravity/commands/ledger.go b/cmd/gravity/commands/ledger.go index 2f5d8d7..083ea96 100755 --- a/cmd/gravity/commands/ledger.go +++ b/cmd/gravity/commands/ledger.go @@ -55,8 +55,8 @@ const ( NetworkFlag = "network" BootstrapUrlFlag = "bootstrap" - Custom Network = "custom" - DevNet Network = "devnet" + Custom Network = "custom" + DevNet Network = "devnet" Mainnet Network = "mainnet" DevNetId ChainId = "gravity-devnet" @@ -76,14 +76,16 @@ var ( Mempool: cfg.DefaultMempoolConfig(), Details: (&config.ValidatorDetails{}).DefaultNew(), Adapters: map[string]config.AdaptorsConfig{ - account.Ethereum.String(): { + "ethereum": { NodeUrl: "https://ropsten.infura.io/v3/598efca7168947c6a186e2f85b600be1", GravityContractAddress: "0x80C52beF8622cDF368Bf8AaD5ee4A78cB68E2a79", + ChainType: "ethereum", }, - account.Waves.String(): { + "waves": { NodeUrl: "https://nodes-stagenet.wavesnodes.com", GravityContractAddress: "3MfrQBknYJSnifUxD86yMPTSHEhgcPe3NBq", ChainId: "S", + ChainType: "waves", }, }, } @@ -186,6 +188,7 @@ var ( }, } ) + func getPublicIP() (string, error) { ifaces, _ := net.Interfaces() @@ -211,7 +214,6 @@ func getPublicIP() (string, error) { return "", fmt.Errorf("not found valid ip") } - func initLedgerConfig(ctx *cli.Context) error { var err error @@ -333,7 +335,7 @@ func startLedger(ctx *cli.Context) error { if err != nil { return err } - + account.ChainMapper.Assign(privKeysCfg.ChainIds) var genesis config.Genesis err = config.ParseConfig(path.Join(home, GenesisFileName), &genesis) if err != nil { @@ -384,7 +386,7 @@ func startLedger(ctx *cli.Context) error { PubKey: ledgerPubKey, } - gravityApp, err := createApp(db, ledgerValidator, privKeysCfg.TargetChains, ledgerConf, genesis, bootstrap, tConfig.RPC.ListenAddress, sysCtx) + gravityApp, err := createApp(db, ledgerValidator, privKeysCfg, ledgerConf, genesis, bootstrap, tConfig.RPC.ListenAddress, sysCtx) if err != nil { return fmt.Errorf("failed to parse gravity config: %w", err) } @@ -463,37 +465,37 @@ func startLedger(ctx *cli.Context) error { return nil } -func createApp(db *badger.DB, ledgerValidator *account.LedgerValidator, privKeys map[string]config.Key, cfg config.LedgerConfig, genesisCfg config.Genesis, bootstrap string, localHost string, ctx context.Context) (*app.GHApplication, error) { +func createApp(db *badger.DB, ledgerValidator *account.LedgerValidator, privKeys config.Keys, cfg config.LedgerConfig, genesisCfg config.Genesis, bootstrap string, localHost string, ctx context.Context) (*app.GHApplication, error) { + bAdaptors := make(map[account.ChainType]adaptors.IBlockchainAdaptor) for k, v := range cfg.Adapters { + cid, err := account.ChainMapper.ToByte(k) + if err != nil { + fmt.Printf("Chaintype '%s' error: %s", k, err) + continue + } + account.ChainMapper.ApendAdaptor(cid, v.ChainType) + chainType, err := account.ParseChainType(k) if err != nil { return nil, err } - privKey, err := account.StringToPrivKey(privKeys[k].PrivKey, chainType) + privKey, err := account.StringToPrivKey(privKeys.TargetChains[k].PrivKey, chainType) if err != nil { return nil, err } - - var adaptor adaptors.IBlockchainAdaptor - - switch chainType { - case account.Binance: - adaptor, err = adaptors.NewBinanceAdaptor(privKey, v.NodeUrl, ctx, adaptors.WithBinanceGravityContract(v.GravityContractAddress)) - if err != nil { - return nil, err - } - case account.Ethereum: - adaptor, err = adaptors.NewEthereumAdaptor(privKey, v.NodeUrl, ctx, adaptors.WithEthereumGravityContract(v.GravityContractAddress)) - if err != nil { - return nil, err - } - case account.Waves: - adaptor, err = adaptors.NewWavesAdapter(privKey, v.NodeUrl, v.ChainId[0], adaptors.WithWavesGravityContract(v.GravityContractAddress)) - if err != nil { - return nil, err - } + chain := byte(0) + if len(v.ChainId) > 0 { + chain = byte(v.ChainId[0]) + } + opts := adaptors.AdapterOptions{ + "gravityContract": v.GravityContractAddress, + "chainID": chain, + } + adaptor, err := adaptors.NewFactory().CreateAdaptor(v.ChainType, privKey, v.NodeUrl, ctx, opts) + if err != nil { + return nil, err } bAdaptors[chainType] = adaptor diff --git a/cmd/gravity/commands/oracle.go b/cmd/gravity/commands/oracle.go index b19f220..e4f5c65 100755 --- a/cmd/gravity/commands/oracle.go +++ b/cmd/gravity/commands/oracle.go @@ -110,6 +110,7 @@ func startOracle(ctx *cli.Context) error { home := ctx.String(HomeFlag) nebulaIdStr := ctx.Args().First() + zap.L().Sugar().Debugf("Nebule id from args is: [%s]", nebulaIdStr) var cfg config.OracleConfig err = config.ParseConfig(path.Join(home, DefaultNebulaeDir, fmt.Sprintf("%s.json", nebulaIdStr)), &cfg) if err != nil { @@ -121,31 +122,49 @@ func startOracle(ctx *cli.Context) error { if err != nil { return err } - + zap.L().Sugar().Debugf("Chain Ids: %s", privKeysCfg.ChainIds) + account.ChainMapper.Assign(privKeysCfg.ChainIds) + account.ChainMapper.ApendAdaptor(byte(0), "ethereum") // for backward compatibility validatorPrivKey, err := hexutil.Decode(privKeysCfg.Validator.PrivKey) if err != nil { return err } - chainType, err := account.ParseChainType(cfg.ChainType) + chain, err := account.ChainMapper.ToByte(cfg.ChainName) if err != nil { return err } + chainType := account.ChainType(chain) + account.ChainMapper.ApendAdaptor(byte(chainType), cfg.ChainType) - nebulaId, err := account.StringToNebulaId(nebulaIdStr, chainType) + zap.L().Sugar().Debugf("parsing chain type: %s", cfg.ChainType) + cType, err := account.ParseChainType(cfg.ChainType) if err != nil { return err } - oracleSecretKey, err := account.StringToPrivKey(privKeysCfg.TargetChains[chainType.String()].PrivKey, chainType) + zap.L().Sugar().Debugf("Chain type is: %d for nebulae id: %s", chainType, nebulaIdStr) + nebulaId, err := account.StringToNebulaId(nebulaIdStr, cType) if err != nil { return err } + zap.L().Sugar().Debugf("PrivKey is: %s", privKeysCfg.TargetChains[cfg.ChainName].PrivKey) + oracleSecretKey, err := account.StringToPrivKey(privKeysCfg.TargetChains[cfg.ChainName].PrivKey, chainType) + if err != nil { + zap.L().Error(err.Error()) + return err + } + zap.L().Sugar().Debug("Oracle secret key is ", oracleSecretKey) var chainId byte if len(cfg.ChainId) > 0 { chainId = cfg.ChainId[0] } + // chain, err := account.ChainMapper.ToByte(cfg.ChainName) + // if err != nil { + // zap.L().Error(err.Error()) + // return err + // } sysCtx := context.Background() oracleNode, err := node.New( nebulaId, @@ -160,11 +179,13 @@ func startOracle(ctx *cli.Context) error { sysCtx) if err != nil { + zap.L().Error(err.Error()) return err } err = oracleNode.Init() if err != nil { + zap.L().Error(err.Error()) return err } diff --git a/cmd/gravity/gravity b/cmd/gravity/gravity index 38981fc..040edc1 100755 Binary files a/cmd/gravity/gravity and b/cmd/gravity/gravity differ diff --git a/common/account/chain.go b/common/account/chain.go index 4660eca..b05dd6e 100755 --- a/common/account/chain.go +++ b/common/account/chain.go @@ -2,7 +2,6 @@ package account import ( "errors" - "strings" ) type ChainType byte @@ -19,26 +18,30 @@ var ( ) func ParseChainType(chainType string) (ChainType, error) { - switch strings.ToLower(chainType) { - case "bsc": - return Binance, nil - case "ethereum": - return Ethereum, nil - case "waves": - return Waves, nil - default: - return 0, ErrParseChainType - } + val, err := ChainMapper.ToByte(chainType) + return ChainType(val), err + // switch strings.ToLower(chainType) { + // case "bsc": + // return Binance, nil + // case "ethereum": + // return Ethereum, nil + // case "waves": + // return Waves, nil + // default: + // return 0, ErrParseChainType + // } } func (ch ChainType) String() string { - switch ch { - case Ethereum: - return "ethereum" - case Waves: - return "waves" - case Binance: - return "bsc" - default: - return "ethereum" - } + val, _ := ChainMapper.ToStr(byte(ch)) + return val + // switch ch { + // case Ethereum: + // return "ethereum" + // case Waves: + // return "waves" + // case Binance: + // return "bsc" + // default: + // return "ethereum" + // } } diff --git a/common/account/mapper.go b/common/account/mapper.go new file mode 100644 index 0000000..b09870b --- /dev/null +++ b/common/account/mapper.go @@ -0,0 +1,53 @@ +package account + +import ( + "fmt" +) + +type Mapper struct { + strToByte map[string]byte + byteToStr map[byte]string + types map[byte]string +} + +var ChainMapper Mapper + +func (m *Mapper) Assign(arg map[string]ChainType) { + m.strToByte = make(map[string]byte) + m.byteToStr = make(map[byte]string) + m.types = make(map[byte]string) + for k, v := range arg { + m.byteToStr[byte(v)] = k + m.strToByte[k] = byte(v) + } +} +func (m *Mapper) ApendAdaptor(id byte, chaintype string) { + m.types[id] = chaintype +} +func (m *Mapper) ToType(id byte) (byte, error) { + v, ok := m.types[id] + if ok { + v2, ok2 := m.strToByte[v] + if ok2 { + return v2, nil + } + return 0, fmt.Errorf("Chain not found") + + } + return 0, fmt.Errorf("Chain not found") +} +func (m *Mapper) ToStr(k byte) (string, error) { + v, ok := m.byteToStr[k] + if ok { + return v, nil + } + return "", fmt.Errorf("Chain not found") +} + +func (m *Mapper) ToByte(k string) (byte, error) { + v, ok := m.strToByte[k] + if ok { + return v, nil + } + return 0, fmt.Errorf("Chain not found") +} diff --git a/common/account/nebula.go b/common/account/nebula.go index 6da75df..dea004b 100755 --- a/common/account/nebula.go +++ b/common/account/nebula.go @@ -4,6 +4,7 @@ import ( "github.com/btcsuite/btcutil/base58" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/wavesplatform/gowaves/pkg/crypto" + "go.uber.org/zap" ) const ( @@ -16,6 +17,11 @@ const ( type NebulaId [NebulaIdLength]byte func StringToNebulaId(address string, chainType ChainType) (NebulaId, error) { + // cid, err := ChainMapper.ToType(byte(chainType)) + // if err != nil { + // return NebulaId{}, err + // } + // ctype := ChainType(cid) var nebula NebulaId switch chainType { @@ -45,8 +51,16 @@ func BytesToNebulaId(value []byte) NebulaId { } func (id NebulaId) ToString(chainType ChainType) string { - nebula := id.ToBytes(chainType) - switch chainType { + zap.L().Sugar().Debugf("chainType: %d", chainType) + cid, err := ChainMapper.ToType(byte(chainType)) + if err != nil { + zap.L().Error(err.Error()) + return "" + } + ctype := ChainType(cid) + + nebula := id.ToBytes(ctype) + switch ctype { case Ethereum, Binance: return hexutil.Encode(nebula[:]) case Waves: @@ -56,6 +70,13 @@ func (id NebulaId) ToString(chainType ChainType) string { return "" } func (id NebulaId) ToBytes(chainType ChainType) []byte { + // cid, err := ChainMapper.ToType(byte(chainType)) + // if err != nil { + // zap.L().Error(err.Error()) + // return nil + // } + // ctype := ChainType(cid) + switch chainType { case Binance: return id[NebulaIdLength-BSCAddressLength:] diff --git a/common/account/nebula_test.go b/common/account/nebula_test.go new file mode 100644 index 0000000..35c6f1b --- /dev/null +++ b/common/account/nebula_test.go @@ -0,0 +1,35 @@ +package account + +import ( + "testing" +) + +func initMapper() { + ChainMapper.Assign(map[string]ChainType{"ethereum": 0, "heco": 3}) + ChainMapper.ApendAdaptor(3, "ethereum") +} + +func TestNebulaId_ToString(t *testing.T) { + initMapper() + type args struct { + chainType ChainType + } + tests := []struct { + name string + id NebulaId + args args + want string + }{ + {name: "test 1", id: NebulaId{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 197, 129, 50, 32, 60, 168, 223, 237, 90, 125, 47, 37, 42, 170, 140, 77, 22, 32, 239}, + args: args{chainType: ChainType(3)}, want: "", + }, + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.id.ToString(tt.args.chainType); got != tt.want { + t.Errorf("NebulaId.ToString() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/common/account/pubkey.go b/common/account/pubkey.go index ba860ec..de140b2 100755 --- a/common/account/pubkey.go +++ b/common/account/pubkey.go @@ -1,20 +1,28 @@ package account import ( + "fmt" + "github.com/btcsuite/btcutil/base58" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/tendermint/tendermint/crypto/ed25519" wavesplatform "github.com/wavesplatform/go-lib-crypto" "github.com/wavesplatform/gowaves/pkg/crypto" + "go.uber.org/zap" ) type ConsulPubKey ed25519.PubKeyEd25519 type OraclesPubKey [33]byte -func StringToPrivKey(value string, chainType ChainType) ([]byte, error) { +func StringToPrivKey(value string, chain ChainType) ([]byte, error) { var privKey []byte var err error - switch chainType { + cType, err := ChainMapper.ToType(byte(chain)) + if err != nil { + return nil, err + } + zap.L().Sugar().Debugf("Converting string to PrivKey. Chain: %d, privKey: %s", cType, value) + switch ChainType(cType) { case Ethereum, Binance: privKey, err = hexutil.Decode(value) if err != nil { @@ -29,13 +37,18 @@ func StringToPrivKey(value string, chainType ChainType) ([]byte, error) { } privKey = secret.Bytes() } - + zap.L().Sugar().Debug("PrivKey", privKey) return privKey, nil } -func BytesToOraclePubKey(value []byte, chainType ChainType) OraclesPubKey { +func BytesToOraclePubKey(value []byte, chain ChainType) OraclesPubKey { var pubKey OraclesPubKey - switch chainType { + cType, err := ChainMapper.ToType(byte(chain)) + if err != nil { + return pubKey + } + + switch ChainType(cType) { case Ethereum, Binance: copy(pubKey[:], value[0:33]) case Waves: @@ -44,9 +57,13 @@ func BytesToOraclePubKey(value []byte, chainType ChainType) OraclesPubKey { return pubKey } -func (pubKey *OraclesPubKey) ToBytes(chainType ChainType) []byte { +func (pubKey *OraclesPubKey) ToBytes(chain ChainType) []byte { var v []byte - switch chainType { + cType, err := ChainMapper.ToType(byte(chain)) + if err != nil { + return v + } + switch ChainType(cType) { case Ethereum, Binance: v = pubKey[:33] case Waves: @@ -54,9 +71,14 @@ func (pubKey *OraclesPubKey) ToBytes(chainType ChainType) []byte { } return v } -func (pubKey *OraclesPubKey) ToString(chainType ChainType) string { - b := pubKey.ToBytes(chainType) - switch chainType { +func (pubKey *OraclesPubKey) ToString(chain ChainType) string { + b := pubKey.ToBytes(chain) + cType, err := ChainMapper.ToType(byte(chain)) + if err != nil { + fmt.Printf("Error converting OraclePubkey to String\n") + } + + switch ChainType(cType) { case Ethereum, Binance: return hexutil.Encode(b) case Waves: @@ -66,10 +88,15 @@ func (pubKey *OraclesPubKey) ToString(chainType ChainType) string { return "" } -func StringToOraclePubKey(value string, chainType ChainType) (OraclesPubKey, error) { +func StringToOraclePubKey(value string, chain ChainType) (OraclesPubKey, error) { var pubKey []byte var err error - switch chainType { + cType, err := ChainMapper.ToType(byte(chain)) + if err != nil { + return OraclesPubKey{}, nil + } + + switch ChainType(cType) { case Ethereum, Binance: pubKey, err = hexutil.Decode(value) if err != nil { @@ -82,7 +109,7 @@ func StringToOraclePubKey(value string, chainType ChainType) (OraclesPubKey, err return [33]byte{}, err } } - return BytesToOraclePubKey(pubKey, chainType), nil + return BytesToOraclePubKey(pubKey, chain), nil } func HexToValidatorPubKey(hex string) (ConsulPubKey, error) { diff --git a/common/adaptors/ethereum.go b/common/adaptors/ethereum.go index ab970be..5767c22 100755 --- a/common/adaptors/ethereum.go +++ b/common/adaptors/ethereum.go @@ -15,6 +15,7 @@ import ( "github.com/Gravity-Tech/gravity-core/abi/ethereum" "github.com/Gravity-Tech/gravity-core/oracle/extractor" "github.com/gookit/validate" + "go.uber.org/zap" "github.com/ethereum/go-ethereum/common/hexutil" @@ -210,7 +211,9 @@ func (adaptor *EthereumAdaptor) WaitTx(id string, ctx context.Context) error { } func (adaptor *EthereumAdaptor) PubKey() account.OraclesPubKey { pubKey := crypto.CompressPubkey(&adaptor.privKey.PublicKey) - oraclePubKey := account.BytesToOraclePubKey(pubKey[:], account.Ethereum) + var oraclePubKey account.OraclesPubKey + copy(oraclePubKey[:], pubKey[0:33]) + return oraclePubKey } func (adaptor *EthereumAdaptor) ValueType(nebulaId account.NebulaId, ctx context.Context) (abi.ExtractorType, error) { @@ -257,7 +260,8 @@ func (adaptor *EthereumAdaptor) AddPulse(nebulaId account.NebulaId, pulseId uint var s [5][32]byte var v [5]uint8 for _, validator := range validators { - pubKey, err := crypto.DecompressPubkey(validator.ToBytes(account.Ethereum)) + //pubKey, err := crypto.DecompressPubkey(validator.ToBytes(account.Ethereum)) + pubKey, err := crypto.DecompressPubkey(validator[:33]) if err != nil { return "", err } @@ -383,7 +387,8 @@ func (adaptor *EthereumAdaptor) SetOraclesToNebula(nebulaId account.NebulaId, or continue } - pubKey, err := crypto.DecompressPubkey(v.ToBytes(account.Ethereum)) + //pubKey, err := crypto.DecompressPubkey(v.ToBytes(account.Ethereum)) + pubKey, err := crypto.DecompressPubkey(v[:33]) if err != nil { return "", err } @@ -400,7 +405,8 @@ func (adaptor *EthereumAdaptor) SetOraclesToNebula(nebulaId account.NebulaId, or var v [5]uint8 for pubKey, sign := range signs { index := -1 - ethPubKey, err := crypto.DecompressPubkey(pubKey.ToBytes(account.Ethereum)) + // ethPubKey, err := crypto.DecompressPubkey(pubKey.ToBytes(account.Ethereum)) + ethPubKey, err := crypto.DecompressPubkey(pubKey[:33]) if err != nil { return "", err } @@ -434,21 +440,27 @@ func (adaptor *EthereumAdaptor) SetOraclesToNebula(nebulaId account.NebulaId, or return tx.Hash().Hex(), nil } func (adaptor *EthereumAdaptor) SendConsulsToGravityContract(newConsulsAddresses []*account.OraclesPubKey, signs map[account.OraclesPubKey][]byte, round int64, ctx context.Context) (string, error) { + logger, err := zap.NewDevelopment() + consuls, err := adaptor.gravityContract.GetConsuls(nil) if err != nil { + logger.Debug(err.Error()) return "", err } var consulsAddress []common.Address for _, v := range newConsulsAddresses { if v == nil { + logger.Sugar().Debugf("Append common.Address %s", common.Address{}.String()) consulsAddress = append(consulsAddress, common.Address{}) continue } - pubKey, err := crypto.DecompressPubkey(v.ToBytes(account.Ethereum)) + // pubKey, err := crypto.DecompressPubkey(v.ToBytes(account.Ethereum)) + pubKey, err := crypto.DecompressPubkey(v[:33]) if err != nil { return "", err } + logger.Sugar().Debugf("Append consul %s", crypto.PubkeyToAddress(*pubKey).String()) consulsAddress = append(consulsAddress, crypto.PubkeyToAddress(*pubKey)) } @@ -457,8 +469,10 @@ func (adaptor *EthereumAdaptor) SendConsulsToGravityContract(newConsulsAddresses var v [5]uint8 for pubKey, sign := range signs { index := -1 - ethPubKey, err := crypto.DecompressPubkey(pubKey.ToBytes(account.Ethereum)) + // ethPubKey, err := crypto.DecompressPubkey(pubKey.ToBytes(account.Ethereum)) + ethPubKey, err := crypto.DecompressPubkey(pubKey[:33]) if err != nil { + logger.Sugar().Debugf("DecompressPubkey error: %s", crypto.PubkeyToAddress(*ethPubKey).String()) return "", err } validatorAddress := crypto.PubkeyToAddress(*ethPubKey) @@ -482,13 +496,16 @@ func (adaptor *EthereumAdaptor) SendConsulsToGravityContract(newConsulsAddresses s[index] = bytes32S v[index] = sign[64:][0] + 27 } - + // logger.Sugar().Debugf("v:%s r:%s s:%s",string(v[:]),string(r[:]),string(s[:])) tx, err := adaptor.gravityContract.UpdateConsuls(bind.NewKeyedTransactor(adaptor.privKey), consulsAddress, v[:], r[:], s[:], big.NewInt(round)) + if err != nil { + logger.Sugar().Debugf("UpdateConsuls eror: %s", err.Error()) return "", err } - + logger.Sugar().Debugf("Transaction: %s", tx.Hash().String()) return tx.Hash().Hex(), nil + } func (adaptor *EthereumAdaptor) SignConsuls(consulsAddresses []*account.OraclesPubKey, roundId int64) ([]byte, error) { var oraclesAddresses []common.Address @@ -497,7 +514,8 @@ func (adaptor *EthereumAdaptor) SignConsuls(consulsAddresses []*account.OraclesP oraclesAddresses = append(oraclesAddresses, common.Address{}) continue } - pubKey, err := crypto.DecompressPubkey(v.ToBytes(account.Ethereum)) + + pubKey, err := crypto.DecompressPubkey(v[:33]) if err != nil { return nil, err } @@ -522,12 +540,16 @@ func (adaptor *EthereumAdaptor) SignOracles(nebulaId account.NebulaId, oracles [ } var oraclesAddresses []common.Address + zap.L().Sugar().Debug("Ethereum sign oracles") + zap.L().Sync() for _, v := range oracles { if v == nil { oraclesAddresses = append(oraclesAddresses, common.Address{}) continue } - pubKey, err := crypto.DecompressPubkey(v.ToBytes(account.Ethereum)) + //pubKey, err := crypto.DecompressPubkey( v.ToBytes(account.Ethereum)) + pubKey, err := crypto.DecompressPubkey(v[:33]) + if err != nil { return nil, err } diff --git a/common/adaptors/waves.go b/common/adaptors/waves.go index af9f952..394586e 100755 --- a/common/adaptors/waves.go +++ b/common/adaptors/waves.go @@ -12,6 +12,7 @@ import ( "github.com/Gravity-Tech/gravity-core/abi" "github.com/Gravity-Tech/gravity-core/oracle/extractor" "github.com/gookit/validate" + "go.uber.org/zap" "github.com/Gravity-Tech/gravity-core/common/storage" @@ -154,8 +155,10 @@ func (adaptor *WavesAdaptor) Sign(msg []byte) ([]byte, error) { return sig.Bytes(), nil } func (adaptor *WavesAdaptor) PubKey() account.OraclesPubKey { + var oraclePubKey account.OraclesPubKey + zap.L().Sugar().Debug("Waves get PubKey") pubKey := crypto.GeneratePublicKey(adaptor.secret) - oraclePubKey := account.BytesToOraclePubKey(pubKey[:], account.Waves) + copy(oraclePubKey[:], append([]byte{0}, pubKey[0:32]...)) return oraclePubKey } func (adaptor *WavesAdaptor) ValueType(nebulaId account.NebulaId, ctx context.Context) (abi.ExtractorType, error) { @@ -458,6 +461,7 @@ func (adaptor *WavesAdaptor) SetOraclesToNebula(nebulaId account.NebulaId, oracl return tx.ID.String(), nil } func (adaptor *WavesAdaptor) SendConsulsToGravityContract(newConsulsAddresses []*account.OraclesPubKey, signs map[account.OraclesPubKey][]byte, round int64, ctx context.Context) (string, error) { + logger, err := zap.NewDevelopment() var stringSigns [5]string lastRoundState, _, err := adaptor.helper.GetStateByAddressAndKey(adaptor.gravityContract, "last_round", ctx) if err != nil { @@ -467,12 +471,14 @@ func (adaptor *WavesAdaptor) SendConsulsToGravityContract(newConsulsAddresses [] lastRound := uint64(lastRoundState.Value.(float64)) consulsState, _, err := adaptor.helper.GetStateByAddressAndKey(adaptor.gravityContract, fmt.Sprintf("consuls_%d", lastRound), ctx) if err != nil { + logger.Sugar().Debugf("Error: %s", err.Error()) return "", err } consuls := strings.Split(consulsState.Value.(string), ",") for k, v := range signs { pubKey := k.ToString(account.Waves) + logger.Sugar().Debugf("signs: %s", pubKey) index := -1 for i, v := range consuls { @@ -501,9 +507,11 @@ func (adaptor *WavesAdaptor) SendConsulsToGravityContract(newConsulsAddresses [] for _, v := range newConsulsAddresses { if v == nil { + logger.Sugar().Debugf("Append default address") newConsulsString = append(newConsulsString, base58.Encode([]byte{0})) continue } + logger.Sugar().Debugf("Append: %s", base58.Encode(v.ToBytes(account.Waves))) newConsulsString = append(newConsulsString, base58.Encode(v.ToBytes(account.Waves))) } @@ -514,11 +522,13 @@ func (adaptor *WavesAdaptor) SendConsulsToGravityContract(newConsulsAddresses [] asset, err := proto.NewOptionalAssetFromString("WAVES") if err != nil { + logger.Sugar().Debugf("Asset: %s", asset.String()) return "", err } contract, err := proto.NewRecipientFromString(adaptor.gravityContract) if err != nil { + logger.Sugar().Debugf("Recipient: %s", asset.String()) return "", err } @@ -548,13 +558,15 @@ func (adaptor *WavesAdaptor) SendConsulsToGravityContract(newConsulsAddresses [] Timestamp: wclient.NewTimestampFromTime(time.Now()), } + logger.Sugar().Debugf("Sign") err = tx.Sign(adaptor.chainID, adaptor.secret) if err != nil { return "", err } - + logger.Sugar().Debugf("Broadcast") _, err = adaptor.wavesClient.Transactions.Broadcast(ctx, tx) if err != nil { + logger.Sugar().Debugf("Error: %s", err.Error()) return "", err } diff --git a/common/gravity/client.go b/common/gravity/client.go index e361566..aeb6058 100755 --- a/common/gravity/client.go +++ b/common/gravity/client.go @@ -11,6 +11,7 @@ import ( "github.com/Gravity-Tech/gravity-core/ledger/query" "github.com/ethereum/go-ethereum/common/hexutil" rpchttp "github.com/tendermint/tendermint/rpc/client/http" + "go.uber.org/zap" ) const ( @@ -38,6 +39,7 @@ func New(host string) (*Client, error) { func (client *Client) SendTx(transaction *transactions.Transaction) error { txBytes, err := json.Marshal(transaction) + zap.L().Sugar().Debug("Send TX: ", string(txBytes)) if err != nil { return err } @@ -78,16 +80,19 @@ func (client *Client) OraclesByValidator(pubKey account.ConsulPubKey) (storage.O } func (client *Client) OraclesByNebula(nebulaId account.NebulaId, chainType account.ChainType) (storage.OraclesMap, error) { + zap.L().Sugar().Debug("Client oracles by nebula start: ", nebulaId) rq := query.ByNebulaRq{ ChainType: chainType, NebulaAddress: nebulaId.ToString(chainType), } - + zap.L().Sugar().Debug("Client oracles by nebula rq: ", rq) rs, err := client.do(query.OracleByNebulaPath, rq) if err != nil && err != ErrValueNotFound { return nil, err } + zap.L().Sugar().Debug("Client oracles by nebula rs: ", string(rs)) + oracles := make(storage.OraclesMap) if err == ErrValueNotFound { return oracles, nil diff --git a/common/helpers/waves.go b/common/helpers/waves.go index 475ebac..1443059 100755 --- a/common/helpers/waves.go +++ b/common/helpers/waves.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "log" "net/http" "time" @@ -29,7 +30,6 @@ func NewClientHelper(client *client.Client) ClientHelper { func (helper *ClientHelper) GetStateByAddressAndKey(address string, key string, ctx context.Context) (*State, *client.Response, error) { url := fmt.Sprintf("%s/%s/%s?key=%s", helper.client.GetOptions().BaseUrl, GetStateByAddressPath, address, key) - req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, nil, err @@ -42,7 +42,8 @@ func (helper *ClientHelper) GetStateByAddressAndKey(address string, key string, } if len(out) == 0 { - return nil, response, fmt.Errorf("States array is empty") + log.Printf("Waves helper: States array is empty") + return nil, response, nil //fmt.Errorf("States array is empty") } return &out[0], response, nil } diff --git a/common/storage/consuls.go b/common/storage/consuls.go index 32e628c..9d2b93c 100755 --- a/common/storage/consuls.go +++ b/common/storage/consuls.go @@ -15,15 +15,16 @@ type Consul struct { } func formSignConsulsByConsulKey(pubKey account.ConsulPubKey, chainType account.ChainType, roundId int64) []byte { - prefix := "" - switch chainType { - case account.Waves: - prefix = "waves" - case account.Ethereum: - prefix = "ethereum" - case account.Binance: - prefix = "bsc" - } + prefix, _ := account.ChainMapper.ToStr(byte(chainType)) + // prefix := "" + // switch chainType { + // case account.Waves: + // prefix = "waves" + // case account.Ethereum: + // prefix = "ethereum" + // case account.Binance: + // prefix = "bsc" + // } return formKey(string(SignConsulsResultByConsulKey), hexutil.Encode(pubKey[:]), prefix, fmt.Sprintf("%d", roundId)) } diff --git a/config/config.go b/config/config.go index 35b3ddc..fcfc783 100755 --- a/config/config.go +++ b/config/config.go @@ -14,9 +14,11 @@ import ( wavesplatform "github.com/wavesplatform/go-lib-crypto" ) +type ChainIds map[string]account.ChainType type Keys struct { Validator Key TargetChains map[string]Key + ChainIds ChainIds } type Key struct { @@ -52,7 +54,6 @@ func generateWavesPrivKeys(chain byte) (*Key, error) { func GeneratePrivKeys(wavesChainID byte) (*Keys, error) { validatorPrivKey := ed25519.GenPrivKey() - ethPrivKeys, err := generateEthereumBasedPrivKeys() if err != nil { return nil, err @@ -74,9 +75,9 @@ func GeneratePrivKeys(wavesChainID byte) (*Keys, error) { PrivKey: hexutil.Encode(validatorPrivKey[:]), }, TargetChains: map[string]Key{ - account.Ethereum.String(): *ethPrivKeys, - account.Binance.String(): *bscPrivKeys, - account.Waves.String(): *wavesPrivKeys, + "ethereum": *ethPrivKeys, + "bsc": *bscPrivKeys, + "waves": *wavesPrivKeys, }, }, nil } diff --git a/config/ledger.go b/config/ledger.go index 300cbe2..eb71339 100755 --- a/config/ledger.go +++ b/config/ledger.go @@ -2,7 +2,7 @@ package config import ( "encoding/json" - "github.com/Gravity-Tech/gravity-core/common/account" + cfg "github.com/tendermint/tendermint/config" ) @@ -14,6 +14,7 @@ type AdaptorsConfig struct { NodeUrl string ChainId string GravityContractAddress string + ChainType string } type ValidatorDetails struct { @@ -46,8 +47,8 @@ type LedgerConfig struct { RPC *cfg.RPCConfig P2P *cfg.P2PConfig - Details *ValidatorDetails - PublicIP string + Details *ValidatorDetails + PublicIP string Adapters map[string]AdaptorsConfig } @@ -61,13 +62,15 @@ func DefaultLedgerConfig() LedgerConfig { P2P: cfg.DefaultP2PConfig(), Details: (&ValidatorDetails{}).DefaultNew(), Adapters: map[string]AdaptorsConfig{ - account.Ethereum.String(): { + "ethereum": { NodeUrl: "", GravityContractAddress: "", + ChainType: "ethereum", }, - account.Waves.String(): { + "waves": { NodeUrl: "", GravityContractAddress: "", + ChainType: "waves", }, }, } diff --git a/config/oracle.go b/config/oracle.go index 1ffebd5..670a532 100755 --- a/config/oracle.go +++ b/config/oracle.go @@ -5,6 +5,7 @@ type OracleConfig struct { ChainId string GravityNodeUrl string ChainType string + ChainName string ExtractorUrl string BlocksInterval uint64 } diff --git a/ledger/scheduler/process.go b/ledger/scheduler/process.go index 5a75d37..5e81abe 100755 --- a/ledger/scheduler/process.go +++ b/ledger/scheduler/process.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/Gravity-Tech/gravity-core/common/gravity" + "go.uber.org/zap" "github.com/Gravity-Tech/gravity-core/common/account" "github.com/Gravity-Tech/gravity-core/common/transactions" @@ -16,26 +17,32 @@ func (scheduler *Scheduler) process(height int64) { } } func (scheduler *Scheduler) processByHeight(height int64) error { + logger, _ := zap.NewDevelopment() + zap.ReplaceGlobals(logger) roundId := CalculateRound(height) - + logger.Sugar().Debugf("Process by height, round id: %d", roundId) consulInfo, err := scheduler.consulInfo() if err != nil { return err } - + zap.L().Sugar().Debug("Check round") isExist := true if IsRoundStart(height) { + logger.Sugar().Debugf("Round start") roundId := int64(CalculateRound(height) - 1) - + logger.Sugar().Debugf("Round started, id: %d", roundId) index := roundId % int64(consulInfo.TotalCount) if index == int64(consulInfo.ConsulIndex) { for k, v := range scheduler.Adaptors { + lastRound, err := v.LastRound(scheduler.ctx) + logger.Sugar().Debugf("Round: chain: %d, Last round: %d", k, lastRound) if err != nil { return err } if uint64(roundId) <= lastRound { + logger.Sugar().Debugf("roundid <= lastround") continue } @@ -65,8 +72,9 @@ func (scheduler *Scheduler) processByHeight(height int64) error { } } } - + zap.L().Sugar().Debug("Check adaptors") for k, v := range scheduler.Adaptors { + zap.L().Sugar().Debug("Iterate adaptors: ", k) lastRound, err := v.LastRound(scheduler.ctx) if err != nil { return err @@ -86,13 +94,15 @@ func (scheduler *Scheduler) processByHeight(height int64) error { return err } - for k, v := range nebulae { - nebulaId, err := account.StringToNebulaId(k, v.ChainType) + for kn, v := range nebulae { + zap.L().Sugar().Debug("Iterate Nebula: ", kn, v.ChainType) + nebulaId, err := account.StringToNebulaId(kn, k) if err != nil { fmt.Printf("Error:%s\n", err.Error()) continue } - err = scheduler.signOraclesByNebula(roundId, nebulaId, v.ChainType) + + err = scheduler.signOraclesByNebula(roundId, nebulaId, k) if err != nil { continue } @@ -198,6 +208,7 @@ func (scheduler *Scheduler) signConsulsResult(roundId int64, chainType account.C return nil } func (scheduler *Scheduler) signOraclesByNebula(roundId int64, nebulaId account.NebulaId, chainType account.ChainType) error { + zap.L().Sugar().Debug("SignOraclesByNebula chain: ", chainType) _, err := scheduler.client.SignNewOraclesByConsul(scheduler.Ledger.PubKey, chainType, nebulaId, roundId) if err != nil && err != gravity.ErrValueNotFound { return err @@ -220,7 +231,7 @@ func (scheduler *Scheduler) signOraclesByNebula(roundId int64, nebulaId account. for i := len(newOracles); i < OracleCount; i++ { newOracles = append(newOracles, nil) } - + zap.L().Sugar().Debug("SignOracles chain: ", chainType, scheduler.Adaptors) sign, err := scheduler.Adaptors[chainType].SignOracles(nebulaId, newOracles) if err != nil { return err @@ -250,20 +261,26 @@ func (scheduler *Scheduler) signOraclesByNebula(roundId int64, nebulaId account. return nil } func (scheduler *Scheduler) sendConsulsToGravityContract(round int64, chainType account.ChainType) error { + + logger, err := zap.NewDevelopment() + logger.Sugar().Debugf("Send consuls to gravity contract Round: %d, Chain: %d\n", round, chainType) exist, err := scheduler.Adaptors[chainType].RoundExist(round, scheduler.ctx) if err != nil { + logger.Sugar().Debugf("Exist error: %s\n", err.Error()) return err } if exist { + logger.Sugar().Debugf("Round exist") return nil } lastRound, err := scheduler.Adaptors[chainType].LastRound(scheduler.ctx) if err != nil { + logger.Sugar().Debugf("last round error: %s", err.Error()) return err } - + logger.Sugar().Debugf("last round: %d , chain type: %d", lastRound, chainType) if round <= int64(lastRound) { return nil } diff --git a/oracle/node/node.go b/oracle/node/node.go index 8f40f60..348b1eb 100755 --- a/oracle/node/node.go +++ b/oracle/node/node.go @@ -82,28 +82,51 @@ func New(nebulaId account.NebulaId, chainType account.ChainType, if err != nil { return nil, err } + ctype, err := account.ChainMapper.ToType(byte(chainType)) + if err != nil { + zap.L().Error(err.Error()) + return nil, err + } - var adaptor adaptors.IBlockchainAdaptor - switch chainType { - case account.Binance: - adaptor, err = adaptors.NewBinanceAdaptor(oracleSecretKey, targetChainNodeUrl, ctx, adaptors.BinanceAdapterWithGhClient(ghClient)) - if err != nil { - return nil, err - } - case account.Ethereum: - adaptor, err = adaptors.NewEthereumAdaptor(oracleSecretKey, targetChainNodeUrl, ctx, adaptors.EthAdapterWithGhClient(ghClient)) - if err != nil { - return nil, err - } - case account.Waves: - adaptor, err = adaptors.NewWavesAdapter(oracleSecretKey, targetChainNodeUrl, chainId, adaptors.WavesAdapterWithGhClient(ghClient)) - if err != nil { - return nil, err - } + chType, err := account.ChainMapper.ToStr(ctype) + if err != nil { + zap.L().Error(err.Error()) + return nil, err } + opts := adaptors.AdapterOptions{ + "ghClient": ghClient, + "chainID": chainId, + } + zap.L().Sugar().Debugf("Creating adaptor ChType: %s, targetChainNode: %s", chType, targetChainNodeUrl) + adaptor, err := adaptors.NewFactory().CreateAdaptor(chType, oracleSecretKey, targetChainNodeUrl, ctx, opts) + if err != nil { + zap.L().Error(err.Error()) + return nil, err + } + // var adaptor adaptors.IBlockchainAdaptor + // switch chainType { + // case account.Binance: + // adaptor, err = adaptors.NewBinanceAdaptor(oracleSecretKey, targetChainNodeUrl, ctx, adaptors.BinanceAdapterWithGhClient(ghClient)) + // if err != nil { + // return nil, err + // } + // case account.Ethereum: + // adaptor, err = adaptors.NewEthereumAdaptor(oracleSecretKey, targetChainNodeUrl, ctx, adaptors.EthAdapterWithGhClient(ghClient)) + // if err != nil { + // return nil, err + // } + // case account.Waves: + // adaptor, err = adaptors.NewWavesAdapter(oracleSecretKey, targetChainNodeUrl, chainId, adaptors.WavesAdapterWithGhClient(ghClient)) + // if err != nil { + // return nil, err + // } + // } + + zap.L().Sugar().Debugf("NebulaId %s", nebulaId.ToString(account.ChainType(ctype))) exType, err := adaptor.ValueType(nebulaId, ctx) if err != nil { + zap.L().Error(err.Error()) return nil, err } @@ -123,15 +146,22 @@ func New(nebulaId account.NebulaId, chainType account.ChainType, } func (node *Node) Init() error { + zap.L().Sugar().Debugf("Oracles by validator pubKey: %s", node.validator.pubKey) + zap.L().Sync() oraclesByValidator, err := node.gravityClient.OraclesByValidator(node.validator.pubKey) if err != nil { + zap.L().Error(err.Error()) return err } - + zap.L().Sugar().Debug(oraclesByValidator) oracle, ok := oraclesByValidator[node.chainType] + zap.L().Sugar().Debug("Oracle:", oracle) + zap.L().Sugar().Debug("Oracle PubKey:", node.oraclePubKey) + if !ok || oracle != node.oraclePubKey { tx, err := transactions.New(node.validator.pubKey, transactions.AddOracle, node.validator.privKey) if err != nil { + zap.L().Error(err.Error()) return err } @@ -145,22 +175,30 @@ func (node *Node) Init() error { }) err = node.gravityClient.SendTx(tx) if err != nil { + zap.L().Error(err.Error()) return err } zap.L().Sugar().Infof("Add oracle (TXID): %s\n", hexutil.Encode(tx.Id[:])) time.Sleep(time.Duration(5) * time.Second) } + ctype, err := account.ChainMapper.ToType(byte(node.chainType)) + zap.L().Sugar().Debugf("Oracles by Nebula: %s , with chain type: %d\n", node.nebulaId.ToString(account.ChainType(ctype)), node.chainType) oraclesByNebulaKey, err := node.gravityClient.OraclesByNebula(node.nebulaId, node.chainType) if err != nil { + zap.L().Error(err.Error()) return err } + zap.L().Sugar().Debugf(node.oraclePubKey.ToString(node.chainType)) + zap.L().Sugar().Debug("Oracles by nebulakey: ", oraclesByNebulaKey) _, ok = oraclesByNebulaKey[node.oraclePubKey.ToString(node.chainType)] if !ok { + zap.L().Sugar().Debugf("!OK") tx, err := transactions.New(node.validator.pubKey, transactions.AddOracleInNebula, node.validator.privKey) if err != nil { + zap.L().Error(err.Error()) return err } @@ -173,8 +211,10 @@ func (node *Node) Init() error { }, }) + zap.L().Sugar().Debug("Send Tx:", tx) err = node.gravityClient.SendTx(tx) if err != nil { + zap.L().Error(err.Error()) return err } @@ -182,7 +222,7 @@ func (node *Node) Init() error { time.Sleep(time.Duration(5) * time.Second) } - nebulaInfo, err := node.gravityClient.NebulaInfo(node.nebulaId, node.chainType) + nebulaInfo, err := node.gravityClient.NebulaInfo(node.nebulaId, account.ChainType(ctype)) if err == gravity.ErrValueNotFound { return errors.New("nebula not found") } else if err != nil {