github.com/bcnmy/go-ethereum@v1.10.27/ethdb/remotedb/remotedb.go (about)

     1  // Copyright 2022 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser 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  // The go-ethereum library 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 Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package remotedb implements the key-value database layer based on a remote geth
    18  // node. Under the hood, it utilises the `debug_dbGet` method to implement a
    19  // read-only database.
    20  // There really are no guarantees in this database, since the local geth does not
    21  // exclusive access, but it can be used for basic diagnostics of a remote node.
    22  package remotedb
    23  
    24  import (
    25  	"errors"
    26  	"strings"
    27  
    28  	"github.com/ethereum/go-ethereum/common/hexutil"
    29  	"github.com/ethereum/go-ethereum/ethdb"
    30  	"github.com/ethereum/go-ethereum/rpc"
    31  )
    32  
    33  // Database is a key-value lookup for a remote database via debug_dbGet.
    34  type Database struct {
    35  	remote *rpc.Client
    36  }
    37  
    38  func (db *Database) Has(key []byte) (bool, error) {
    39  	if _, err := db.Get(key); err != nil {
    40  		return false, nil
    41  	}
    42  	return true, nil
    43  }
    44  
    45  func (db *Database) Get(key []byte) ([]byte, error) {
    46  	var resp hexutil.Bytes
    47  	err := db.remote.Call(&resp, "debug_dbGet", hexutil.Bytes(key))
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	return resp, nil
    52  }
    53  
    54  func (db *Database) HasAncient(kind string, number uint64) (bool, error) {
    55  	if _, err := db.Ancient(kind, number); err != nil {
    56  		return false, nil
    57  	}
    58  	return true, nil
    59  }
    60  
    61  func (db *Database) Ancient(kind string, number uint64) ([]byte, error) {
    62  	var resp hexutil.Bytes
    63  	err := db.remote.Call(&resp, "debug_dbAncient", kind, number)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	return resp, nil
    68  }
    69  
    70  func (db *Database) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) {
    71  	panic("not supported")
    72  }
    73  
    74  func (db *Database) Ancients() (uint64, error) {
    75  	var resp uint64
    76  	err := db.remote.Call(&resp, "debug_dbAncients")
    77  	return resp, err
    78  }
    79  
    80  func (db *Database) Tail() (uint64, error) {
    81  	panic("not supported")
    82  }
    83  
    84  func (db *Database) AncientSize(kind string) (uint64, error) {
    85  	panic("not supported")
    86  }
    87  
    88  func (db *Database) ReadAncients(fn func(op ethdb.AncientReaderOp) error) (err error) {
    89  	return fn(db)
    90  }
    91  
    92  func (db *Database) Put(key []byte, value []byte) error {
    93  	panic("not supported")
    94  }
    95  
    96  func (db *Database) Delete(key []byte) error {
    97  	panic("not supported")
    98  }
    99  
   100  func (db *Database) ModifyAncients(f func(ethdb.AncientWriteOp) error) (int64, error) {
   101  	panic("not supported")
   102  }
   103  
   104  func (db *Database) TruncateHead(n uint64) error {
   105  	panic("not supported")
   106  }
   107  
   108  func (db *Database) TruncateTail(n uint64) error {
   109  	panic("not supported")
   110  }
   111  
   112  func (db *Database) Sync() error {
   113  	return nil
   114  }
   115  
   116  func (db *Database) MigrateTable(s string, f func([]byte) ([]byte, error)) error {
   117  	panic("not supported")
   118  }
   119  
   120  func (db *Database) NewBatch() ethdb.Batch {
   121  	panic("not supported")
   122  }
   123  
   124  func (db *Database) NewBatchWithSize(size int) ethdb.Batch {
   125  	panic("not supported")
   126  }
   127  
   128  func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
   129  	panic("not supported")
   130  }
   131  
   132  func (db *Database) Stat(property string) (string, error) {
   133  	panic("not supported")
   134  }
   135  
   136  func (db *Database) AncientDatadir() (string, error) {
   137  	panic("not supported")
   138  }
   139  
   140  func (db *Database) Compact(start []byte, limit []byte) error {
   141  	return nil
   142  }
   143  
   144  func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
   145  	panic("not supported")
   146  }
   147  
   148  func (db *Database) Close() error {
   149  	db.remote.Close()
   150  	return nil
   151  }
   152  
   153  func dialRPC(endpoint string) (*rpc.Client, error) {
   154  	if endpoint == "" {
   155  		return nil, errors.New("endpoint must be specified")
   156  	}
   157  	if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
   158  		// Backwards compatibility with geth < 1.5 which required
   159  		// these prefixes.
   160  		endpoint = endpoint[4:]
   161  	}
   162  	return rpc.Dial(endpoint)
   163  }
   164  
   165  func New(endpoint string) (ethdb.Database, error) {
   166  	client, err := dialRPC(endpoint)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	return &Database{
   171  		remote: client,
   172  	}, nil
   173  }