From 7b6676680c36bf1c66f5a6fa45649a5aa4819500 Mon Sep 17 00:00:00 2001 From: "vracek@protonmail.com" Date: Thu, 7 Jun 2018 10:00:32 -0600 Subject: [PATCH 1/5] legacyrpc: add hashContracts, createContractArray, and lexiSort --- internal/rpc/jsonrpc/methods.go | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/internal/rpc/jsonrpc/methods.go b/internal/rpc/jsonrpc/methods.go index 6c464cfcc..7c052e2f2 100644 --- a/internal/rpc/jsonrpc/methods.go +++ b/internal/rpc/jsonrpc/methods.go @@ -8,10 +8,14 @@ package jsonrpc import ( "bytes" "context" + "crypto/hmac" + "crypto/sha512" "encoding/base64" "encoding/binary" "encoding/hex" "encoding/json" + "hash" + "io/ioutil" "math/big" "sort" "strconv" @@ -832,6 +836,40 @@ func difficultyRatio(bits uint32, params *chaincfg.Params) float64 { return ratio } +func hashContracts(contractArray [][]byte, contractAmounts int) [][]byte { + + var hashedContracts []hash.Hash + hashedContractsByte := make([][]byte, contractAmounts) + for i := range contractArray { + hashedContracts[i] = hmac.New(sha512.New, contractArray[i]) + hashedContractsByte[i] = hashedContracts[i].Sum(nil) + } + + return hashedContractsByte +} + +func createContractArray(filePaths []string) [][]byte { + contractArray := make([][]byte, len(filePaths)) + + for i := range filePaths { + contractArray[i], _ = ioutil.ReadFile(filePaths[i]) + } + + return contractArray +} + +func lexiSort(hashedContracts [][]byte) [][]byte { + for i := range hashedContracts { + for j := range hashedContracts { + if hashedContracts[i][j] > hashedContracts[i][j+1] { + hashedContracts[i], hashedContracts[i+1] = hashedContracts[i+1], hashedContracts[i] + } + } + } + + return hashedContracts +} + // getInfo handles a getinfo request by returning a structure containing // information about the current state of the wallet. func (s *Server) getInfo(ctx context.Context, icmd interface{}) (interface{}, error) { From 59c5bcc21e943b54bda9cf773c0954f1b1570a37 Mon Sep 17 00:00:00 2001 From: "vracek@protonmail.com" Date: Thu, 7 Jun 2018 10:07:04 -0600 Subject: [PATCH 2/5] legacyrpc: add getContractHash method --- Gopkg.lock | 221 ++++++++++++++++++++++++++++++++ internal/rpc/jsonrpc/methods.go | 132 +++++++++++++++++-- rpc/legacyrpc/contracts.go | 107 ++++++++++++++++ rpc/legacyrpc/contracts_test.go | 29 +++++ 4 files changed, 476 insertions(+), 13 deletions(-) create mode 100644 Gopkg.lock create mode 100644 rpc/legacyrpc/contracts.go create mode 100644 rpc/legacyrpc/contracts_test.go diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 000000000..a0d9d1a9c --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,221 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/aead/siphash" + packages = ["."] + revision = "e404fcfc888570cadd1610538e2dbc89f66af814" + +[[projects]] + branch = "master" + name = "github.com/agl/ed25519" + packages = [ + ".", + "edwards25519" + ] + revision = "5312a61534124124185d41f09206b9fef1d88403" + +[[projects]] + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" + version = "v1.3.1" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/go-socks" + packages = ["socks"] + revision = "4720035b7bfd2a9bb130b1c184f8bbe41b6f0d0f" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/websocket" + packages = ["."] + revision = "31079b6807923eb23992c421b114992b95131b55" + +[[projects]] + branch = "master" + name = "github.com/dchest/blake256" + packages = ["."] + revision = "dee3fe6eb0e98dc774a94fc231f85baf7c29d360" + +[[projects]] + branch = "master" + name = "github.com/decred/base58" + packages = ["."] + revision = "b3520e187fa8ebe65eb74245408cf4b83e6a65d3" + +[[projects]] + branch = "master" + name = "github.com/decred/dcrd" + packages = [ + "blockchain", + "blockchain/indexers", + "blockchain/internal/dbnamespace", + "blockchain/internal/progresslog", + "blockchain/stake", + "blockchain/stake/internal/dbnamespace", + "blockchain/stake/internal/ticketdb", + "blockchain/stake/internal/tickettreap", + "certgen", + "chaincfg", + "chaincfg/chainec", + "chaincfg/chainhash", + "database", + "dcrec/edwards", + "dcrec/secp256k1", + "dcrec/secp256k1/schnorr", + "dcrjson", + "dcrutil", + "gcs", + "gcs/blockcf", + "hdkeychain", + "mempool", + "mining", + "rpcclient", + "txscript", + "wire" + ] + revision = "386527c3a649ba0340f67b698f0b4c2d35ac8aa1" + +[[projects]] + name = "github.com/decred/slog" + packages = ["."] + revision = "fbd821ef791ba2b8ae945f5d44f4e49396d230c5" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang/protobuf" + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp" + ] + revision = "130e6b02ab059e7b717a096f397c5b60111cae74" + +[[projects]] + name = "github.com/gorilla/websocket" + packages = ["."] + revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b" + version = "v1.2.0" + +[[projects]] + name = "github.com/jessevdk/go-flags" + packages = ["."] + revision = "96dc06278ce32a0e9d957d590bb987c81ee66407" + version = "v1.3.0" + +[[projects]] + branch = "master" + name = "github.com/jrick/bitset" + packages = ["."] + revision = "06eae37cdf93c699c0503c23f998167ce841974c" + +[[projects]] + branch = "master" + name = "github.com/jrick/logrotate" + packages = ["rotator"] + revision = "a93b200c26cbae3bb09dd0dc2c7c7fe1468a034a" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "nacl/secretbox", + "pbkdf2", + "poly1305", + "ripemd160", + "salsa20/salsa", + "scrypt", + "ssh/terminal" + ] + revision = "847319b7fc94cab682988f93da778204da164588" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "lex/httplex", + "trace" + ] + revision = "278c6cf336eb9139d63479da09da0cfb40fdc4c8" + +[[projects]] + branch = "master" + name = "golang.org/x/sync" + packages = ["errgroup"] + revision = "f52d1811a62927559de87708c8913c1650ce4f26" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows" + ] + revision = "429f518978ab01db8bb6f44b66785088e7fba58b" + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] + revision = "1cbadb444a806fd9430d14ad08967ed91da4fa0a" + +[[projects]] + branch = "master" + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + revision = "1e559d0a00eef8a9a43151db4665280bd8dd5886" + +[[projects]] + name = "google.golang.org/grpc" + packages = [ + ".", + "codes", + "connectivity", + "credentials", + "grpclb/grpc_lb_v1/messages", + "grpclog", + "internal", + "keepalive", + "metadata", + "naming", + "peer", + "stats", + "status", + "tap", + "transport" + ] + revision = "f92cdcd7dcdc69e81b2d7b338479a19a8723cfa3" + version = "v1.6.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "f096b2d652111ee61bde4e3a49c9074b9ca1e06234a6b4725ba817fa8fa2b93c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/internal/rpc/jsonrpc/methods.go b/internal/rpc/jsonrpc/methods.go index 7c052e2f2..e2709ff7e 100644 --- a/internal/rpc/jsonrpc/methods.go +++ b/internal/rpc/jsonrpc/methods.go @@ -8,23 +8,37 @@ package jsonrpc import ( "bytes" "context" - "crypto/hmac" - "crypto/sha512" "encoding/base64" "encoding/binary" "encoding/hex" "encoding/json" +<<<<<<< HEAD "hash" "io/ioutil" "math/big" "sort" "strconv" "strings" +======= +>>>>>>> update "sync" "time" +<<<<<<< HEAD:internal/rpc/jsonrpc/methods.go "github.com/decred/dcrd/blockchain/stake/v2" blockchain "github.com/decred/dcrd/blockchain/standalone" +======= +<<<<<<< HEAD +<<<<<<< HEAD + "github.com/decred/dcrd/blockchain" +======= + "github.com/decred/base58" +>>>>>>> legacyrpc: add paytocontracthashaddress rpc method +======= +>>>>>>> update + "github.com/decred/dcrd/blockchain/stake" + "github.com/decred/dcrd/chaincfg" +>>>>>>> legacyrpc: add getContractHash method:rpc/legacyrpc/methods.go "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/chaincfg/v2" "github.com/decred/dcrd/dcrec" @@ -836,6 +850,10 @@ func difficultyRatio(bits uint32, params *chaincfg.Params) float64 { return ratio } +<<<<<<< HEAD:internal/rpc/jsonrpc/methods.go +======= +// hashContracts hashes contracts and places them in a array. +>>>>>>> legacyrpc: add getContractHash method:rpc/legacyrpc/methods.go func hashContracts(contractArray [][]byte, contractAmounts int) [][]byte { var hashedContracts []hash.Hash @@ -848,26 +866,50 @@ func hashContracts(contractArray [][]byte, contractAmounts int) [][]byte { return hashedContractsByte } -func createContractArray(filePaths []string) [][]byte { - contractArray := make([][]byte, len(filePaths)) +// hashContracts hashes contracts and places them in a array. +func hashContracts(contractArray [][]byte, contractAmount int) [][]byte { + var hashedContracts []hash.Hash + hashedContracts := make([][]byte, contractAmount) + hasher := sha256.New() + for i := range contractArray { + hasher.Write(contractArray[i]) + hashedContracts[i] = hasher.Sum(nil) + } + return hashedContracts +} + +// createContractArray creates a array of contracts from the input filepath slice. +func createContractArray(filePaths []string) ([][]byte, error) { + contractArray := make([][]byte, len(filePaths)) for i := range filePaths { - contractArray[i], _ = ioutil.ReadFile(filePaths[i]) + contractArray[i], err = ioutil.ReadFile(filePaths[i]) + if err != nil { + return nil, err + } } - return contractArray + return contractArray, nil } -func lexiSort(hashedContracts [][]byte) [][]byte { +// getContractHash returns a slice of hashed contracts in string form. +func getContractHash(s *Server, icmd interface{}) (interface{}, error) { + cmd := icmd.(*dcrjson.GetContractHashCmd) + + contractArray, err := createContractArray(cmd.FilePath[i]) + if err != nil { + return nil, err + } + + hashedContracts := hashContracts(contractArray, len(cmd.FilePath)) + hashedContractsString := make([]string, len(cmd.FilePath)) for i := range hashedContracts { - for j := range hashedContracts { - if hashedContracts[i][j] > hashedContracts[i][j+1] { - hashedContracts[i], hashedContracts[i+1] = hashedContracts[i+1], hashedContracts[i] - } - } + hashedContractsString[i] = string(hashedContractsString[i]) } - return hashedContracts + return &dcrjson.GetContractHashResult{ + ContractHash: hashedContractsString, + }, nil } // getInfo handles a getinfo request by returning a structure containing @@ -1313,7 +1355,12 @@ func (s *Server) getNewAddress(ctx context.Context, icmd interface{}) (interface if cmd.Account != nil { acctName = *cmd.Account } +<<<<<<< HEAD:internal/rpc/jsonrpc/methods.go account, err := w.AccountNumber(ctx, acctName) +======= + + account, err := w.AccountNumber(acctName) +>>>>>>> legacyrpc: add getContractHash method:rpc/legacyrpc/methods.go if err != nil { if errors.Is(err, errors.NotExist) { return nil, errAccountNotFound @@ -1328,6 +1375,65 @@ func (s *Server) getNewAddress(ctx context.Context, icmd interface{}) (interface return addr.Address(), nil } +// lexiSort arranges hashedcontracts lexigraphically. Since all inputted hashes are size 256 +// sorting by size is unnecessary. +func lexiSort(hashedContracts [][]byte) [][]byte { + for i := range hashedContracts { + for j := range hashedContracts { + if hashedContracts[i][j] > hashedContracts[i][j+1] { + hashedContracts[i], hashedContracts[i+1] = hashedContracts[i+1], hashedContracts[i] + } + } + } + + return hashedContracts +} + +// getPayToContractAddress handles the getpaytocontractaddress by returning a +// address for a contract array +func getPayToContractAddress(s *Server, icmd interface{}) (interface{}, error) { + cmd := icmd.(*dcrjson.GetPayToContractAddressCmd) + w, ok := s.walletLoader.LoadedWallet() + if !ok { + return nil, ErrUnloadedWallet + } + + // TODO: I need to utilize the hdkeychain.Zero() after every childkey derivation + contractArray, err := createContractArray(cmd.FilePath[i]) + if err != nil { + return nil, err + } + + // hash each contract and then sort them lexicographically + hashedContracts := hashContracts(contractArray, len(cmd.FilePath)) + hashedContracts = lexiSort(hashedContracts) + + // obtain the contractHash extendedKey + contractHash := ContractHash(hashedContracts) + + // paymentBase and coin type key are synonyms. + paymentBase, err := w.CoinTypeKey() + if err != nil { + return nil, err + } + + // append the contractHash derivation path to the paymentBase + extendedKey, err := NewKeyFromString(append(paymentBase.String(), contractHash.String())) + if err != nil { + return nil, err + } + + // take the address format 1. begins with the version byte denoting the address type and end with a 4 byte checksum - checksum (SHA256(SHA256(prefix+data))) + addr, err := extendedKey.Address(w.ChainParams()) + if err != nil { + return nil, err + } + + return &dcrjson.GetPayToContractAddressResult{ + ContractAddress: addr.EncodeAddress(), + }, nil +} + // getRawChangeAddress handles a getrawchangeaddress request by creating // and returning a new change address for an account. // diff --git a/rpc/legacyrpc/contracts.go b/rpc/legacyrpc/contracts.go new file mode 100644 index 000000000..1089ad37d --- /dev/null +++ b/rpc/legacyrpc/contracts.go @@ -0,0 +1,107 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2015-2016 The Decred developers +// Copyright (c) 2017-2018 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package legacyrpc + +import ( + "bytes" + "encoding/binary" + "fmt" + + "io/ioutil" + + "github.com/decred/dcrd/hdkeychain" + "github.com/decred/dcrd/chainhash" +) + +// Contracthash gets the contract hash from the inputted hashedContracts +func ContractHash(hashedContracts [][]byte) (hdkeychain.ExtendedKey, error) { + // append the hashed contracts i.e h1 + h2 + h3 to create combinedContractHashes + combinedContractHashes := make([]byte, 1) + for i := range hashedContracts { + for j := range hashedContracts { + combinedContractHashes = append(combinedContractHashes, hashedContracts[i][j]) + } + } + + // apply the blake256 hash function to the combinedContractHashes + contractsHashed := chainhash.HashB(combinedContractHashes) + + // build the contract hash extended key + hashChan := make(chan hdkeychain.ExtendedKey) + go func (contractsHashed []byte) { + segmentedHashedContracts := make([][]byte, 16) + uint32segmentedHashedContracts := make([]uint32, 16) + for i := 0; i < 16; i++ { + switch i { + case i == 0: + segmentedHashedContracts[i] = contractsHashed[i*5 : (i*5)+5] + uint32segmentedHashedContracts[i] = byteToUInt32(segmentedHashedContracts[i]) + contractHash := hdkeychain.NewKeyFromString(string(segmentedHashedContracts[i]) + case i >= 1: + segmentedHashedContracts[i] = contractsHashed[i*5 : (i*5)+5] + uint32segmentedHashedContracts[i] = byteToUInt32(segmentedHashedContracts[i]) + contractHash, err := contractHash.Child(uint32segmentedHashedContracts[i]) + if err != nil { + return nil, err + } + } + } + + hashChan <- contractHash + }(contractsHashed) + + + return <- hashChan, nil +} + +// createContractArray creates a array of contracts from the input filepath slice. +// +// TODO: convert text to a input standard here before ReadFile path. +// or add error checking for specific text format +func createContractArray(filePaths []string) ([][]byte, error) { + var contractArray = make([][]byte, len(filePaths)) + for i := range filePaths { + contractArray[i], _ = ioutil.ReadFile(filePaths[i]) + } + + if len(contractArray) != len(filePaths) { + return nil, fmt.Errorf("Contract Array was not created successfully") + } + + return contractArray, nil +} + +func byteToUInt32(data []byte) (ret uint32) { + buf := bytes.NewBuffer(data) + binary.Read(buf, binary.LittleEndian, &ret) + return +} + +// hashContracts hashes contracts and places them in a lexigrahpically assorted array. +func hashContracts(contractArray [][]byte) [][]byte { + hashedContracts := make([][]byte, len(contractArray)) + + for i := range contractArray { + hashedContracts[i] = chainhash.HashB(contractArray[i]) + } + + return lexiSort(hashedContracts) +} + +func lexiSort(hashedContracts [][]byte) ([][]byte, error) { + for i := range hashedContracts { + for j := range hashedContracts { + if len(hashedContracts[i][j]) != 256 { + return nil, fmt.Errorf("Contract should be a size of 256 bits") + } else if hashedContracts[i][j] > hashedContracts[i][j+1] { + hashedContracts[i], hashedContracts[i+1] = hashedContracts[i+1], hashedContracts[i] + } + } + } + + return hashedContracts, nil +} diff --git a/rpc/legacyrpc/contracts_test.go b/rpc/legacyrpc/contracts_test.go new file mode 100644 index 000000000..7c41ee4d9 --- /dev/null +++ b/rpc/legacyrpc/contracts_test.go @@ -0,0 +1,29 @@ +package dcrutil + +import "testing" + +func TestlexiSort(t *testing.T) { + + lexiSort() +} + +func TesthashContracts(t *testing.T) { + + hashContracts() +} + +func TestbyteToUInt32(t *testing.T) { + + byteToUInt32() +} + +func TestcreateContractArray(t *testing.T) { + + createContractArray() +} + +func TestContractHash(t *testing.T) { + // t.Fatal("not implemented") + + ContractHash() +} From f273bb9f729e0e56f9fb249fd9837b0190415b98 Mon Sep 17 00:00:00 2001 From: "vracek@protonmail.com" Date: Fri, 11 Oct 2019 16:43:54 -0600 Subject: [PATCH 3/5] jsonrpc: update imports --- internal/rpc/jsonrpc/methods.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/internal/rpc/jsonrpc/methods.go b/internal/rpc/jsonrpc/methods.go index e2709ff7e..4eeb7e545 100644 --- a/internal/rpc/jsonrpc/methods.go +++ b/internal/rpc/jsonrpc/methods.go @@ -12,33 +12,15 @@ import ( "encoding/binary" "encoding/hex" "encoding/json" -<<<<<<< HEAD - "hash" - "io/ioutil" "math/big" "sort" "strconv" "strings" -======= ->>>>>>> update "sync" "time" -<<<<<<< HEAD:internal/rpc/jsonrpc/methods.go "github.com/decred/dcrd/blockchain/stake/v2" blockchain "github.com/decred/dcrd/blockchain/standalone" -======= -<<<<<<< HEAD -<<<<<<< HEAD - "github.com/decred/dcrd/blockchain" -======= - "github.com/decred/base58" ->>>>>>> legacyrpc: add paytocontracthashaddress rpc method -======= ->>>>>>> update - "github.com/decred/dcrd/blockchain/stake" - "github.com/decred/dcrd/chaincfg" ->>>>>>> legacyrpc: add getContractHash method:rpc/legacyrpc/methods.go "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/chaincfg/v2" "github.com/decred/dcrd/dcrec" From d650172f5539c640ec5e8f1af670fc71c63e0e3c Mon Sep 17 00:00:00 2001 From: "vracek@protonmail.com" Date: Sat, 26 Oct 2019 19:40:40 -0600 Subject: [PATCH 4/5] multi: change getpaytocontractaddress result and add it's method to the rpc server --- go.mod | 1 + internal/rpc/jsonrpc/methods.go | 137 ++++++++++++++++++-------------- rpc/jsonrpc/types/results.go | 6 +- rpc/legacyrpc/contracts.go | 107 ------------------------- rpc/legacyrpc/contracts_test.go | 29 ------- 5 files changed, 83 insertions(+), 197 deletions(-) delete mode 100644 rpc/legacyrpc/contracts.go delete mode 100644 rpc/legacyrpc/contracts_test.go diff --git a/go.mod b/go.mod index 4c88cc3a3..6c7ea826f 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/decred/dcrd/chaincfg/v2 v2.3.0 github.com/decred/dcrd/connmgr v1.0.2 github.com/decred/dcrd/connmgr/v2 v2.0.0 + github.com/decred/dcrd/crypto/blake256 v1.0.0 github.com/decred/dcrd/dcrec v1.0.0 github.com/decred/dcrd/dcrjson/v2 v2.2.0 github.com/decred/dcrd/dcrjson/v3 v3.0.1 diff --git a/internal/rpc/jsonrpc/methods.go b/internal/rpc/jsonrpc/methods.go index 4eeb7e545..926c52530 100644 --- a/internal/rpc/jsonrpc/methods.go +++ b/internal/rpc/jsonrpc/methods.go @@ -12,6 +12,7 @@ import ( "encoding/binary" "encoding/hex" "encoding/json" + "io/ioutil" "math/big" "sort" "strconv" @@ -23,6 +24,7 @@ import ( blockchain "github.com/decred/dcrd/blockchain/standalone" "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/chaincfg/v2" + "github.com/decred/dcrd/crypto/blake256" "github.com/decred/dcrd/dcrec" "github.com/decred/dcrd/dcrjson/v3" "github.com/decred/dcrd/dcrutil/v2" @@ -80,8 +82,10 @@ var handlers = map[string]handler{ "getbestblockhash": {fn: (*Server).getBestBlockHash}, "getblockcount": {fn: (*Server).getBlockCount}, "getblockhash": {fn: (*Server).getBlockHash}, + "getcontracthash": {fn: (*Server).getContractHash}, "getinfo": {fn: (*Server).getInfo}, "getmasterpubkey": {fn: (*Server).getMasterPubkey}, + "getpaytocontractaddress": {fn: (*Server).getPayToContractAddress}, "getmultisigoutinfo": {fn: (*Server).getMultisigOutInfo}, "getnewaddress": {fn: (*Server).getNewAddress}, "getrawchangeaddress": {fn: (*Server).getRawChangeAddress}, @@ -832,64 +836,52 @@ func difficultyRatio(bits uint32, params *chaincfg.Params) float64 { return ratio } -<<<<<<< HEAD:internal/rpc/jsonrpc/methods.go -======= // hashContracts hashes contracts and places them in a array. ->>>>>>> legacyrpc: add getContractHash method:rpc/legacyrpc/methods.go -func hashContracts(contractArray [][]byte, contractAmounts int) [][]byte { - - var hashedContracts []hash.Hash - hashedContractsByte := make([][]byte, contractAmounts) +func hashContracts(contractArray [][]byte) [][]byte { + // var contractHasher hash.Hash = blake256.New() + hc32 := make([][32]byte, len(contractArray)) + hc := make([][]byte, len(contractArray)) for i := range contractArray { - hashedContracts[i] = hmac.New(sha512.New, contractArray[i]) - hashedContractsByte[i] = hashedContracts[i].Sum(nil) + hc32[i] = blake256.Sum256(contractArray[i]) + hc[i] = hc32[i][:] } - return hashedContractsByte + return hc } -// hashContracts hashes contracts and places them in a array. -func hashContracts(contractArray [][]byte, contractAmount int) [][]byte { - var hashedContracts []hash.Hash - hashedContracts := make([][]byte, contractAmount) - hasher := sha256.New() - for i := range contractArray { - hasher.Write(contractArray[i]) - hashedContracts[i] = hasher.Sum(nil) - } - - return hashedContracts -} - -// createContractArray creates a array of contracts from the input filepath slice. +// createContractArray creates a array of contracts in byte form from the input filepath slice. func createContractArray(filePaths []string) ([][]byte, error) { - contractArray := make([][]byte, len(filePaths)) + // TODO: add checking here for right file type + var contractArray = make([][]byte, len(filePaths)) for i := range filePaths { - contractArray[i], err = ioutil.ReadFile(filePaths[i]) - if err != nil { - return nil, err - } + contractArray[i], _ = ioutil.ReadFile(filePaths[i]) + /* + if err != nil { + return nil, err + } + */ } return contractArray, nil } // getContractHash returns a slice of hashed contracts in string form. -func getContractHash(s *Server, icmd interface{}) (interface{}, error) { - cmd := icmd.(*dcrjson.GetContractHashCmd) - - contractArray, err := createContractArray(cmd.FilePath[i]) +func (s *Server) getContractHash(ctx context.Context, icmd interface{}) (interface{}, error) { + cmd := icmd.(*types.GetContractHashCmd) + contractArray, err := createContractArray(cmd.FilePath) if err != nil { return nil, err } - hashedContracts := hashContracts(contractArray, len(cmd.FilePath)) + hashedContracts := hashContracts(contractArray) + + // TODO: how can I do this better, do I really need to make them as strings? hashedContractsString := make([]string, len(cmd.FilePath)) for i := range hashedContracts { hashedContractsString[i] = string(hashedContractsString[i]) } - return &dcrjson.GetContractHashResult{ + return &types.GetContractHashResult{ ContractHash: hashedContractsString, }, nil } @@ -1337,12 +1329,8 @@ func (s *Server) getNewAddress(ctx context.Context, icmd interface{}) (interface if cmd.Account != nil { acctName = *cmd.Account } -<<<<<<< HEAD:internal/rpc/jsonrpc/methods.go - account, err := w.AccountNumber(ctx, acctName) -======= - account, err := w.AccountNumber(acctName) ->>>>>>> legacyrpc: add getContractHash method:rpc/legacyrpc/methods.go + account, err := w.AccountNumber(ctx, acctName) if err != nil { if errors.Is(err, errors.NotExist) { return nil, errAccountNotFound @@ -1371,48 +1359,81 @@ func lexiSort(hashedContracts [][]byte) [][]byte { return hashedContracts } +func getP2PKHFromExtendedKey(extKey *hdkeychain.ExtendedKey, n *chaincfg.Params) (string, error) { + ecPubKey, err := extKey.ECPubKey() + if err != nil { + return "", err + } + pkHash := dcrutil.Hash160(ecPubKey.SerializeCompressed()) + addr, err := dcrutil.NewAddressPubKeyHash(pkHash, n, dcrec.STEcdsaSecp256k1) + if err != nil { + return "", err + } + return addr.String(), nil +} + // getPayToContractAddress handles the getpaytocontractaddress by returning a // address for a contract array -func getPayToContractAddress(s *Server, icmd interface{}) (interface{}, error) { - cmd := icmd.(*dcrjson.GetPayToContractAddressCmd) +func (s *Server) getPayToContractAddress(ctx context.Context, icmd interface{}) (interface{}, error) { + cmd := icmd.(*types.GetPayToContractAddressCmd) w, ok := s.walletLoader.LoadedWallet() if !ok { - return nil, ErrUnloadedWallet + return nil, errUnloadedWallet } - // TODO: I need to utilize the hdkeychain.Zero() after every childkey derivation - contractArray, err := createContractArray(cmd.FilePath[i]) + net := w.ChainParams() + + contractArray, err := createContractArray(cmd.FilePath) if err != nil { return nil, err } - // hash each contract and then sort them lexicographically - hashedContracts := hashContracts(contractArray, len(cmd.FilePath)) - hashedContracts = lexiSort(hashedContracts) + hashedContracts := lexiSort(hashContracts(contractArray)) - // obtain the contractHash extendedKey - contractHash := ContractHash(hashedContracts) + var contractHash []byte + for i := 0; i < len(hashedContracts); i++ { + for j := 0; i < len(hashedContracts); j++ { + contractHash = append(contractHash, hashedContracts[i][j]) + } + } + + ch32 := blake256.Sum256(contractHash) + stringCh := string(ch32[:]) + + contractsHashedExtKey, err := hdkeychain.NewKeyFromString(stringCh, net) + if err != nil { + return nil, err + } + defer contractsHashedExtKey.Zero() + + contractsHashedExtKey, err = contractsHashedExtKey.Child(0) + if err != nil { + return nil, err + } + + coinTypePrivKey, err := w.CoinTypePrivKey(ctx) + if err != nil { + return nil, err + } + defer coinTypePrivKey.Zero() - // paymentBase and coin type key are synonyms. - paymentBase, err := w.CoinTypeKey() + contractsHashedExtKey, err = hdkeychain.NewKeyFromString(coinTypePrivKey.String()+contractsHashedExtKey.String(), w.ChainParams()) if err != nil { return nil, err } - // append the contractHash derivation path to the paymentBase - extendedKey, err := NewKeyFromString(append(paymentBase.String(), contractHash.String())) + contractsHashedExtKey, err = contractsHashedExtKey.Child(0) if err != nil { return nil, err } - // take the address format 1. begins with the version byte denoting the address type and end with a 4 byte checksum - checksum (SHA256(SHA256(prefix+data))) - addr, err := extendedKey.Address(w.ChainParams()) + payToContractAddress, err := getP2PKHFromExtendedKey(contractsHashedExtKey, net) if err != nil { return nil, err } - return &dcrjson.GetPayToContractAddressResult{ - ContractAddress: addr.EncodeAddress(), + return &types.GetPayToContractAddressResult{ + Address: payToContractAddress, }, nil } diff --git a/rpc/jsonrpc/types/results.go b/rpc/jsonrpc/types/results.go index fbedcf690..4adaaece3 100644 --- a/rpc/jsonrpc/types/results.go +++ b/rpc/jsonrpc/types/results.go @@ -43,7 +43,7 @@ type GetBalanceResult struct { // GetContractHashResult models the data from the getcontracthash command. type GetContractHashResult struct { - ContractHash string `json:"contracthash"` + ContractHash []string `json:"contracthash"` } // GetMultisigOutInfoResult models the data returned from the getmultisigoutinfo @@ -63,9 +63,9 @@ type GetMultisigOutInfoResult struct { Amount float64 `json:"amount"` } -// GetPayToContractHashResult models the data returned from the getpaytocontracthash +// GetPayToContractAddressResult models the data returned from the getpaytocontracthash // command. -type GetPayToContractHashResult struct { +type GetPayToContractAddressResult struct { Address string `json:"address"` } diff --git a/rpc/legacyrpc/contracts.go b/rpc/legacyrpc/contracts.go deleted file mode 100644 index 1089ad37d..000000000 --- a/rpc/legacyrpc/contracts.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2016 The Decred developers -// Copyright (c) 2017-2018 The Decred developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package legacyrpc - -import ( - "bytes" - "encoding/binary" - "fmt" - - "io/ioutil" - - "github.com/decred/dcrd/hdkeychain" - "github.com/decred/dcrd/chainhash" -) - -// Contracthash gets the contract hash from the inputted hashedContracts -func ContractHash(hashedContracts [][]byte) (hdkeychain.ExtendedKey, error) { - // append the hashed contracts i.e h1 + h2 + h3 to create combinedContractHashes - combinedContractHashes := make([]byte, 1) - for i := range hashedContracts { - for j := range hashedContracts { - combinedContractHashes = append(combinedContractHashes, hashedContracts[i][j]) - } - } - - // apply the blake256 hash function to the combinedContractHashes - contractsHashed := chainhash.HashB(combinedContractHashes) - - // build the contract hash extended key - hashChan := make(chan hdkeychain.ExtendedKey) - go func (contractsHashed []byte) { - segmentedHashedContracts := make([][]byte, 16) - uint32segmentedHashedContracts := make([]uint32, 16) - for i := 0; i < 16; i++ { - switch i { - case i == 0: - segmentedHashedContracts[i] = contractsHashed[i*5 : (i*5)+5] - uint32segmentedHashedContracts[i] = byteToUInt32(segmentedHashedContracts[i]) - contractHash := hdkeychain.NewKeyFromString(string(segmentedHashedContracts[i]) - case i >= 1: - segmentedHashedContracts[i] = contractsHashed[i*5 : (i*5)+5] - uint32segmentedHashedContracts[i] = byteToUInt32(segmentedHashedContracts[i]) - contractHash, err := contractHash.Child(uint32segmentedHashedContracts[i]) - if err != nil { - return nil, err - } - } - } - - hashChan <- contractHash - }(contractsHashed) - - - return <- hashChan, nil -} - -// createContractArray creates a array of contracts from the input filepath slice. -// -// TODO: convert text to a input standard here before ReadFile path. -// or add error checking for specific text format -func createContractArray(filePaths []string) ([][]byte, error) { - var contractArray = make([][]byte, len(filePaths)) - for i := range filePaths { - contractArray[i], _ = ioutil.ReadFile(filePaths[i]) - } - - if len(contractArray) != len(filePaths) { - return nil, fmt.Errorf("Contract Array was not created successfully") - } - - return contractArray, nil -} - -func byteToUInt32(data []byte) (ret uint32) { - buf := bytes.NewBuffer(data) - binary.Read(buf, binary.LittleEndian, &ret) - return -} - -// hashContracts hashes contracts and places them in a lexigrahpically assorted array. -func hashContracts(contractArray [][]byte) [][]byte { - hashedContracts := make([][]byte, len(contractArray)) - - for i := range contractArray { - hashedContracts[i] = chainhash.HashB(contractArray[i]) - } - - return lexiSort(hashedContracts) -} - -func lexiSort(hashedContracts [][]byte) ([][]byte, error) { - for i := range hashedContracts { - for j := range hashedContracts { - if len(hashedContracts[i][j]) != 256 { - return nil, fmt.Errorf("Contract should be a size of 256 bits") - } else if hashedContracts[i][j] > hashedContracts[i][j+1] { - hashedContracts[i], hashedContracts[i+1] = hashedContracts[i+1], hashedContracts[i] - } - } - } - - return hashedContracts, nil -} diff --git a/rpc/legacyrpc/contracts_test.go b/rpc/legacyrpc/contracts_test.go deleted file mode 100644 index 7c41ee4d9..000000000 --- a/rpc/legacyrpc/contracts_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package dcrutil - -import "testing" - -func TestlexiSort(t *testing.T) { - - lexiSort() -} - -func TesthashContracts(t *testing.T) { - - hashContracts() -} - -func TestbyteToUInt32(t *testing.T) { - - byteToUInt32() -} - -func TestcreateContractArray(t *testing.T) { - - createContractArray() -} - -func TestContractHash(t *testing.T) { - // t.Fatal("not implemented") - - ContractHash() -} From 5d78bf616fe9f755da4e105ba194ebf33e5d95e7 Mon Sep 17 00:00:00 2001 From: "vracek@protonmail.com" Date: Sat, 26 Oct 2019 20:28:30 -0600 Subject: [PATCH 5/5] multi: required changes for help for getcontracthashes and getpaytocontracthash --- internal/rpc/jsonrpc/rpcserverhelp.go | 4 +++- internal/rpchelp/helpdescs_en_US.go | 12 ++++++++++++ internal/rpchelp/methods.go | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/internal/rpc/jsonrpc/rpcserverhelp.go b/internal/rpc/jsonrpc/rpcserverhelp.go index 7a67d8bf6..74897fcaa 100644 --- a/internal/rpc/jsonrpc/rpcserverhelp.go +++ b/internal/rpc/jsonrpc/rpcserverhelp.go @@ -22,10 +22,12 @@ func helpDescsEnUS() map[string]string { "getbestblock": "getbestblock\n\nReturns the hash and height of the newest block in the best chain that wallet has finished syncing with.\n\nArguments:\nNone\n\nResult:\n{\n \"hash\": \"value\", (string) The hash of the block\n \"height\": n, (numeric) The blockchain height of the block\n} \n", "getblockcount": "getblockcount\n\nReturns the blockchain height of the newest block in the best chain that wallet has finished syncing with.\n\nArguments:\nNone\n\nResult:\nn.nnn (numeric) The blockchain height of the most recent synced-to block\n", "getblockhash": "getblockhash index\n\nReturns the hash of a main chain block at some height\n\nArguments:\n1. index (numeric, required) The block height\n\nResult:\n\"value\" (string) The main chain block hash\n", + "getcontracthash": "getcontracthash [\"filepath\",...]\n\nTakes contracts (files) and hashes them.\n\nArguments:\n1. filepath (array of string, required) The paths of the files to be hashed.\n\nResult:\n{\n \"contracthash\": [\"value\",...], (array of string) Returns the contracts hashed\n} \n", "getinfo": "getinfo\n\nReturns a JSON object containing various state info.\n\nArguments:\nNone\n\nResult:\n{\n \"version\": n, (numeric) The version of the server\n \"protocolversion\": n, (numeric) The latest supported protocol version\n \"walletversion\": n, (numeric) The version of the address manager database\n \"balance\": n.nnn, (numeric) The balance of all accounts calculated with one block confirmation\n \"blocks\": n, (numeric) The number of blocks processed\n \"timeoffset\": n, (numeric) The time offset\n \"connections\": n, (numeric) The number of connected peers\n \"proxy\": \"value\", (string) The proxy used by the server\n \"difficulty\": n.nnn, (numeric) The current target difficulty\n \"testnet\": true|false, (boolean) Whether or not server is using testnet\n \"keypoololdest\": n, (numeric) Unset\n \"keypoolsize\": n, (numeric) Unset\n \"unlocked_until\": n, (numeric) Unset\n \"paytxfee\": n.nnn, (numeric) The fee per kB of the serialized tx size used each time more fee is required for an authored transaction\n \"relayfee\": n.nnn, (numeric) The minimum relay fee for non-free transactions in DCR/KB\n \"errors\": \"value\", (string) Any current errors\n} \n", "getmasterpubkey": "getmasterpubkey (\"account\")\n\nRequests the master pubkey from the wallet.\n\nArguments:\n1. account (string, optional) The account to get the master pubkey for\n\nResult:\n\"value\" (string) The master pubkey for the wallet\n", "getmultisigoutinfo": "getmultisigoutinfo \"hash\" index\n\nReturns information about a multisignature output.\n\nArguments:\n1. hash (string, required) Input hash to check.\n2. index (numeric, required) Index of input.\n\nResult:\n{\n \"address\": \"value\", (string) Script address.\n \"redeemscript\": \"value\", (string) Hex of the redeeming script.\n \"m\": n, (numeric) m (in m-of-n)\n \"n\": n, (numeric) n (in m-of-n)\n \"pubkeys\": [\"value\",...], (array of string) Associated pubkeys.\n \"txhash\": \"value\", (string) txhash\n \"blockheight\": n, (numeric) Height of the containing block.\n \"blockhash\": \"value\", (string) Hash of the containing block.\n \"spent\": true|false, (boolean) If it has been spent.\n \"spentby\": \"value\", (string) Hash of spending tx.\n \"spentbyindex\": n, (numeric) Index of spending tx.\n \"amount\": n.nnn, (numeric) Amount of coins contained.\n} \n", "getnewaddress": "getnewaddress (\"account\" \"gappolicy\")\n\nGenerates and returns a new payment address.\n\nArguments:\n1. account (string, optional) Account name the new address will belong to (default=\"default\")\n2. gappolicy (string, optional) String defining the policy to use when the BIP0044 gap limit would be violated, may be \"error\", \"ignore\", or \"wrap\"\n\nResult:\n\"value\" (string) The payment address\n", + "getpaytocontractaddress": "getpaytocontractaddress [\"filepath\",...]\n\nReturns the pay to contract P2PKH of given contracts.\n\nArguments:\n1. filepath (array of string, required) The filepaths of the contracts to be used for the P2PKH\n\nResult:\n\"value\" (string) The pay to contract P2PKH\n", "getrawchangeaddress": "getrawchangeaddress (\"account\")\n\nGenerates and returns a new internal payment address for use as a change address in raw transactions.\n\nArguments:\n1. account (string, optional) Account name the new internal address will belong to (default=\"default\")\n\nResult:\n\"value\" (string) The internal payment address\n", "getreceivedbyaccount": "getreceivedbyaccount \"account\" (minconf=1)\n\nReturns the total amount received by addresses of some account, including spent outputs.\n\nArguments:\n1. account (string, required) Account name to query total received amount for\n2. minconf (numeric, optional, default=1) Minimum number of block confirmations required before an output's value is included in the total\n\nResult:\nn.nnn (numeric) The total received amount valued in decred\n", "getreceivedbyaddress": "getreceivedbyaddress \"address\" (minconf=1)\n\nReturns the total amount received by a single address, including spent outputs.\n\nArguments:\n1. address (string, required) Payment address which received outputs to include in total\n2. minconf (numeric, optional, default=1) Minimum number of block confirmations required before an output's value is included in the total\n\nResult:\nn.nnn (numeric) The total received amount valued in decred\n", @@ -87,4 +89,4 @@ var localeHelpDescs = map[string]func() map[string]string{ "en_US": helpDescsEnUS, } -var requestUsages = "abandontransaction \"hash\"\naccountaddressindex \"account\" branch\naccountsyncaddressindex \"account\" branch index\naddmultisigaddress nrequired [\"key\",...] (\"account\")\naddticket \"tickethex\"\nconsolidate inputs (\"account\" \"address\")\ncreatemultisig nrequired [\"key\",...]\ncreatenewaccount \"account\"\ndumpprivkey \"address\"\ngeneratevote \"blockhash\" height \"tickethash\" votebits \"votebitsext\"\ngetaccountaddress \"account\"\ngetaccount \"address\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblockhash\ngetbestblock\ngetblockcount\ngetblockhash index\ngetinfo\ngetmasterpubkey (\"account\")\ngetmultisigoutinfo \"hash\" index\ngetnewaddress (\"account\" \"gappolicy\")\ngetrawchangeaddress (\"account\")\ngetreceivedbyaccount \"account\" (minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngetstakeinfo\ngetticketfee\ngettickets includeimmature\ngettransaction \"txid\" (includewatchonly=false)\ngetunconfirmedbalance (\"account\")\ngetvotechoices\ngetwalletfee\nhelp (\"command\")\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportscript \"hex\" (rescan=true scanfrom)\nimportxpub \"name\" \"xpub\"\nmixaccount\nmixoutput \"outpoint\"\nlistaccounts (minconf=1)\nlistaddresstransactions [\"address\",...] (\"account\")\nlistalltransactions (\"account\")\nlistlockunspent\nlistreceivedbyaccount (minconf=1 includeempty=false includewatchonly=false)\nlistreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\nlistscripts\nlistsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\nlisttransactions (\"account\" count=10 from=0 includewatchonly=false)\nlistunspent (minconf=1 maxconf=9999999 [\"address\",...])\nlockunspent unlock [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...]\npurchaseticket \"fromaccount\" spendlimit (minconf=1 \"ticketaddress\" numtickets \"pooladdress\" poolfees expiry \"comment\" ticketfee)\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\nrenameaccount \"oldaccount\" \"newaccount\"\nrescanwallet (beginheight=0)\nrevoketickets\nsendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 \"comment\" \"commentto\")\nsendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 \"comment\")\nsendtoaddress \"address\" amount (\"comment\" \"commentto\")\nsendtomultisig \"fromaccount\" amount [\"pubkey\",...] (nrequired=1 minconf=1 \"comment\")\nsetticketfee fee\nsettxfee amount\nsetvotechoice \"agendaid\" \"choiceid\"\nsignmessage \"address\" \"message\"\nsignrawtransaction \"rawtx\" ([{\"txid\":\"value\",\"vout\":n,\"tree\":n,\"scriptpubkey\":\"value\",\"redeemscript\":\"value\"},...] [\"privkey\",...] flags=\"ALL\")\nsignrawtransactions [\"rawtx\",...] (send=true)\nstakepooluserinfo \"user\"\nsweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\nticketsforaddress \"address\"\nvalidateaddress \"address\"\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpassphrase \"passphrase\" timeout" +var requestUsages = "abandontransaction \"hash\"\naccountaddressindex \"account\" branch\naccountsyncaddressindex \"account\" branch index\naddmultisigaddress nrequired [\"key\",...] (\"account\")\naddticket \"tickethex\"\nconsolidate inputs (\"account\" \"address\")\ncreatemultisig nrequired [\"key\",...]\ncreatenewaccount \"account\"\ndumpprivkey \"address\"\ngeneratevote \"blockhash\" height \"tickethash\" votebits \"votebitsext\"\ngetaccountaddress \"account\"\ngetaccount \"address\"\ngetaddressesbyaccount \"account\"\ngetbalance (\"account\" minconf=1)\ngetbestblockhash\ngetbestblock\ngetblockcount\ngetblockhash index\ngetcontracthash [\"filepath\",...]\ngetinfo\ngetmasterpubkey (\"account\")\ngetmultisigoutinfo \"hash\" index\ngetnewaddress (\"account\" \"gappolicy\")\ngetpaytocontractaddress [\"filepath\",...]\ngetrawchangeaddress (\"account\")\ngetreceivedbyaccount \"account\" (minconf=1)\ngetreceivedbyaddress \"address\" (minconf=1)\ngetstakeinfo\ngetticketfee\ngettickets includeimmature\ngettransaction \"txid\" (includewatchonly=false)\ngetunconfirmedbalance (\"account\")\ngetvotechoices\ngetwalletfee\nhelp (\"command\")\nimportprivkey \"privkey\" (\"label\" rescan=true scanfrom)\nimportscript \"hex\" (rescan=true scanfrom)\nimportxpub \"name\" \"xpub\"\nmixaccount\nmixoutput \"outpoint\"\nlistaccounts (minconf=1)\nlistaddresstransactions [\"address\",...] (\"account\")\nlistalltransactions (\"account\")\nlistlockunspent\nlistreceivedbyaccount (minconf=1 includeempty=false includewatchonly=false)\nlistreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\nlistscripts\nlistsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\nlisttransactions (\"account\" count=10 from=0 includewatchonly=false)\nlistunspent (minconf=1 maxconf=9999999 [\"address\",...])\nlockunspent unlock [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...]\npurchaseticket \"fromaccount\" spendlimit (minconf=1 \"ticketaddress\" numtickets \"pooladdress\" poolfees expiry \"comment\" ticketfee)\nredeemmultisigout \"hash\" index tree (\"address\")\nredeemmultisigouts \"fromscraddress\" (\"toaddress\" number)\nrenameaccount \"oldaccount\" \"newaccount\"\nrescanwallet (beginheight=0)\nrevoketickets\nsendfrom \"fromaccount\" \"toaddress\" amount (minconf=1 \"comment\" \"commentto\")\nsendmany \"fromaccount\" {\"address\":amount,...} (minconf=1 \"comment\")\nsendtoaddress \"address\" amount (\"comment\" \"commentto\")\nsendtomultisig \"fromaccount\" amount [\"pubkey\",...] (nrequired=1 minconf=1 \"comment\")\nsetticketfee fee\nsettxfee amount\nsetvotechoice \"agendaid\" \"choiceid\"\nsignmessage \"address\" \"message\"\nsignrawtransaction \"rawtx\" ([{\"txid\":\"value\",\"vout\":n,\"tree\":n,\"scriptpubkey\":\"value\",\"redeemscript\":\"value\"},...] [\"privkey\",...] flags=\"ALL\")\nsignrawtransactions [\"rawtx\",...] (send=true)\nstakepooluserinfo \"user\"\nsweepaccount \"sourceaccount\" \"destinationaddress\" (requiredconfirmations feeperkb)\nticketsforaddress \"address\"\nvalidateaddress \"address\"\nverifymessage \"address\" \"signature\" \"message\"\nversion\nwalletinfo\nwalletislocked\nwalletlock\nwalletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\nwalletpassphrase \"passphrase\" timeout" diff --git a/internal/rpchelp/helpdescs_en_US.go b/internal/rpchelp/helpdescs_en_US.go index a446ae373..2e993686d 100644 --- a/internal/rpchelp/helpdescs_en_US.go +++ b/internal/rpchelp/helpdescs_en_US.go @@ -576,11 +576,23 @@ var helpDescsEnUS = map[string]string{ "getbestblockresult-hash": "The hash of the block", "getbestblockresult-height": "The blockchain height of the block", + // GetContractHash help. + "getcontracthash--synopsis": "Takes contracts (files) and hashes them.", + "getcontracthash-filepath": "The paths of the files to be hashed.", + // GetContractHashResult help. + "getcontracthashresult-contracthash": "Returns the contracts hashed", + // GetUnconfirmedBalanceCmd help. "getunconfirmedbalance--synopsis": "Calculates the unspent output value of all unmined transaction outputs for an account.", "getunconfirmedbalance-account": "The account to query the unconfirmed balance for (default=\"default\")", "getunconfirmedbalance--result0": "Total amount of all unmined unspent outputs of the account valued in decred.", + "getpaytocontractaddress--synopsis": "Returns the pay to contract P2PKH of given contracts.", + "getpaytocontractaddress-filepath": "The filepaths of the contracts to be used for the P2PKH", + + // GetPayToContractAddressResultCmd help. + "getpaytocontractaddress--result0": "The pay to contract P2PKH", + // ListAddressTransactionsCmd help. "listaddresstransactions--synopsis": "Returns a JSON array of objects containing verbose details for wallet transactions pertaining some addresses.", "listaddresstransactions-addresses": "Addresses to filter transaction results by", diff --git a/internal/rpchelp/methods.go b/internal/rpchelp/methods.go index 4f02388f1..ff85079a3 100644 --- a/internal/rpchelp/methods.go +++ b/internal/rpchelp/methods.go @@ -45,10 +45,12 @@ var Methods = []struct { {"getbestblock", []interface{}{(*dcrdtypes.GetBestBlockResult)(nil)}}, {"getblockcount", returnsNumber}, {"getblockhash", returnsString}, + {"getcontracthash", []interface{}{(*types.GetContractHashResult)(nil)}}, {"getinfo", []interface{}{(*types.InfoWalletResult)(nil)}}, {"getmasterpubkey", []interface{}{(*string)(nil)}}, {"getmultisigoutinfo", []interface{}{(*types.GetMultisigOutInfoResult)(nil)}}, {"getnewaddress", returnsString}, + {"getpaytocontractaddress", returnsString}, {"getrawchangeaddress", returnsString}, {"getreceivedbyaccount", returnsNumber}, {"getreceivedbyaddress", returnsNumber},