Skip to content

Commit

Permalink
Merge pull request #275 from OneOf-Inc/feature/tezos_signer
Browse files Browse the repository at this point in the history
Add tezos signer as a part of the FF stack for the tezos flow
  • Loading branch information
nguyer authored Oct 27, 2023
2 parents 5f7fbf7 + 5e99b8f commit 7dae6c2
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 27 deletions.
10 changes: 10 additions & 0 deletions cmd/init_tezos.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ var initTezosCmd = &cobra.Command{
// By default we turn off multiparty mode while it's not supported yet
initOptions.MultipartyEnabled = false
initOptions.TokenProviders = []string{}
if err := validateTezosFlags(); err != nil {
return err
}
if err := initCommon(args); err != nil {
return err
}
Expand All @@ -56,6 +59,13 @@ var initTezosCmd = &cobra.Command{
},
}

func validateTezosFlags() error {
if initOptions.RemoteNodeURL == "" {
return fmt.Errorf("you must provide 'remote-node-url' flag as local node mode is not supported")
}
return nil
}

func init() {
initTezosCmd.Flags().IntVar(&initOptions.BlockPeriod, "block-period", -1, "Block period in seconds. Default is variable based on selected blockchain provider.")
initTezosCmd.Flags().StringVar(&initOptions.ContractAddress, "contract-address", "", "Do not automatically deploy a contract, instead use a pre-configured address")
Expand Down
9 changes: 0 additions & 9 deletions internal/blockchain/ethereum/ethsigner/ethsigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,6 @@ func (p *EthSignerProvider) getCommand(rpcURL string) string {
}

func (p *EthSignerProvider) GetDockerServiceDefinition(rpcURL string) *docker.ServiceDefinition {
addresses := ""
for i, member := range p.stack.Members {
account := member.Account.(*ethereum.Account)
addresses = addresses + account.Address
if i+1 < len(p.stack.Members) {
addresses = addresses + ","
}
}

return &docker.ServiceDefinition{
ServiceName: "ethsigner",
Service: &docker.Service{
Expand Down
2 changes: 1 addition & 1 deletion internal/blockchain/tezos/connector/connector_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (

type Connector interface {
GetServiceDefinitions(s *types.Stack, dependentServices map[string]string) []*docker.ServiceDefinition
GenerateConfig(stack *types.Stack, member *types.Organization) Config
GenerateConfig(stack *types.Stack, member *types.Organization, signerHostname, rpcURL string) Config
Name() string
Port() int
}
Expand Down
23 changes: 21 additions & 2 deletions internal/blockchain/tezos/connector/tezosconnect/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/hyperledger/firefly-cli/internal/blockchain/tezos/connector"
"github.com/hyperledger/firefly-cli/pkg/types"
Expand All @@ -44,7 +45,13 @@ type APIConfig struct {
}

type ConnectorConfig struct {
URL string `yaml:"url,omitempty"`
Blockchain *BlockchainConfig `yaml:"blockchain,omitempty"`
}

type BlockchainConfig struct {
Network string `yaml:"network,omitempty"`
RPC string `yaml:"rpc,omitempty"`
Signatory string `yaml:"signatory,omitempty"`
}

type PersistenceConfig struct {
Expand Down Expand Up @@ -85,7 +92,7 @@ func (c *Config) WriteConfig(filename string, extraTezosconnectConfigPath string
return nil
}

func (t *Tezosconnect) GenerateConfig(stack *types.Stack, org *types.Organization) connector.Config {
func (t *Tezosconnect) GenerateConfig(stack *types.Stack, org *types.Organization, signerHostname, rpcURL string) connector.Config {
confirmations := new(int)
*confirmations = 0
var metrics *types.MetricsServerConfig
Expand All @@ -104,6 +111,11 @@ func (t *Tezosconnect) GenerateConfig(stack *types.Stack, org *types.Organizatio
metrics = nil
}

network := "mainnet"
if strings.Contains(rpcURL, "ghost") {
network = "ghostnet"
}

return &Config{
Log: &types.LogConfig{
Level: "debug",
Expand All @@ -113,6 +125,13 @@ func (t *Tezosconnect) GenerateConfig(stack *types.Stack, org *types.Organizatio
Address: "0.0.0.0",
PublicURL: fmt.Sprintf("http://127.0.0.1:%v", org.ExposedConnectorPort),
},
Connector: &ConnectorConfig{
Blockchain: &BlockchainConfig{
Network: network,
RPC: rpcURL,
Signatory: fmt.Sprintf("http://%s:6732", signerHostname),
},
},
Persistence: &PersistenceConfig{
LevelDB: &LevelDBConfig{
Path: "/tezosconnect/leveldb",
Expand Down
30 changes: 15 additions & 15 deletions internal/blockchain/tezos/remoterpc/remoterpc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/hyperledger/firefly-cli/internal/blockchain/tezos"
"github.com/hyperledger/firefly-cli/internal/blockchain/tezos/connector"
"github.com/hyperledger/firefly-cli/internal/blockchain/tezos/connector/tezosconnect"
"github.com/hyperledger/firefly-cli/internal/blockchain/tezos/tezossigner"

"github.com/hyperledger/firefly-cli/internal/constants"
"github.com/hyperledger/firefly-cli/internal/docker"
Expand All @@ -35,13 +36,15 @@ type RemoteRPCProvider struct {
ctx context.Context
stack *types.Stack
connector connector.Connector
signer *tezossigner.TezosSignerProvider
}

func NewRemoteRPCProvider(ctx context.Context, stack *types.Stack) *RemoteRPCProvider {
return &RemoteRPCProvider{
ctx: ctx,
stack: stack,
connector: tezosconnect.NewTezosconnect(ctx),
signer: tezossigner.NewTezosSignerProvider(ctx, stack),
}
}

Expand All @@ -50,15 +53,19 @@ func (p *RemoteRPCProvider) WriteConfig(options *types.InitOptions) error {
for i, member := range p.stack.Members {
// Generate the connector config for each member
connectorConfigPath := filepath.Join(initDir, "config", fmt.Sprintf("%s_%v.yaml", p.connector.Name(), i))
if err := p.connector.GenerateConfig(p.stack, member).WriteConfig(connectorConfigPath, options.ExtraConnectorConfigPath); err != nil {
if err := p.connector.GenerateConfig(p.stack, member, "tezossigner", options.RemoteNodeURL).WriteConfig(connectorConfigPath, options.ExtraConnectorConfigPath); err != nil {
return err
}
}

return nil
return p.signer.WriteConfig(options)
}

func (p *RemoteRPCProvider) FirstTimeSetup() error {
if err := p.signer.FirstTimeSetup(); err != nil {
return err
}

for i := range p.stack.Members {
// Copy connector config to each member's volume
connectorConfigPath := filepath.Join(p.stack.StackDir, "runtime", "config", fmt.Sprintf("%s_%v.yaml", p.connector.Name(), i))
Expand All @@ -82,7 +89,11 @@ func (p *RemoteRPCProvider) DeployFireFlyContract() (*types.ContractDeploymentRe
}

func (p *RemoteRPCProvider) GetDockerServiceDefinitions() []*docker.ServiceDefinition {
defs := p.connector.GetServiceDefinitions(p.stack, map[string]string{})
defs := []*docker.ServiceDefinition{
p.signer.GetDockerServiceDefinition(p.stack.RemoteNodeURL),
}
defs = append(defs, p.connector.GetServiceDefinitions(p.stack, map[string]string{"tezossigner": "service_healthy"})...)

return defs
}

Expand Down Expand Up @@ -130,18 +141,7 @@ func (p *RemoteRPCProvider) DeployContract(filename, contractName, instanceName
}

func (p *RemoteRPCProvider) CreateAccount(args []string) (interface{}, error) {
// Currently, accounts (private/public keys) created by FireFly are not involved in the tx signing process.
// Accounts should be created in any key management system supported by the signatory service https://signatory.io/
// And then account address (derivative of the public key) must be provided during each transaction sending via FireFly
address, pk, err := tezos.GenerateAddressAndPrivateKey()
if err != nil {
return nil, err
}

return &tezos.Account{
Address: address,
PrivateKey: pk,
}, nil
return p.signer.CreateAccount(args)
}

func (p *RemoteRPCProvider) GetConnectorName() string {
Expand Down
106 changes: 106 additions & 0 deletions internal/blockchain/tezos/tezossigner/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright © 2021 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tezossigner

import (
"os"
"path/filepath"

"gopkg.in/yaml.v2"
)

type Config struct {
Server ServerConfig `yaml:"server"`
Vaults VaultsConfig `yaml:"vaults"`
Tezos map[string]AccountConfig `yaml:"tezos"`
}

type ServerConfig struct {
Address string `yaml:"address,omitempty"`
UtilityAddress string `yaml:"utility_address,omitempty"`
}

type VaultsConfig struct {
LocalSecret LocalSecretConfig `yaml:"local_secret,omitempty"`
}

type LocalSecretConfig struct {
Driver string `yaml:"driver,omitempty"`
File FileConfig `yaml:"config,omitempty"`
}

type FileConfig struct {
SecretPath string `yaml:"file,omitempty"`
}

type AccountConfig struct {
LogPayloads bool `yaml:"log_payloads"`
Allow AllowedTransactionsConfig `yaml:"allow"`
}

type AllowedTransactionsConfig struct {
Block []string `yaml:"block"`
Endorsement []string `yaml:"endorsement"`
Preendorsement []string `yaml:"preendorsement"`
Generic []string `yaml:"generic"`
}

func (c *Config) WriteConfig(filename string) error {
configYamlBytes, _ := yaml.Marshal(c)
return os.WriteFile(filepath.Join(filename), configYamlBytes, 0755)
}

func GenerateSignerConfig(accountsAddresses []string) *Config {
config := &Config{
Server: ServerConfig{
Address: ":6732",
UtilityAddress: ":9583",
},
Vaults: VaultsConfig{
LocalSecret: LocalSecretConfig{
Driver: "file",
File: FileConfig{
SecretPath: "/etc/secret.json",
},
},
},
}

addresses := map[string]AccountConfig{}
// Give accounts the rights to sign certain types of transactions
for _, address := range accountsAddresses {
addresses[address] = AccountConfig{
LogPayloads: true,
Allow: AllowedTransactionsConfig{
/* List of [activate_account, ballot, delegation, double_baking_evidence, double_endorsement_evidence,
double_preendorsement_evidence, endorsement, failing_noop, origination, preendorsement, proposals,
register_global_constant, reveal, sc_rollup_add_messages, sc_rollup_cement, sc_rollup_originate,
sc_rollup_publish, seed_nonce_revelation, set_deposits_limit, transaction, transfer_ticket,
tx_rollup_commit, tx_rollup_dispatch_tickets, tx_rollup_finalize_commitment, tx_rollup_origination,
tx_rollup_rejection, tx_rollup_remove_commitment, tx_rollup_return_bond, tx_rollup_submit_batch]*/
Generic: []string{
"transaction",
"endorsement",
"reveal",
},
},
}
}
config.Tezos = addresses

return config
}
Loading

0 comments on commit 7dae6c2

Please sign in to comment.