Git Product home page Git Product logo

go-monero's Introduction

go-monero

GoDoc

A multi-platform Go library (and command line interface) for interacting with Monero servers either on clearnet or not (see Tor support), supporting daemon and wallet RPC, p2p commands and ZeroMQ.

Quick start

Command Line Interface

Under cmd/monero you'll find a command line interface that exposes most of the functionality that the library provides.

You can either install it by using Go building from scratch

$ GO111MODULE=on go get github.com/cirocosta/go-monero/cmd/monero

or, using docker

$ docker run utxobr/go-monero:v0.0.5 --help
Daemon, Wallet, and p2p command line monero CLI

Usage:
  monero [command]

Available Commands:
  daemon      execute remote procedure calls against a monero node
  p2p         execute p2p commands against a monero node
  wallet      execute remote procedure calls against a monero wallet rpc server
...

or fetching the binary for your distribution from the releases page. See INSTALL.md for details and examples.

Example

$ monero daemon get-transaction --txn 53c1ef0cff73d12294e3055400826905efc397814aacd7208921a9abfd1f6328
Hash:                   53c1ef0cff73d12294e3055400826905efc397814aacd7208921a9abfd1f6328
Fee (µɱ):               9.13
Fee per kB (µɱ):        6.416691832532602
In/Out:                 1/2
Size:                   1.4 KiB
Public Key:             fbc0ac2c62514f68134f543ce5c4efe51ec55a0952eb188dadf22dccc3c5ffdf
Age:                    20 minutes ago
Block:                  2406735
Confirmations:          4

Outputs

        STEALTH ADDR                                                        AMOUNT IDX
0       574e3a3dda7cde249a81c0a0637ce78999e114dd478479e3e04680ffdcd34c97    35307867
1       7d3e93ecfa2bd8c27f7a2bbd57488c1121924e58591b32e99be42da6ae249e9c    35307868


Input Key Image:        2cd588cbc9214e1b683a8c3f0d7c25b8e61779806051356dee1fac6cf42c0c7e

        RING MEMBER              TXID              BLK        AGE
0       ef729a26d047508fb1       1ed88a49d533e     2342514    2 months ago
1       33351ad5aed5df1c4b       e0782b630670d     2382635    1 month ago
2       df5b27b873dc93e423       a96889571eab7     2397359    1 week ago
3       f30b7e8a36b38d95dc       a3eede407f106     2401095    1 week ago
4       f684f88cd52ef0c39b       de3a7e7b8ced8     2401120    1 week ago
5       96b6addb19dfa8ea78       13c9063f09e05     2402375    6 days ago
6       cd573966c650555377       4639ecf7293c8     2403122    5 days ago
7       b9c6c95c0994266249       04800ff34ee29     2404029    3 days ago
8       c4b4d2549c9a731157       6ebad604e6d81     2405504    1 day ago
9       36516e699ceffb665b       e996d5b951ed1     2406458    9 hours ago
10      91ab8220d7d87e465f       9dd40e49611f1     2406541    6 hours ago

(^ ring member and txid shortened just in this README for brevity sake)

$ monero --help
Daemon, Wallet, and p2p command line monero CLI

Usage:
  monero [command]

Available Commands:
  completion  generate the autocompletion script for the specified shell
  daemon      execute remote procedure calls against a monero node
  help        Help about any command
  p2p         execute p2p commands against a monero node
  wallet      execute remote procedure calls against a monero wallet rpc server

Flags:
  -h, --help   help for monero

Use "monero [command] --help" for more information about a command.
$ monero daemon --help
execute remote procedure calls against a monero node

Usage:
  monero daemon [command]

