2014-10-21 19:42:44 +00:00
|
|
|
package namecoin
|
|
|
|
|
|
|
|
// btcjson had to be modified a bit to get correct error reporting.
|
2014-10-17 16:23:51 +00:00
|
|
|
import "github.com/hlandauf/btcjson"
|
2015-09-02 07:49:40 +00:00
|
|
|
import "gopkg.in/hlandau/madns.v1/merr"
|
2014-12-16 10:55:42 +00:00
|
|
|
import extratypes "github.com/hlandau/ncbtcjsontypes"
|
2014-10-21 19:42:44 +00:00
|
|
|
|
2014-10-13 22:26:02 +00:00
|
|
|
import "fmt"
|
2014-12-06 09:30:14 +00:00
|
|
|
import "expvar"
|
2014-12-16 22:49:12 +00:00
|
|
|
import "sync/atomic"
|
2014-12-06 09:30:14 +00:00
|
|
|
|
|
|
|
var cQueryCalls = expvar.NewInt("ncdns.namecoin.numQueryCalls")
|
|
|
|
var cSyncCalls = expvar.NewInt("ncdns.namecoin.numSyncCalls")
|
|
|
|
var cFilterCalls = expvar.NewInt("ncdns.namecoin.numFilterCalls")
|
|
|
|
var cCurHeightCalls = expvar.NewInt("ncdns.namecoin.numCurHeightCalls")
|
2014-10-13 22:26:02 +00:00
|
|
|
|
2014-10-21 19:42:44 +00:00
|
|
|
// Used for generating IDs for JSON-RPC requests.
|
2014-11-13 11:11:51 +00:00
|
|
|
var idCounter int32
|
2014-10-13 22:26:02 +00:00
|
|
|
|
|
|
|
func newID() int32 {
|
2014-11-13 10:55:51 +00:00
|
|
|
return atomic.AddInt32(&idCounter, 1)
|
2014-10-13 22:26:02 +00:00
|
|
|
}
|
|
|
|
|
2014-10-21 20:30:19 +00:00
|
|
|
// Used to query a Namecoin JSON-RPC interface. Initialize the struct with a
|
|
|
|
// username, password, and address (hostname:port).
|
2014-11-13 11:11:51 +00:00
|
|
|
type Conn struct {
|
2014-11-13 10:55:51 +00:00
|
|
|
Username string
|
|
|
|
Password string
|
|
|
|
Server string
|
2014-10-13 22:26:02 +00:00
|
|
|
}
|
|
|
|
|
2014-10-21 20:30:19 +00:00
|
|
|
// Query the Namecoin daemon for a Namecoin domain (e.g. d/example).
|
|
|
|
// If the domain exists, returns the value stored in Namecoin, which should be JSON.
|
|
|
|
// Note that this will return domain data even if the domain is expired.
|
2014-11-13 11:11:51 +00:00
|
|
|
func (nc *Conn) Query(name string) (v string, err error) {
|
2014-12-06 09:30:14 +00:00
|
|
|
cQueryCalls.Add(1)
|
|
|
|
|
2014-11-13 10:55:51 +00:00
|
|
|
cmd, err := extratypes.NewNameShowCmd(newID(), name)
|
|
|
|
if err != nil {
|
|
|
|
//log.Info("NC NEWCMD ", err)
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
r, err := btcjson.RpcSend(nc.Username, nc.Password, nc.Server, cmd)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.Error != nil {
|
|
|
|
//log.Info("RPC error: ", r.Error)
|
|
|
|
if r.Error.Code == -4 {
|
|
|
|
return "", merr.ErrNoSuchDomain
|
|
|
|
}
|
|
|
|
return "", r.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.Result == nil {
|
|
|
|
//log.Info("NC NILRESULT")
|
|
|
|
return "", fmt.Errorf("got nil result")
|
|
|
|
}
|
|
|
|
|
|
|
|
if nsr, ok := r.Result.(*extratypes.NameShowReply); ok {
|
|
|
|
//log.Info("NC OK")
|
|
|
|
return nsr.Value, nil
|
|
|
|
}
|
2014-11-13 11:11:51 +00:00
|
|
|
|
|
|
|
//log.Info("NC BADREPLY")
|
|
|
|
return "", fmt.Errorf("bad reply")
|
2014-10-13 22:26:02 +00:00
|
|
|
}
|
2014-10-17 16:08:53 +00:00
|
|
|
|
2014-11-25 13:50:51 +00:00
|
|
|
var ErrSyncNoSuchBlock = fmt.Errorf("no block exists with given hash")
|
|
|
|
|
|
|
|
const rpcInvalidAddressOrKey = -5
|
|
|
|
|
|
|
|
func (nc *Conn) Sync(hash string, count int, wait bool) ([]extratypes.NameSyncEvent, error) {
|
2014-12-06 09:30:14 +00:00
|
|
|
cSyncCalls.Add(1)
|
|
|
|
|
2014-11-25 13:50:51 +00:00
|
|
|
cmd, err := extratypes.NewNameSyncCmd(newID(), hash, count, wait)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
r, err := btcjson.RpcSend(nc.Username, nc.Password, nc.Server, cmd)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.Error != nil {
|
|
|
|
if r.Error.Code == rpcInvalidAddressOrKey {
|
|
|
|
return nil, ErrSyncNoSuchBlock
|
|
|
|
}
|
|
|
|
return nil, r.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.Result == nil {
|
|
|
|
return nil, fmt.Errorf("got nil result")
|
|
|
|
}
|
|
|
|
|
|
|
|
if nsr, ok := r.Result.(extratypes.NameSyncReply); ok {
|
|
|
|
return []extratypes.NameSyncEvent(nsr), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("bad reply")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (nc *Conn) CurHeight() (int, error) {
|
2014-12-06 09:30:14 +00:00
|
|
|
cCurHeightCalls.Add(1)
|
|
|
|
|
2014-11-25 13:50:51 +00:00
|
|
|
cmd, err := btcjson.NewGetInfoCmd(newID())
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
r, err := btcjson.RpcSend(nc.Username, nc.Password, nc.Server, cmd)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.Error != nil {
|
|
|
|
return 0, r.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.Result == nil {
|
|
|
|
return 0, fmt.Errorf("got nil result")
|
|
|
|
}
|
|
|
|
|
|
|
|
if rep, ok := r.Result.(*btcjson.InfoResult); ok {
|
|
|
|
return int(rep.Blocks), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0, fmt.Errorf("bad reply")
|
|
|
|
}
|
|
|
|
|
2014-12-01 00:44:06 +00:00
|
|
|
func (nc *Conn) Filter(regexp string, maxage, from, count int) (names []extratypes.NameFilterItem, err error) {
|
2014-12-06 09:30:14 +00:00
|
|
|
cFilterCalls.Add(1)
|
|
|
|
|
2014-12-01 00:44:06 +00:00
|
|
|
cmd, err := extratypes.NewNameFilterCmd(newID(), regexp, maxage, from, count)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
r, err := btcjson.RpcSend(nc.Username, nc.Password, nc.Server, cmd)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.Error != nil {
|
|
|
|
return nil, r.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.Result == nil {
|
|
|
|
return nil, fmt.Errorf("got nil result")
|
|
|
|
}
|
|
|
|
|
|
|
|
if nsr, ok := r.Result.(extratypes.NameFilterReply); ok {
|
|
|
|
return []extratypes.NameFilterItem(nsr), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("bad reply")
|
|
|
|
}
|
|
|
|
|
2014-11-11 10:35:48 +00:00
|
|
|
// © 2014 Hugo Landau <hlandau@devever.net> GPLv3 or later
|