kopia lustrzana https://github.com/bugout-dev/moonstream
				
				
				
			
		
			
				
	
	
		
			248 wiersze
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			248 wiersze
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
| package cmd
 | |
| 
 | |
| import (
 | |
| 	"database/sql"
 | |
| 	"fmt"
 | |
| 	"math/big"
 | |
| 
 | |
| 	"github.com/bugout-dev/moonstream/crawlers/ldb/configs"
 | |
| 
 | |
| 	"github.com/ethereum/go-ethereum/cmd/utils"
 | |
| 	"github.com/ethereum/go-ethereum/common"
 | |
| 	"github.com/ethereum/go-ethereum/core/rawdb"
 | |
| 	"github.com/ethereum/go-ethereum/core/types"
 | |
| 	"github.com/ethereum/go-ethereum/eth/ethconfig"
 | |
| 	"github.com/ethereum/go-ethereum/node"
 | |
| 	_ "github.com/lib/pq"
 | |
| 	"gopkg.in/urfave/cli.v1"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	localConnections *LocalConnections
 | |
| )
 | |
| 
 | |
| // Modified lightweight go-ethereum function
 | |
| // Source: github.com/ethereum/go-ethereum/cmd/geth/config.go
 | |
| func defaultNodeConfig() node.Config {
 | |
| 	cfg := node.DefaultConfig
 | |
| 	cfg.Name = "geth"
 | |
| 	return cfg
 | |
| }
 | |
| 
 | |
| // Establish connection with blockchain
 | |
| func setLocalChain(ctx *cli.Context) error {
 | |
| 	cfg := gethConfig{
 | |
| 		Eth:  ethconfig.Defaults,
 | |
| 		Node: defaultNodeConfig(),
 | |
| 	}
 | |
| 
 | |
| 	// Apply flags
 | |
| 	utils.SetNodeConfig(ctx, &cfg.Node)
 | |
| 	stack, err := node.New(&cfg.Node)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("Failed to create the protocol stack: %v", err)
 | |
| 	}
 | |
| 	localConnections.Stack = stack
 | |
| 
 | |
| 	utils.SetEthConfig(ctx, stack, &cfg.Eth)
 | |
| 
 | |
| 	chain, chainDB := utils.MakeChain(ctx, stack)
 | |
| 	localConnections.Chain = chain
 | |
| 	localConnections.ChainDB = chainDB
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Establish connection with database
 | |