Available Commands:
  generate-blocks            generate blocks when in regtest mode
  get-alternate-chains       display alternative chains as seen by the node
  get-bans                   all the nodes that have been banned by our node
  get-block                  full block information by either block height or hash
  get-block-count            look up how many blocks are in the longest chain known to the node
  get-block-header           retrieve block(s) header(s) by hash
  get-block-headers-range    retrieve a range of block headers
  get-block-template         generate a block template for mining a new block
  get-coinbase-tx-sum        compute the coinbase amount and the fees amount for n last blocks starting at particular height
  get-connections            information about incoming and outgoing connections.
  get-fee-estimate           estimate fees in atomic units per kB
  get-height                 node's current chain height
  get-info                   general information about the node and the network
  get-last-block-header      header of the last block.
  get-net-stats              networking statistics.
  get-outs                   output details
  get-peer-list              peers lists (white and gray)
  get-public-nodes           all known peers advertising as public nodes
  get-transaction            lookup a transaction, in the pool or not
  get-transaction-pool       information about valid transactions seen by the node but not yet mined into a block, including spent key image info for the txpool
  get-transaction-pool-stats statistics about the transaction pool
  get-version                version of the monero daemon
  hardfork-info              information regarding hard fork voting and readiness.
  mining-status              information about this daemon's mining activity
  on-get-block-hash          find out block's hash by height
  relay-tx                   relay a list of transaction ids
  rpc-access-tracking        statistics about rpc access
  set-bans                   ban another nodes
  start-mining               start mining on the daemon
  stop-mining                stop mining on the daemon
  sync-info                  daemon's chain synchronization info
  zmq                        listen for zmq notifications

Flags:
  -a, --address string             full address of the monero node to reach out to [MONERO_ADDRESS] (default "http://localhost:18081")
  -h, --help                       help for daemon
  -p, --password string            password to supply for rpc auth
      --request-timeout duration   max wait time until considering the request a failure (default 1m0s)
      --shorten-addresses          whether addresses should be shortened when displaying pretty results (default true)
      --tls-ca-cert string         certificate authority to load
      --tls-client-cert string     tls client certificate to use when connecting
      --tls-client-key string      tls client key to use when connecting
  -k, --tls-skip-verify            skip verification of certificate chain and host name
  -u, --username string            name of the user to use during rpc auth
  -v, --verbose                    dump http requests and responses to stderr

Use "monero daemon [command] --help" for more information about a command.

Tor support

Nodes reachable only through the Tor network (hidden services) or proxying traffic through Tor to clearnet is supported despite the lack of a specific flag for specifying the proxy address.

For instance:

$ export HTTP_PROXY="socks5://127.0.0.1:9050" 
$ export MONERO_ADDR=http://rbpgdckle3h3vi4wwwrh75usqtoc5r3alohy7yyx57isynvay63nacyd.onion:18089

$ monero daemon --verbose -a $MONERO_ADDR  get-version --verbose
GET /json_rpc HTTP/1.1
Host: rbpgdckle3h3vi4wwwrh75usqtoc5r3alohy7yyx57isynvay63nacyd.onion:18089
User-Agent: Go-http-client/1.1
Content-Length: 49
Content-Type: application/json
Accept-Encoding: gzip

{"id":"0","jsonrpc":"2.0","method":"get_version"}

HTTP/1.1 200 Ok
Content-Length: 150
Accept-Ranges: bytes
Content-Type: application/json
Last-Modified: Sun, 18 Jul 2021 21:10:57 GMT
Server: Epee-based

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "release": true,
    "status": "OK",
    "untrusted": false,
    "version": 196613
  }
}

Release:        true
Major:          3
Minor:          5

Library

To consume go-monero as a library for your Go project:

$ go get -u -v github.com/cirocosta/go-monero

go-monero exposes two high-level packages: levin and rpc.

The first (levin) is used for interacting with the p2p network via plain TCP (optionally, Tor and I2P can also be used via socks5 proxy - see options).

For instance, to reach out to a node (of a particular address addr) and grab its list of connected peers (information that comes out of the initial handshake):

import (
	"context"
	"fmt"

	"github.com/cirocosta/go-monero/pkg/levin"
)

