github.com/notegio/go-ethereum@v1.9.5-4/cmd/geth/txrelay.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"github.com/ethereum/go-ethereum"
    23  	"github.com/ethereum/go-ethereum/cmd/utils"
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/ethclient"
    26  	"github.com/ethereum/go-ethereum/rlp"
    27  	"github.com/ethereum/go-ethereum/ethdb/cdc"
    28  	"github.com/Shopify/sarama"
    29  	"gopkg.in/urfave/cli.v1"
    30  	"os"
    31  	"time"
    32  	"log"
    33  )
    34  
    35  var (
    36  	txrelayCommand = cli.Command{
    37  		Action:    utils.MigrateFlags(txrelay), // keep track of migration progress
    38  		Name:      "txrelay",
    39  		Usage:     "Broadcast signed transactions from a Kafka topic",
    40  		ArgsUsage: " ",
    41  		Category:  "REPLICA COMMANDS",
    42  		Description: `
    43  Picks up transactions placed on Kafka topics by replicas an relays them to RPC
    44  nodes.
    45  `,
    46  		Flags: []cli.Flag{
    47  			utils.KafkaLogBrokerFlag,
    48  			utils.KafkaTransactionTopicFlag,
    49  			utils.KafkaTransactionConsumerGroupFlag,
    50  		},
    51  	}
    52  )
    53  // replica starts replica node
    54  func txrelay(ctx *cli.Context) error {
    55  	sarama.Logger = log.New(os.Stderr, "[sarama]", 0)
    56  	rpcEndpoint := ctx.Args().First()
    57  	if rpcEndpoint == "" {
    58  		rpcEndpoint = fmt.Sprintf("%s/.ethereum/geth.ipc", os.Getenv("HOME"))
    59  	}
    60  	brokerURL := ctx.GlobalString(utils.KafkaLogBrokerFlag.Name)
    61  	brokers, config := cdc.ParseKafkaURL(brokerURL)
    62  	topic := ctx.GlobalString(utils.KafkaTransactionTopicFlag.Name)
    63  	consumerGroupID := ctx.GlobalString(utils.KafkaTransactionConsumerGroupFlag.Name)
    64  	if err := cdc.CreateTopicIfDoesNotExist(brokerURL, topic); err != nil {
    65  		fmt.Println("Error creating topic")
    66  		return err
    67  	}
    68  	consumerGroup, err := sarama.NewConsumerGroup(brokers, consumerGroupID, config)
    69  	if err != nil {
    70  		fmt.Printf("Looks like %v isn't available\n", brokerURL)
    71  		return err
    72  	}
    73  	defer consumerGroup.Close()
    74  	conn, err := ethclient.Dial(rpcEndpoint)
    75  	if err != nil {
    76  		fmt.Println("Dial Error")
    77  		return err
    78  	}
    79  	for {
    80  		handler := relayConsumerGroup{conn}
    81  		if err := consumerGroup.Consume(context.Background(), []string{topic}, handler); err != nil {
    82  			return err
    83  		}
    84  		time.Sleep(500 * time.Millisecond)
    85  	}
    86  }
    87  
    88  
    89  type relayConsumerGroup struct{
    90  	txs ethereum.TransactionSender
    91  }
    92  
    93  func (relayConsumerGroup) Setup(_ sarama.ConsumerGroupSession) error   { return nil }
    94  func (relayConsumerGroup) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
    95  func (h relayConsumerGroup) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
    96    for msg := range claim.Messages() {
    97  		transaction := &types.Transaction{}
    98  		fmt.Printf("Msg: %v\n", msg)
    99  		if err := rlp.DecodeBytes(msg.Value, transaction); err != nil {
   100  			fmt.Printf("Error decoding: %v\n", err.Error())
   101  		}
   102  		if err := h.txs.SendTransaction(context.Background(), transaction); err != nil {
   103  			fmt.Printf("Error Sending: %v\n", err.Error())
   104  		}
   105      sess.MarkMessage(msg, "")
   106  		fmt.Println("Processed a message\n")
   107    }
   108    return nil
   109  }