diff --git a/blockdag/blockindex.go b/blockdag/blockindex.go index 5964c5baf..dc171c385 100644 --- a/blockdag/blockindex.go +++ b/blockdag/blockindex.go @@ -160,9 +160,9 @@ func newBlockNode(blockHeader *wire.BlockHeader, parents blockSet, phantomK uint // Header constructs a block header from the node and returns it. // // This function is safe for concurrent access. -func (node *blockNode) Header() wire.BlockHeader { +func (node *blockNode) Header() *wire.BlockHeader { // No lock is needed because all accessed fields are immutable. - return wire.BlockHeader{ + return &wire.BlockHeader{ Version: node.version, NumPrevBlocks: byte(len(node.parents)), PrevBlocks: node.PrevHashes(), diff --git a/blockdag/checkpoints.go b/blockdag/checkpoints.go index f41c80704..6f410bc74 100644 --- a/blockdag/checkpoints.go +++ b/blockdag/checkpoints.go @@ -130,7 +130,7 @@ func (dag *BlockDAG) findPreviousCheckpoint() (*blockNode, error) { // When there is a next checkpoint and the height of the current best // chain does not exceed it, the current checkpoint lockin is still // the latest known checkpoint. - if dag.SelectedTip().height < dag.nextCheckpoint.Height { + if dag.selectedTip().height < dag.nextCheckpoint.Height { return dag.checkpointNode, nil } @@ -218,7 +218,7 @@ func (dag *BlockDAG) IsCheckpointCandidate(block *util.Block) (bool, error) { // A checkpoint must be at least CheckpointConfirmations blocks // before the end of the main chain. - dagHeight := dag.SelectedTip().height + dagHeight := dag.selectedTip().height if node.height > (dagHeight - CheckpointConfirmations) { return false, nil } diff --git a/blockdag/dag.go b/blockdag/dag.go index cfe334732..86c88014c 100644 --- a/blockdag/dag.go +++ b/blockdag/dag.go @@ -322,7 +322,7 @@ func (dag *BlockDAG) CalcSequenceLock(tx *util.Tx, utxoSet UTXOSet, mempool bool dag.dagLock.Lock() defer dag.dagLock.Unlock() - return dag.calcSequenceLock(dag.SelectedTip(), utxoSet, tx, mempool) + return dag.calcSequenceLock(dag.selectedTip(), utxoSet, tx, mempool) } // calcSequenceLock computes the relative lock-times for the passed @@ -924,7 +924,7 @@ func (dag *BlockDAG) isCurrent() bool { // Not current if the latest main (best) chain height is before the // latest known good checkpoint (when checkpoints are enabled). checkpoint := dag.LatestCheckpoint() - if checkpoint != nil && dag.SelectedTip().height < checkpoint.Height { + if checkpoint != nil && dag.selectedTip().height < checkpoint.Height { return false } @@ -934,7 +934,7 @@ func (dag *BlockDAG) isCurrent() bool { // The chain appears to be current if none of the checks reported // otherwise. minus24Hours := dag.timeSource.AdjustedTime().Add(-24 * time.Hour).Unix() - return dag.SelectedTip().timestamp >= minus24Hours + return dag.selectedTip().timestamp >= minus24Hours } // IsCurrent returns whether or not the chain believes it is current. Several @@ -951,14 +951,27 @@ func (dag *BlockDAG) IsCurrent() bool { return dag.isCurrent() } -// SelectedTip returns the current selected tip for the DAG. +// selectedTip returns the current selected tip for the DAG. // It will return nil if there is no tip. // // This function is safe for concurrent access. -func (dag *BlockDAG) SelectedTip() *blockNode { +func (dag *BlockDAG) selectedTip() *blockNode { return dag.virtual.selectedParent } +// SelectedTipHeader returns the header of the current selected tip for the DAG. +// It will return nil if there is no tip. +// +// This function is safe for concurrent access. +func (dag *BlockDAG) SelectedTipHeader() *wire.BlockHeader { + selectedTip := dag.selectedTip() + if selectedTip == nil { + return nil + } + + return selectedTip.Header() +} + // UTXOSet returns the DAG's UTXO set func (dag *BlockDAG) UTXOSet() *FullUTXOSet { return dag.virtual.utxoSet @@ -1027,11 +1040,11 @@ func (dag *BlockDAG) CurrentBits() uint32 { // HeaderByHash returns the block header identified by the given hash or an // error if it doesn't exist. -func (dag *BlockDAG) HeaderByHash(hash *daghash.Hash) (wire.BlockHeader, error) { +func (dag *BlockDAG) HeaderByHash(hash *daghash.Hash) (*wire.BlockHeader, error) { node := dag.index.LookupNode(hash) if node == nil { err := fmt.Errorf("block %s is not known", hash) - return wire.BlockHeader{}, err + return &wire.BlockHeader{}, err } return node.Header(), nil @@ -1277,7 +1290,7 @@ func (dag *BlockDAG) locateInventory(locator BlockLocator, hashStop *daghash.Has } // Calculate how many entries are needed. - total := uint32((dag.SelectedTip().height - startNode.height) + 1) + total := uint32((dag.selectedTip().height - startNode.height) + 1) if stopNode != nil && stopNode.height >= startNode.height { total = uint32((stopNode.height - startNode.height) + 1) } @@ -1340,7 +1353,7 @@ func (dag *BlockDAG) LocateBlocks(locator BlockLocator, hashStop *daghash.Hash, // See the comment on the exported function for more details on special cases. // // This function MUST be called with the chain state lock held (for reads). -func (dag *BlockDAG) locateHeaders(locator BlockLocator, hashStop *daghash.Hash, maxHeaders uint32) []wire.BlockHeader { +func (dag *BlockDAG) locateHeaders(locator BlockLocator, hashStop *daghash.Hash, maxHeaders uint32) []*wire.BlockHeader { // Find the node after the first known block in the locator and the // total number of nodes after it needed while respecting the stop hash // and max entries. @@ -1350,7 +1363,7 @@ func (dag *BlockDAG) locateHeaders(locator BlockLocator, hashStop *daghash.Hash, } // Populate and return the found headers. - headers := make([]wire.BlockHeader, 0, total) + headers := make([]*wire.BlockHeader, 0, total) for i := uint32(0); i < total; i++ { headers = append(headers, node.Header()) node = node.diffChild @@ -1381,7 +1394,7 @@ func (dag *BlockDAG) UTXORUnlock() { // after the genesis block will be returned // // This function is safe for concurrent access. -func (dag *BlockDAG) LocateHeaders(locator BlockLocator, hashStop *daghash.Hash) []wire.BlockHeader { +func (dag *BlockDAG) LocateHeaders(locator BlockLocator, hashStop *daghash.Hash) []*wire.BlockHeader { dag.dagLock.RLock() headers := dag.locateHeaders(locator, hashStop, wire.MaxBlockHeadersPerMsg) dag.dagLock.RUnlock() @@ -1539,7 +1552,7 @@ func New(config *Config) (*BlockDAG, error) { return nil, err } - selectedTip := dag.SelectedTip() + selectedTip := dag.selectedTip() log.Infof("DAG state (height %d, hash %v, work %v)", selectedTip.height, selectedTip.hash, selectedTip.workSum) diff --git a/blockdag/dag_test.go b/blockdag/dag_test.go index 25338176c..c60149cf5 100644 --- a/blockdag/dag_test.go +++ b/blockdag/dag_test.go @@ -220,7 +220,7 @@ func TestCalcSequenceLock(t *testing.T) { // Generate enough synthetic blocks for the rest of the test dag := newTestDAG(netParams) - node := dag.SelectedTip() + node := dag.selectedTip() blockTime := node.Header().Timestamp numBlocksToGenerate := uint32(5) for i := uint32(0); i < numBlocksToGenerate; i++ { diff --git a/blockdag/difficulty.go b/blockdag/difficulty.go index c8b623d54..ae59f0768 100644 --- a/blockdag/difficulty.go +++ b/blockdag/difficulty.go @@ -290,7 +290,7 @@ func (dag *BlockDAG) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTim // This function is safe for concurrent access. func (dag *BlockDAG) CalcNextRequiredDifficulty(timestamp time.Time) (uint32, error) { dag.dagLock.Lock() - difficulty, err := dag.calcNextRequiredDifficulty(dag.SelectedTip(), timestamp) + difficulty, err := dag.calcNextRequiredDifficulty(dag.selectedTip(), timestamp) dag.dagLock.Unlock() return difficulty, err } diff --git a/blockdag/doc.go b/blockdag/doc.go index 082918bd7..e4ee535a0 100644 --- a/blockdag/doc.go +++ b/blockdag/doc.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. /* -Package blockchain implements bitcoin block handling and chain selection rules. +Package blockdag implements bitcoin block handling and chain selection rules. The bitcoin block handling and chain selection rules are an integral, and quite likely the most important, part of bitcoin. Unfortunately, at the time of diff --git a/blockdag/test_utils.go b/blockdag/test_utils.go index adf8f19c4..d14ca77fd 100644 --- a/blockdag/test_utils.go +++ b/blockdag/test_utils.go @@ -7,7 +7,7 @@ import ( "github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/database" - _ "github.com/daglabs/btcd/database/ffldb" + _ "github.com/daglabs/btcd/database/ffldb" // blank import ffldb so that its init() function runs before tests "github.com/daglabs/btcd/txscript" "github.com/daglabs/btcd/wire" ) diff --git a/blockdag/thresholdstate.go b/blockdag/thresholdstate.go index 150022c05..d08165102 100644 --- a/blockdag/thresholdstate.go +++ b/blockdag/thresholdstate.go @@ -265,7 +265,7 @@ func (dag *BlockDAG) thresholdState(prevNode *blockNode, checker thresholdCondit // This function is safe for concurrent access. func (dag *BlockDAG) ThresholdState(deploymentID uint32) (ThresholdState, error) { dag.dagLock.Lock() - state, err := dag.deploymentState(dag.SelectedTip(), deploymentID) + state, err := dag.deploymentState(dag.selectedTip(), deploymentID) dag.dagLock.Unlock() return state, err @@ -277,7 +277,7 @@ func (dag *BlockDAG) ThresholdState(deploymentID uint32) (ThresholdState, error) // This function is safe for concurrent access. func (dag *BlockDAG) IsDeploymentActive(deploymentID uint32) (bool, error) { dag.dagLock.Lock() - state, err := dag.deploymentState(dag.SelectedTip(), deploymentID) + state, err := dag.deploymentState(dag.selectedTip(), deploymentID) dag.dagLock.Unlock() if err != nil { return false, err @@ -316,7 +316,7 @@ func (dag *BlockDAG) initThresholdCaches() error { // threshold state for each of them. This will ensure the caches are // populated and any states that needed to be recalculated due to // definition changes is done now. - prevNode := dag.SelectedTip().selectedParent + prevNode := dag.selectedTip().selectedParent for bit := uint32(0); bit < vbNumBits; bit++ { checker := bitConditionChecker{bit: bit, chain: dag} cache := &dag.warningCaches[bit] @@ -340,7 +340,7 @@ func (dag *BlockDAG) initThresholdCaches() error { if dag.isCurrent() { // Warn if a high enough percentage of the last blocks have // unexpected versions. - bestNode := dag.SelectedTip() + bestNode := dag.selectedTip() if err := dag.warnUnknownVersions(bestNode); err != nil { return err } diff --git a/blockdag/utxoset.go b/blockdag/utxoset.go index 0faf6a7e3..80d736346 100644 --- a/blockdag/utxoset.go +++ b/blockdag/utxoset.go @@ -461,6 +461,7 @@ func (fus *FullUTXOSet) clone() UTXOSet { return &FullUTXOSet{utxoCollection: fus.utxoCollection.clone()} } +// Get returns the UTXOEntry associated with the given OutPoint, and a boolean indicating if such entry was found func (fus *FullUTXOSet) Get(outPoint wire.OutPoint) (*UTXOEntry, bool) { utxoEntry, ok := fus.utxoCollection[outPoint] return utxoEntry, ok diff --git a/blockdag/validate.go b/blockdag/validate.go index 075a881e0..6e18c0e51 100644 --- a/blockdag/validate.go +++ b/blockdag/validate.go @@ -1093,7 +1093,7 @@ func (dag *BlockDAG) CheckConnectBlockTemplate(block *util.Block) error { return err } - err = dag.checkBlockContext(block, parents, dag.SelectedTip(), flags) + err = dag.checkBlockContext(block, parents, dag.selectedTip(), flags) if err != nil { return err } diff --git a/blockdag/validate_test.go b/blockdag/validate_test.go index 3fa9e8280..77cb09f3c 100644 --- a/blockdag/validate_test.go +++ b/blockdag/validate_test.go @@ -526,7 +526,7 @@ func TestPastMedianTime(t *testing.T) { dagconfig.MainNetParams.K) header := node.Header() - err := dag.checkBlockHeaderContext(&header, node.parents.bluest(), height, BFNone) + err := dag.checkBlockHeaderContext(header, node.parents.bluest(), height, BFNone) if err != nil { t.Errorf("TestPastMedianTime: unexpected error from checkBlockHeaderContext: %v"+ "(a block with timestamp equals to past median time should be valid)", err) @@ -541,7 +541,7 @@ func TestPastMedianTime(t *testing.T) { dagconfig.MainNetParams.K) header = node.Header() - err = dag.checkBlockHeaderContext(&header, node.parents.bluest(), height, BFNone) + err = dag.checkBlockHeaderContext(header, node.parents.bluest(), height, BFNone) if err != nil { t.Errorf("TestPastMedianTime: unexpected error from checkBlockHeaderContext: %v"+ "(a block with timestamp bigger than past median time should be valid)", err) @@ -556,7 +556,7 @@ func TestPastMedianTime(t *testing.T) { dagconfig.MainNetParams.K) header = node.Header() - err = dag.checkBlockHeaderContext(&header, node.parents.bluest(), height, BFNone) + err = dag.checkBlockHeaderContext(header, node.parents.bluest(), height, BFNone) if err == nil { t.Errorf("TestPastMedianTime: unexpected success: block should be invalid if its timestamp is before past median time") } diff --git a/blockdag/versionbits.go b/blockdag/versionbits.go index 07860a14a..d4a9599c8 100644 --- a/blockdag/versionbits.go +++ b/blockdag/versionbits.go @@ -221,7 +221,7 @@ func (dag *BlockDAG) calcNextBlockVersion(prevNode *blockNode) (int32, error) { // This function is safe for concurrent access. func (dag *BlockDAG) CalcNextBlockVersion() (int32, error) { dag.dagLock.Lock() - version, err := dag.calcNextBlockVersion(dag.SelectedTip()) + version, err := dag.calcNextBlockVersion(dag.selectedTip()) dag.dagLock.Unlock() return version, err } diff --git a/config/config.go b/config/config.go index 00f8650f4..c824900b7 100644 --- a/config/config.go +++ b/config/config.go @@ -24,7 +24,6 @@ import ( "github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/dagconfig/daghash" "github.com/daglabs/btcd/database" - _ "github.com/daglabs/btcd/database/ffldb" "github.com/daglabs/btcd/logger" "github.com/daglabs/btcd/mempool" "github.com/daglabs/btcd/util" @@ -65,13 +64,13 @@ const ( ) var ( - DefaultHomeDir = util.AppDataDir("btcd", false) - defaultConfigFile = filepath.Join(DefaultHomeDir, defaultConfigFilename) - defaultDataDir = filepath.Join(DefaultHomeDir, defaultDataDirname) + defaultHomeDir = util.AppDataDir("btcd", false) + defaultConfigFile = filepath.Join(defaultHomeDir, defaultConfigFilename) + defaultDataDir = filepath.Join(defaultHomeDir, defaultDataDirname) knownDbTypes = database.SupportedDrivers() - defaultRPCKeyFile = filepath.Join(DefaultHomeDir, "rpc.key") - defaultRPCCertFile = filepath.Join(DefaultHomeDir, "rpc.cert") - defaultLogDir = filepath.Join(DefaultHomeDir, defaultLogDirname) + defaultRPCKeyFile = filepath.Join(defaultHomeDir, "rpc.key") + defaultRPCCertFile = filepath.Join(defaultHomeDir, "rpc.cert") + defaultLogDir = filepath.Join(defaultHomeDir, defaultLogDirname) ) // activeNetParams is a pointer to the parameters specific to the @@ -191,7 +190,7 @@ type serviceOptions struct { func cleanAndExpandPath(path string) string { // Expand initial ~ to OS specific home directory. if strings.HasPrefix(path, "~") { - homeDir := filepath.Dir(DefaultHomeDir) + homeDir := filepath.Dir(defaultHomeDir) path = strings.Replace(path, "~", homeDir, 1) } @@ -405,7 +404,7 @@ func loadConfig() (*Config, []string, error) { // Create the home directory if it doesn't already exist. funcName := "loadConfig" - err = os.MkdirAll(DefaultHomeDir, 0700) + err = os.MkdirAll(defaultHomeDir, 0700) if err != nil { // Show a nicer error message if it's because a symlink is // linked to a directory that does not exist (probably because diff --git a/dagconfig/daghash/hash.go b/dagconfig/daghash/hash.go index 86fcc5b6d..53abdd019 100644 --- a/dagconfig/daghash/hash.go +++ b/dagconfig/daghash/hash.go @@ -35,6 +35,7 @@ func (hash Hash) String() string { return hex.EncodeToString(hash[:]) } +// Strings returns a slice of strings representing the hashes in the given slice of hashes func Strings(hashes []Hash) []string { strings := make([]string, len(hashes)) for i, hash := range hashes { diff --git a/docker/Dockerfile b/docker/Dockerfile index 81bfd7994..374925393 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -22,7 +22,7 @@ COPY . . RUN TEST_DIRS=`go list -f {{.Dir}} ./... | grep -v /vendor/` RUN GOFMT_RESULT=`gofmt -l $TEST_DIRS`; echo $GOFMT_RESULT; test -z "$GOFMT_RESULT" RUN go vet ./... -# RUN golint -set_exit_status $TEST_DIRS +RUN golint -set_exit_status $TEST_DIRS # RUN aligncheck ./... # RUN structcheck -e ./... # RUN varcheck -e ./... @@ -42,4 +42,4 @@ COPY --from=build /go/src/github.com/daglabs/btcd/btcd /app/ COPY --from=build /go/src/github.com/daglabs/btcd/version.txt /app/ USER nobody -ENTRYPOINT [ "/sbin/tini", "--" ] \ No newline at end of file +ENTRYPOINT [ "/sbin/tini", "--" ] diff --git a/mining/mining.go b/mining/mining.go index b11050065..eb14e09ce 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -698,7 +698,7 @@ mempoolLoop: // Calculate the required difficulty for the block. The timestamp // is potentially adjusted to ensure it comes after the median time of // the last several blocks per the chain consensus rules. - ts := medianAdjustedTime(g.dag.SelectedTip().CalcPastMedianTime(), g.timeSource) + ts := medianAdjustedTime(g.dag.CalcPastMedianTime(), g.timeSource) reqDifficulty, err := g.dag.CalcNextRequiredDifficulty(ts) if err != nil { return nil, err diff --git a/server/p2p/p2p.go b/server/p2p/p2p.go index 870e800a3..d7fde4240 100644 --- a/server/p2p/p2p.go +++ b/server/p2p/p2p.go @@ -721,7 +721,7 @@ func (sp *Peer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) { // Send found headers to the requesting peer. blockHeaders := make([]*wire.BlockHeader, len(headers)) for i := range headers { - blockHeaders[i] = &headers[i] + blockHeaders[i] = headers[i] } sp.QueueMessage(&wire.MsgHeaders{Headers: blockHeaders}, nil) } @@ -2437,7 +2437,7 @@ func NewServer(listenAddrs []string, db database.DB, dagParams *dagconfig.Params }, DAGParams: dagParams, BestHeight: func() int32 { return s.DAG.Height() }, //TODO: (Ori) This is probably wrong. Done only for compilation - MedianTimePast: func() time.Time { return s.DAG.SelectedTip().CalcPastMedianTime() }, + MedianTimePast: func() time.Time { return s.DAG.CalcPastMedianTime() }, CalcSequenceLock: func(tx *util.Tx, utxoSet blockdag.UTXOSet) (*blockdag.SequenceLock, error) { return s.DAG.CalcSequenceLock(tx, utxoSet, true) }, diff --git a/server/rpc/rpcadapters.go b/server/rpc/rpcadapters.go index 1175329d8..07522a66f 100644 --- a/server/rpc/rpcadapters.go +++ b/server/rpc/rpcadapters.go @@ -275,6 +275,6 @@ func (b *rpcSyncMgr) SyncPeerID() int32 { // // This function is safe for concurrent access and is part of the // rpcserverSyncManager interface implementation. -func (b *rpcSyncMgr) LocateHeaders(locators []*daghash.Hash, hashStop *daghash.Hash) []wire.BlockHeader { +func (b *rpcSyncMgr) LocateHeaders(locators []*daghash.Hash, hashStop *daghash.Hash) []*wire.BlockHeader { return b.server.DAG.LocateHeaders(locators, hashStop) } diff --git a/server/rpc/rpcserver.go b/server/rpc/rpcserver.go index aa3b3295e..eaa80bdad 100644 --- a/server/rpc/rpcserver.go +++ b/server/rpc/rpcserver.go @@ -1206,7 +1206,7 @@ func handleGetBlockDAGInfo(s *Server, cmd interface{}, closeChan <-chan struct{} Headers: dag.Height(), //TODO: (Ori) This is wrong. Done only for compilation TipHashes: daghash.Strings(dag.TipHashes()), Difficulty: getDifficultyRatio(dag.CurrentBits(), params), - MedianTime: dag.SelectedTip().CalcPastMedianTime().Unix(), + MedianTime: dag.CalcPastMedianTime().Unix(), Pruned: false, Bip9SoftForks: make(map[string]*btcjson.Bip9SoftForkDescription), } @@ -1559,7 +1559,7 @@ func (state *gbtWorkState) updateBlockTemplate(s *Server, useCoinbaseValue bool) // Get the minimum allowed timestamp for the block based on the // median timestamp of the last several blocks per the chain // consensus rules. - minTimestamp := mining.MinimumMedianTime(s.cfg.DAG.SelectedTip().CalcPastMedianTime()) + minTimestamp := mining.MinimumMedianTime(s.cfg.DAG.CalcPastMedianTime()) // Update work state to ensure another block template isn't // generated until needed. @@ -2202,7 +2202,7 @@ func handleGetCurrentNet(s *Server, cmd interface{}, closeChan <-chan struct{}) // handleGetDifficulty implements the getDifficulty command. func handleGetDifficulty(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { - return getDifficultyRatio(s.cfg.DAG.SelectedTip().Header().Bits, s.cfg.DAGParams), nil + return getDifficultyRatio(s.cfg.DAG.SelectedTipHeader().Bits, s.cfg.DAGParams), nil } // handleGetGenerate implements the getGenerate command. @@ -2516,7 +2516,7 @@ func handleGetRawTransaction(s *Server, cmd interface{}, closeChan <-chan struct return nil, internalRPCError(err.Error(), context) } - blkHeader = &header + blkHeader = header blkHashStr = blkHash.String() dagHeight = s.cfg.DAG.Height() } @@ -3146,7 +3146,7 @@ func handleSearchRawTransactions(s *Server, cmd interface{}, closeChan <-chan st return nil, internalRPCError(err.Error(), context) } - blkHeader = &header + blkHeader = header blkHashStr = blkHash.String() blkHeight = height } @@ -4070,7 +4070,7 @@ type rpcserverSyncManager interface { // block in the provided locators until the provided stop hash or the // current tip is reached, up to a max of wire.MaxBlockHeadersPerMsg // hashes. - LocateHeaders(locators []*daghash.Hash, hashStop *daghash.Hash) []wire.BlockHeader + LocateHeaders(locators []*daghash.Hash, hashStop *daghash.Hash) []*wire.BlockHeader } // rpcserverConfig is a descriptor containing the RPC server configuration. @@ -4213,7 +4213,7 @@ func NewRPCServer( gbtWorkState: newGbtWorkState(cfg.TimeSource), helpCacher: newHelpCacher(), requestProcessShutdown: make(chan struct{}), - quit: make(chan int), + quit: make(chan int), } if config.MainConfig().RPCUser != "" && config.MainConfig().RPCPass != "" { login := config.MainConfig().RPCUser + ":" + config.MainConfig().RPCPass diff --git a/util/hdkeychain/extendedkey.go b/util/hdkeychain/extendedkey.go index 19615afd2..d481f17c7 100644 --- a/util/hdkeychain/extendedkey.go +++ b/util/hdkeychain/extendedkey.go @@ -363,11 +363,13 @@ func (k *ExtendedKey) Neuter() (*ExtendedKey, error) { k.depth, k.childNum, false), nil } +// HDKeyIDPair represents a pair of public and private key IDs type HDKeyIDPair struct { PrivateKeyID [4]byte PublicKeyID [4]byte } +// HDKeyPairs for all kinds of nets var ( HDKeyPairMainNet = HDKeyIDPair{ PrivateKeyID: [4]byte{0x04, 0x88, 0xad, 0xe4}, // starts with xprv @@ -387,6 +389,7 @@ var ( } ) +// RegisterHDKeyIDPair registers an HDKeyIDPair in the private to public key map func RegisterHDKeyIDPair(hdKeyIDPair HDKeyIDPair) { hdPrivToPubKeyIDs[hdKeyIDPair.PrivateKeyID] = hdKeyIDPair.PublicKeyID[:] }