func ListNodePeers(ctx context.Context, addr string) error {
	// start a client - this will actually establish a TCP `connect()`ion
	// with the other node.
	//
	client, err := levin.NewClient(ctx, addr)
	if err != nil {
		return fmt.Errorf("new client '%s': %w", addr, err)
	}

	// close the connection when done
	//
	defer client.Close()

	// perform the handshake
	//
	pl, err := client.Handshake(ctx)
	if err != nil {
		return fmt.Errorf("handshake: %w", err)
	}

	// list the peers reported back (250 max per monero's implementation)
	//
	for addr := range pl.Peers {
		fmt.Println(addr)
	}

	return nil
}

The second (rpc), is used to communicate with monerod via its HTTP endpoints. Note that not all endpoints/fields are exposed on a given port - if it's being served in a restricted manner, you'll have access to less endpoints than you see in the documentation (https://www.getmonero.org/resources/developer-guides/daemon-rpc.html)

rpc itself is subdivided in two other packages: wallet and daemon, exposing monero-wallet-rpc and monerod RPCs accordingly.

For instance, to get the the height of the main chain:

package daemon_test

import (
	"context"
	"fmt"

	"github.com/cirocosta/go-monero/pkg/rpc"
	"github.com/cirocosta/go-monero/pkg/rpc/daemon"
)

func ExampleGetHeight() {
	ctx := context.Background()
	addr := "http://localhost:18081"

	// instantiate a generic RPC client
	//
	client, err := rpc.NewClient(addr)
	if err != nil {
		panic(fmt.Errorf("new client for '%s': %w", addr, err))
	}

	// instantiate a daemon-specific client and call the `get_height`
	// remote procedure.
	//
	height, err := daemon.NewClient(client).GetHeight(ctx)
	if err != nil {
		panic(fmt.Errorf("get height: %w", err))
	}

	fmt.Printf("height=%d hash=%s\n", height.Height, height.Hash)
}

License

See LICENSE.

Thanks

Big thanks to the Monero community and other projects around cryptonote:

Donate

xmr address

891B5keCnwXN14hA9FoAzGFtaWmcuLjTDT5aRTp65juBLkbNpEhLNfgcBn6aWdGuBqBnSThqMPsGRjWVQadCrhoAT6CnSL3

go-monero's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

go-monero's Issues

cmd/addr: sub-address generation

given that we have included the necessary crypto utils for generating the primary address, we could keep going and add support for subaddresses, which is not very far off.

from monero-project/monero#2056

I imagine we could do so by either extending the interface of Seed with an extra method Subaddress(major, minor uint32) []byte (1) or getting rid of PrimaryAddress() []byte and having only the subaddress one considering major=0,minor=0 the case for PrimaryAddress (2).

imo, (1) is the way to go.


m = Hs(a || i)
M = m*G
D = B + M
C = a*D

being

  • a being the master private view key
  • Hs being Keccak-256 with || representing the concatenation
  • G the base point of he ed25519 curve per cryptonote's paper
  • B being the master public spend key
  • C and D the generated public view and public spend keys that can be composed together to form the final address using the same method as we do for a primary address
  • * being scalar multiplication
  • + being compressed addition

bug: `get_info` unmarshalling

get block count: jsonrpc: submit request: decode: json: cannot unmarshal number 18446744073709551615 into Go struct field GetInfoResult.result.free_space of type int64

from

MONERO_ADDRESS=http://localhost:18089 monero daemon get-info -v
GET /json_rpc HTTP/1.1
Host: localhost:18089
User-Agent: Go-http-client/1.1
Content-Length: 46
Content-Type: application/json
Accept-Encoding: gzip

{"id":"0","jsonrpc":"2.0","method":"get_info"}
HTTP/1.1 200 Ok
Content-Length: 1414
Accept-Ranges: bytes
Content-Type: application/json
Last-Modified: Tue, 03 Aug 2021 20:51:18 GMT
Server: Epee-based

{
  "id": "0",
  "jsonrpc": "2.0",
  "result": {
    "adjusted_time": 1621218384,
    "alt_blocks_count": 0,
    "block_size_limit": 600000,
    "block_size_median": 300000,
    "block_weight_limit": 600000,
    "block_weight_median": 300000,
    "bootstrap_daemon_address": "",
    "busy_syncing": true,
    "credits": 0,
    "cumulative_difficulty": 106481972508558381,
    "cumulative_difficulty_top64": 0,
    "database_size": 112742891520,
    "difficulty": 320281691384,
    "difficulty_top64": 0,
    "free_space": 18446744073709551615,
    "grey_peerlist_size": 0,
    "height": 2362612,
    "height_without_bootstrap": 0,
    "incoming_connections_count": 0,
    "mainnet": true,
    "nettype": "mainnet",
    "offline": false,
    "outgoing_connections_count": 0,
    "rpc_connections_count": 0,
    "stagenet": false,
    "start_time": 0,
    "status": "OK",
    "synchronized": false,
    "target": 120,
    "target_height": 2419228,
    "testnet": false,
    "top_block_hash": "fa5d998295a00c1dc8f8189d1dfbcd3737125f9c4a69fffdfb3d579dcf26a6cb",
    "top_hash": "",
    "tx_count": 13626918,
    "tx_pool_size": 1,
    "untrusted": false,
    "update_available": false,
    "version": "",
    "was_bootstrap_ever_used": false,
    "white_peerlist_size": 0,
    "wide_cumulative_difficulty": "0x17a4cca325b042d",
    "wide_difficulty": "0x4a9246c4f8"
  }
}

consistent units

some of the pretty prints are not really consistent: in some places, we should atomic unics, in others, ɱ. In some places, KiB, in others, KB ... let's make sure these units are consistent

cmd: addr wrapping

for some commands, showing the full address forces the user to make their terminals pretty wide

e.g.

$ monero wallet get-accounts
Total Balance:          390311543905607
Total Unlocked Balance: 390311543905607

        LABEL           TAG     ADDR                                                                                            BALANCE         UNLOCKED BALANCE
0       Primary account         53G25UfvJkvKZpJk3LgKTebdLwcxVQxSrWcwLHJUtWYHPZX6PrwggUN1PisbZG81YkJNVEgpCUMBKE8Dkaqn4CpsPUA91AX 389311543905607 389311543905607
1       test                    72vD5orMS7tVykwtGHcCJVK5zzqL6h3jwb3spQBYR5qQVRcs2Jx1SQzWHozsqQqjWnKrrYE2MLiNu6PwwGQukm6nTk43SXV 1000000000000   1000000000000

requires 160 chars

but, if we were to reduce those addresses to include just the first and last 5 chars, then we get down to ~80

Total Balance:          390311543905607
Total Unlocked Balance: 390311543905607

        LABEL           TAG     ADDR           BALANCE         UNLOCKED BALANCE
0       Primary account         53G25...A91AX  389311543905607 389311543905607
1       test                    72vD5...43SXV  1000000000000   1000000000000

we could include an extra flag passed down to the pretty printers to toggle such behavior, something like --wrap which would be true by default?

improve crawler resiliency over proxies

when using tor, I think we're not really getting the best results (if you look at the errors, you can tell there's a bunch of SOCKS Unknown Error, or some TTLs too).