| func setDatabase() error {
 | |
| 	db, err := sql.Open("postgres", configs.MOONSTREAM_DB_URI)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("DSN parse error or another database initialization error: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Set the maximum number of concurrently idle connections,
 | |
| 	// by default sql.DB allows a maximum of 2 idle connections.
 | |
| 	db.SetMaxIdleConns(configs.MOONSTREAM_DB_MAX_IDLE_CONNS)
 | |
| 
 | |
| 	// Set the maximum lifetime of a connection.
 | |
| 	// Longer lifetime increase memory usage.
 | |
| 	db.SetConnMaxLifetime(configs.MOONSTREAM_DB_CONN_MAX_LIFETIME)
 | |
| 
 | |
| 	localConnections.Database = db
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Retrive block from blockchain
 | |
| func (lc *LocalConnections) getChainBlock(number uint64) (*types.Block, error) {
 | |
| 	block := lc.Chain.GetBlockByNumber(number)
 | |
| 	if block == nil {
 | |
| 		return nil, fmt.Errorf("Not found %d block in chain", number)
 | |
| 	}
 | |
| 	return block, nil
 | |
| }
 | |
| 
 | |
| // Retrive block transactions from blockchain
 | |
| func (lc *LocalConnections) getChainTxs(blockHash common.Hash, number uint64) []*types.Transaction {
 | |
| 	var transactions []*types.Transaction
 | |
| 	body := rawdb.ReadBody(lc.ChainDB, blockHash, number)
 | |
| 	for _, tx := range body.Transactions {
 | |
| 		transactions = append(transactions, tx)
 | |
| 	}
 | |
| 
 | |
| 	return transactions
 | |
| }
 | |
| 
 | |
| // Retrive block with transactions from database
 | |
| func (lc *LocalConnections) getDatabaseBlockTxs(blockchain, blockHash string) (LightBlock, error) {
 | |
| 	var lBlock LightBlock
 | |
| 	var txs []LightTransaction
 | |
| 	query := fmt.Sprintf(
 | |
| 		`SELECT 
 | |
| 			%s_blocks.hash,
 | |
| 			%s_blocks.block_number,
 | |
| 			%s_transactions.hash
 | |
| 		FROM %s_blocks
 | |
| 			LEFT JOIN %s_transactions ON %s_blocks.block_number = %s_transactions.block_number
 | |
| 		WHERE %s_blocks.hash = '%s';`,
 | |
| 		blockchain, blockchain, blockchain, blockchain, blockchain, blockchain, blockchain, blockchain, blockHash,
 | |
| 	)
 | |
| 	rows, err := lc.Database.Query(query)
 | |
| 	if err != nil {
 | |
| 		return lBlock, fmt.Errorf("An error occurred during sql operation: %v", err)
 | |
| 	}
 | |
| 	defer rows.Close()
 | |
| 
 | |
| 	for rows.Next() {
 | |
| 		var blockHash, blockNumberStr, txHash sql.NullString
 | |
| 		err := rows.Scan(&blockHash, &blockNumberStr, &txHash)
 | |
| 		if err != nil {
 | |
| 			return lBlock, fmt.Errorf("An error occurred during sql operation: %v", err)
 | |
| 		}
 | |
| 
 | |
| 		var lTx LightTransaction
 | |
| 		if txHash.Valid != false {
 | |
| 			lTx = LightTransaction{
 | |
| 				Hash: txHash.String,
 | |
| 			}
 | |
| 			txs = append(lBlock.Transactions, lTx)
 | |
| 		}
 | |
| 
 | |
| 		blockNumber := new(big.Int)
 | |
| 		blockNumber, ok := blockNumber.SetString(blockNumberStr.String, 10)
 | |
| 		if !ok {
 | |
| 			return lBlock, fmt.Errorf("Unable to parse block number")
 | |
| 		}
 | |
| 
 | |
| 		lBlock = LightBlock{
 | |
| 			Hash:         blockHash.String,
 | |
| 			Number:       blockNumber,
 | |
| 			Transactions: txs,
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return lBlock, nil
 | |
| }
 | |
| 
 | |
| // Write block with transactions to database
 | |
| func (lc *LocalConnections) writeDatabaseBlockTxs(
 | |
| 	blockchain string, block *types.Block, txs []*types.Transaction, td *big.Int,
 | |
| ) error {
 | |
| 	// block.extraData doesn't exist at Polygon mainnet
 | |
| 	var extraData interface{}
 | |
| 	if block.Extra() == nil {
 | |
| 		extraData = "NULL"
 | |
| 	} else {
 | |
| 		extraData = fmt.Sprintf("'0x%x'", block.Extra())
 | |
| 	}
 | |
| 
 | |
| 	// For support of blocks before London hardfork
 | |
| 	var baseFee interface{}
 | |
| 	if block.BaseFee() == nil {
 | |
| 		baseFee = "NULL"
 | |
| 	} else {
 | |
| 		baseFee = block.BaseFee()
 | |
| 	}
 | |
| 
 | |
| 	blockQuery := fmt.Sprintf(
 | |
| 		`INSERT INTO %s_blocks (
 | |
| 			block_number,
 | |
| 			difficulty,
 | |
| 			extra_data,
 | |
| 			gas_limit,
 | |
| 			gas_used,
 | |
| 			base_fee_per_gas,
 | |
| 			hash,
 | |
| 			logs_bloom,
 | |
| 			miner,
 | |
| 			nonce,
 | |
| 			parent_hash,
 | |
| 			receipt_root,
 | |
| 			uncles,
 | |
| 			size,
 | |
| 			state_root,
 | |
| 			timestamp,
 | |
| 			total_difficulty,
 | |
| 			transactions_root
 | |
| 		) VALUES (%d, %d, %v, %d, %d, %v, '%s', '0x%x', '%s', '0x%x', '0x%x', '0x%x', '0x%x', %f, '0x%x', %d, %d, '0x%x');`,
 | |
| 		blockchain,
 | |
| 		block.Number(),
 | |
| 		block.Difficulty(),
 | |
| 		extraData,
 | |
| 		block.GasLimit(),
 | |
| 		block.GasUsed(),
 | |
| 		baseFee,
 | |
| 		block.Hash(),
 | |
| 		block.Bloom(),
 | |
| 		block.Coinbase(),
 | |
| 		block.Nonce(),
 | |
| 		block.ParentHash(),
 | |
| 		block.ReceiptHash(),
 | |
| 		block.UncleHash(),
 | |
| 		block.Size(),
 | |
| 		block.Root(),
 | |
| 		block.Time(),
 | |
| 		td,
 | |
| 		block.TxHash(),
 | |
| 	)
 | |
| 	_, err := lc.Database.Exec(blockQuery)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("An error occurred during sql operation: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// for _, tx := range(txs) {
 | |
| 	// 	txQuery := fmt.Sprintf(
 | |
| 	// 		`INSERT INTO %s_transactions (
 | |
| 	// 			hash,
 | |
| 	// 			block_number,
 | |
| 	// 			from_address,
 | |
| 	// 			to_address,
 | |
| 	// 			gas,
 | |
| 	// 			gas_price,
 | |
| 	// 			max_fee_per_gas,
 | |
| 	// 			max_priority_fee_per_gas,
 | |
| 	// 			input,
 | |
| 	// 			nonce,
 | |
| 	// 			transaction_index,
 | |
| 	// 			transaction_type,
 | |
| 	// 			value
 | |
| 	// 		) VALUES ('%s', %d, '%s', '%s', %d, %d, );`,
 | |
| 	// 		blockchain,
 | |
| 	// 		tx.Hash(),
 | |
| 	// 		block.Number(),
 | |
| 	// 		tx.from,
 | |
| 	// 		tx.To(),
 | |
| 	// 		tx.Gas(),
 | |
| 	// 		tx.GasPrice(),
 | |
| 	// 		"max_fee",
 | |
| 	// 		"max_prior",
 | |
| 	// 		tx.input,
 | |
| 	// 		tx.Nonce(),
 | |
| 	// 		"tx_index",
 | |
| 	// 		tx.Type(),
 | |
| 	// 		tx.Value(),
 | |
| 	// 	)
 | |
| 	// }
 | |
| 	return nil
 | |
| }
 |