Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 34 additions & 8 deletions docs/json_rpc_api.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,9 @@ the method name for further details such as parameter and return information.
|Y
|Returns a mix message and its message type by its hash if it is accepted by and currently in the mixpool.
|-
|[[#getmixpairrequests|getmixpairrequests]]
|[[#getmixpoolinfo|getmixpoolinfo]]
|Y
|Returns the current set of mixing pair request messages from the mixpool. WARNING: This is experimental and will very likely be removed in the next version. Do not use!
|Returns the current state of the mixpool including timing of the next mix epoch and pending pair requests.
|-
|[[#getnettotals|getnettotals]]
|Y
Expand Down Expand Up @@ -1549,24 +1549,50 @@ of the best block.

----

====getmixpairrequests====
====getmixpoolinfo====
{|
!Method
|getmixpairrequests
|getmixpoolinfo
|-
!Parameters
|None
|-
!Description
|
: Returns the current set of mixing pair request messages from the mixpool.
: WARNING: This is experimental and will very likely be removed in the next version. Do not use!
: Returns the current state of the mixpool including timing of the next mix epoch and pending pair requests.
|-
!Returns
|<code>(json array of string)</code> hex-encoded mixing pair request messages.
|<code>(json object)</code>
: <code>epoch</code>: <code>(numeric)</code> Duration between mix epochs, in seconds.
: <code>nextepoch</code>: <code>(numeric)</code> Unix timestamp of the next mix epoch.
: <code>pairings</code>: <code>(json array of object)</code> Pending pair requests grouped by mixing compatibility.
:: <code>mixamount</code>: <code>(numeric)</code> Amount of each mixed output, in DCR.
:: <code>scriptclass</code>: <code>(string)</code> Script class of the mixed outputs.
:: <code>txversion</code>: <code>(numeric)</code> Transaction version of the mix transaction.
:: <code>locktime</code>: <code>(numeric)</code> Lock time of the mix transaction.
:: <code>pairingflags</code>: <code>(numeric)</code> Pairing flags of the pair request.
:: <code>pairrequests</code>: <code>(json array of object)</code> The pair requests matching these mixing parameters.
::: <code>hash</code>: <code>(string)</code> Hash of the pair request message.
::: <code>identity</code>: <code>(string)</code> Participant ephemeral public key identity as a hex string.
::: <code>messagecount</code>: <code>(numeric)</code> Number of mixed outputs, each of value mixamount, the pair request is creating.
::: <code>inputvalue</code>: <code>(numeric)</code> Total value of inputs contributed by the pair request, in DCR.
::: <code>utxos</code>: <code>(json array of object)</code> Unspent transaction outputs contributed by the pair request.
:::: <code>txid</code>: <code>(string)</code> The hash of the origin transaction.
:::: <code>vout</code>: <code>(numeric)</code> The index of the output being contributed.
:::: <code>tree</code>: <code>(numeric)</code> The tree of the output being contributed.
:::: <code>amountin</code>: <code>(numeric)</code> The amount of the output, in DCR.
:::: <code>blockheight</code>: <code>(numeric)</code> The height of the block containing the origin transaction.
:::: <code>scriptPubKey</code>: <code>(json object)</code> The public key script used to pay coins.
::::: <code>asm</code>: <code>(string)</code> Disassembly of the script.
::::: <code>hex</code>: <code>(string)</code> Hex-encoded bytes of the script.
::::: <code>reqSigs</code>: <code>(numeric)</code> The number of required signatures.
::::: <code>type</code>: <code>(string)</code> The type of the script (e.g. 'pubkeyhash').
::::: <code>addresses</code>: <code>(json array of string)</code> The Decred addresses associated with this output.
::::: <code>version</code>: <code>(numeric)</code> The script version.
::: <code>expiry</code>: <code>(numeric)</code> Block height at which the pair request expires.
|-
!Example Return
|<code>["a1d1d8c6ffc20a51ad9a5aa093c31bdeb06a0f627af95...",...]</code>
|<code>{"epoch":600,"nextepoch":1751049600,"pairings":[{"mixamount":1,"scriptclass":"P2PKH-secp256k1-v0","txversion":1,"locktime":0,"pairingflags":1,"pairrequests":[{"hash":"a1d1d8c6...","identity":"02d1a...","messagecount":1,"inputvalue":1.2,"utxos":[{"txid":"a1d1d8c6...","vout":0,"tree":0,"amountin":1.2,"blockheight":987000,"scriptPubKey":{"asm":"OP_DUP OP_HASH160 2da3aaa402b110247f08c3ea2300a0567de77a5b OP_EQUALVERIFY OP_CHECKSIG","hex":"76a9142da3aaa402b110247f08c3ea2300a0567de77a5b88ac","reqSigs":1,"type":"pubkeyhash","addresses":["DsV8DxpEUFyZtcAwpWfejmWRpR5FEsrM6Yo"],"version":0}}],"expiry":987654}]}]}</code>
|}

----
Expand Down
3 changes: 3 additions & 0 deletions internal/rpcserver/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,9 @@ type MixPooler interface {

// Message searches the mixing pool for a message by its hash.
Message(query *chainhash.Hash) (mixing.Message, error)

// Epoch returns the duration between mix epochs.
Epoch() time.Duration
}

// TxIndexer provides an interface for retrieving details for a given
Expand Down
148 changes: 106 additions & 42 deletions internal/rpcserver/rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ import (

// API version constants.
const (
jsonrpcSemverMajor = 8
jsonrpcSemverMinor = 3
jsonrpcSemverMajor = 9
jsonrpcSemverMinor = 0
jsonrpcSemverPatch = 0
)

Expand Down Expand Up @@ -210,7 +210,7 @@ var rpcHandlersBeforeInit = map[types.Method]commandHandler{
"getmempoolinfo": handleGetMempoolInfo,
"getmininginfo": handleGetMiningInfo,
"getmixmessage": handleGetMixMessage,
"getmixpairrequests": handleGetMixPairRequests,
"getmixpoolinfo": handleGetMixpoolInfo,
"getnettotals": handleGetNetTotals,
"getnetworkhashps": handleGetNetworkHashPS,
"getnetworkinfo": handleGetNetworkInfo,
Expand Down Expand Up @@ -380,7 +380,7 @@ var rpcLimited = map[string]struct{}{
"getheaders": {},
"getinfo": {},
"getmixmessage": {},
"getmixpairrequests": {},
"getmixpoolinfo": {},
"getnettotals": {},
"getnetworkhashps": {},
"getnetworkinfo": {},
Expand Down Expand Up @@ -1266,6 +1266,38 @@ func createVinList(mtx *wire.MsgTx, isTreasuryEnabled bool) []types.Vin {
return vinList
}

// createScriptPubKeyResult returns a JSON object describing the passed public
// key script information.
func createScriptPubKeyResult(scriptVersion uint16, pkScript []byte,
chainParams *chaincfg.Params) types.ScriptPubKeyResult {

// Disassemble script into single line printable format. The disassembled
// string will contain [error] inline if the script doesn't fully parse, so
// ignore the error here.
script := pkScript
disbuf, _ := txscript.DisasmString(script)

// Attempt to extract known addresses associated with the script.
scriptType, addrs := stdscript.ExtractAddrs(scriptVersion, script,
chainParams)
addresses := make([]string, len(addrs))
for i, addr := range addrs {
addresses[i] = addr.String()
}

// Determine the number of required signatures for known standard types.
reqSigs := stdscript.DetermineRequiredSigs(scriptVersion, script)

return types.ScriptPubKeyResult{
Asm: disbuf,
Hex: hex.EncodeToString(script),
ReqSigs: int32(reqSigs),
Type: scriptType.String(),
Addresses: addresses,
Version: scriptVersion,
}
}

// createVoutList returns a slice of JSON objects for the outputs of the passed
// transaction.
func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params,
Expand Down Expand Up @@ -2666,27 +2698,82 @@ func handleGetMixMessage(_ context.Context, s *Server, cmd any) (any, error) {
return &result, nil
}

// handleGetMixPairRequests implements the getmixpairrequests command,
// returning all current mixing pair requests messages from mixpool.
func handleGetMixPairRequests(_ context.Context, s *Server, _ any) (any, error) {
// handleGetMixpoolInfo implements the getmixpoolinfo command, returning the
// timing of the next mix epoch and the pending pair requests grouped by pairing
// description.
func handleGetMixpoolInfo(_ context.Context, s *Server, _ any) (any, error) {
mp := s.cfg.MixPooler

prs := mp.MixPRs()

buf := new(strings.Builder)
res := make([]string, 0, len(prs))

const pver = wire.MixVersion
// Use a map to group PRs by their pairing description. This is converted to
// a slice for JSON marshalling later.
groups := make(map[string]*types.Pairing)
for _, pr := range prs {
err := pr.BtcEncode(hex.NewEncoder(buf), pver)
pairing, err := pr.Pairing()
if err != nil {
return nil, err
return nil, rpcInternalErr(err, "Failed to generate PR pairing")
}
res = append(res, buf.String())
buf.Reset()

key := string(pairing)
group, ok := groups[key]
if !ok {
group = &types.Pairing{
MixAmount: dcrutil.Amount(pr.MixAmount).ToCoin(),
ScriptClass: pr.ScriptClass,
Comment thread
davecgh marked this conversation as resolved.
TxVersion: pr.TxVersion,
LockTime: pr.LockTime,
PairingFlags: pr.PairingFlags,
Comment thread
jholdstock marked this conversation as resolved.
PairRequests: make([]types.PairRequest, 0, min(len(prs), mixing.MaxPeers)),
}
groups[key] = group
}

// The pair request only provides the hash, index and tree of the UTXO,
// so amountIn, blockHeight and scriptPubKey are retrieved from the
// local UTXO set.
utxos := make([]types.PairRequestUTXO, len(pr.UTXOs))
for i := range pr.UTXOs {
op := pr.UTXOs[i].OutPoint

entry, err := s.cfg.Chain.FetchUtxoEntry(op)
if entry == nil || err != nil {
return nil, rpcNoTxInfoError(&op.Hash)
}

utxos[i].Txid = op.Hash.String()
utxos[i].Vout = op.Index
utxos[i].Tree = op.Tree
utxos[i].AmountIn = dcrutil.Amount(entry.Amount()).ToCoin()
utxos[i].BlockHeight = uint32(entry.BlockHeight())
utxos[i].ScriptPubKey = createScriptPubKeyResult(
entry.ScriptVersion(), entry.PkScript(), s.cfg.ChainParams)
}

group.PairRequests = append(group.PairRequests, types.PairRequest{
Hash: pr.Hash().String(),
Identity: hex.EncodeToString(pr.Identity[:]),
MessageCount: pr.MessageCount,
InputValue: dcrutil.Amount(pr.InputValue).ToCoin(),
UTXOs: utxos,
Expiry: pr.Expiry,
})
}

return res, nil
// Convert map to slice for JSON marshalling.
pairings := make([]types.Pairing, 0, len(groups))
for _, group := range groups {
pairings = append(pairings, *group)
}

epoch := mp.Epoch()
nextEpoch := s.cfg.Clock.Now().Truncate(epoch).Add(epoch)

result := types.GetMixpoolInfoResult{
Epoch: int64(epoch.Seconds()),
NextEpoch: nextEpoch.Unix(),
Pairings: pairings,
}
return &result, nil
}

// handleGetNetTotals implements the getnettotals command.
Expand Down Expand Up @@ -3752,35 +3839,12 @@ func handleGetTxOut(_ context.Context, s *Server, cmd any) (any, error) {
isCoinbase = entry.IsCoinBase()
}

// Disassemble script into single line printable format. The
// disassembled string will contain [error] inline if the script
// doesn't fully parse, so ignore the error here.
script := pkScript
disbuf, _ := txscript.DisasmString(script)

// Attempt to extract known addresses associated with the script.
scriptType, addrs := stdscript.ExtractAddrs(scriptVersion, script,
s.cfg.ChainParams)
addresses := make([]string, len(addrs))
for i, addr := range addrs {
addresses[i] = addr.String()
}

// Determine the number of required signatures for known standard types.
reqSigs := stdscript.DetermineRequiredSigs(scriptVersion, script)

txOutReply := &types.GetTxOutResult{
BestBlock: bestBlockHash,
Confirmations: confirmations,
Value: dcrutil.Amount(value).ToUnit(dcrutil.AmountCoin),
ScriptPubKey: types.ScriptPubKeyResult{
Asm: disbuf,
Hex: hex.EncodeToString(pkScript),
ReqSigs: int32(reqSigs),
Type: scriptType.String(),
Addresses: addresses,
Version: scriptVersion,
},
ScriptPubKey: createScriptPubKeyResult(scriptVersion, pkScript,
s.cfg.ChainParams),
Coinbase: isCoinbase,
}
return txOutReply, nil
Expand Down
Loading