it might be wise to add some retry logic for some of these errors (or just a very permissive catch-all to try again?)

dns leak when connecting to clearnet nodes via tor proxy

currently, if one decides to use -x to provide the socks5 address of their local tor client and connect to a public node they know by name (say, node.melo.tools), a DNS leak will occur as Go will issue a dns query for node.melo.tools over clearnet ignoring the proxy.

keeping our paranoid hats on, we should provide the ability for folks to specify that the DNS resolution should be carried over tcp passing through our proxy (so that we can resolve, e.g., using dns4torpnlfs2ifuz2s2yf3fc7rdmsbhm6rw75euj35pac6ap25zgqad.onion:443 aka cloudflare's dns over https as a hidden service or somethign else)

tcp read and write timeouts

levin-related: when reading from the tcp sockets that get created for each host, we should enforce some deadlines in order to make sure the opposite of a slow-loris is taking place by a tweaked server

Status of Levin Protocol Implementation

Hello @cirocosta, want to say thank you for your time and effort put into this project.
I'm mostly interested in the Levin Protocol Implementation and have been digging around to try and understand the implementation at hand.
My problem is as follows:

l, err := levin.NewPortableStorageFromBytes(buff) 
if err != nil {
log.Fatal(err)
for x := range l.Entries {
      fmt.Println(x) 
    }
}

Have tested this against a few binary(levin) RPC request/responce messages generated from the official monero RPC client connected to the test network and every time I try to decode them I get panic: unknown ttype b
After analyzing https://github.com/cirocosta/go-monero/blob/master/pkg/levin/portable_storage.go#L204 and comparing to the defined constants BoostSerializeType*, I come to the conclusion that a few methods are still missing for this to be complete, in this case BoostSerializeTypeBool.

Is my assumption correct?
From your point of view and experience can you express in percentage how complete this implementation is ?
Do you have some examples that I can try in case I'm using the library in the wrong way?

Thank you for your time.

dane/tlsa

from monero-project/monero#7089

The current default SSL security policy of the monero-wallet-cli and monero-wallet-rpc is to autodetect whether the daemon RPC has SSL enabled. A root-CA check against the domain is attempted, but only a warning is logged if it fails. The root-CA validation is not mandatory with autodect because an attacker can mitm the connection to downgrade to cleartext. A connection must be SSL mandatory for peer authentication; DANE/TLSA was created to solve the opportunistic encryption failures of SMTP.

...

Proposal 2: Add DANE/TLSA support to the wallet autodetect mode. Its basically completed, for better or worse. Domains can "opt-in" by putting SHA256 or SHA512 fingerprints of their self-signed certificates in DNSSEC records. Domains that do not have this DNSSEC record have no change. The fingerprint could also be cached locally in the wallet data for an improved trust-on-first-use mode. The domain can set an expiry longer than 3 months for $0. The security is based on the TLD, registrar, and ICANN. So not nation-state proof, but average miscreant proof. Hopefully more difficult than root-CA shenanigans, but subjective.

(reference implem: monero-project/monero@af252c0)

https://datatracker.ietf.org/doc/html/rfc6698

tls support

$ monerod  --help | grep ssl
  --rpc-ssl arg (=autodetect)           Enable SSL on RPC connections:
  --rpc-ssl-private-key arg             Path to a PEM format private key
  --rpc-ssl-certificate arg             Path to a PEM format certificate
  --rpc-ssl-ca-certificates arg         Path to file containing concatenated
  --rpc-ssl-allowed-fingerprints arg    List of certificate fingerprints to
  --rpc-ssl-allow-chained               Allow user (via --rpc-ssl-certificates)
  --rpc-ssl-allow-any-cert              Allow any peer certificate

cmd/set-bans: support banning based on a csv file

it'd be great if one could control monerod in a declarative manner when it comes to bans, specially if we consider the monero-operator usecase.

$ monero daemon set-bans -f ./bans.csv

where bans.csv

1.2.3.4,720h

cli: porcelain

at the moment, all we do is output the json representation of the internal structures that we have in go structs.

given that we already have -v to put under stderr the json as it goes through the wire, let's make the cli pretty 💅

handle basic auth

so we can handle

  --rpc-login arg                       Specify username[:password] required

refactor levin package

it does what's supposed to do, but:

  • the types kinda suck
  • it's very specific solely to levin's handshake command

it served us well for creating the tor/i2p/clearnet p2p crawler, but it deserves some TLC

consistently make use of addr shortening

#17 introduced

      --shorten-addresses          whether addresses should be shortened when displaying pretty results (default true)

as a "global" flag for daemon and wallet subcommands, it'd be good to ensure that we retrieve make use of the options formatter in every place where addresses are returned

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.