From 70908f9587c158947436a4358da7c34f8e4ec2c9 Mon Sep 17 00:00:00 2001 From: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Date: Wed, 1 Aug 2018 14:11:00 +0800 Subject: [PATCH] get/set mining addr (#1195) * get mining address * Set mining addr * go fmt * Fix CI * Avoid mining to null addr * Prevent mining to null addr for api * clean vendor * format get/setMiningAddress func * Update if statements format * Combine * go fmt * clean GetMiningAddress() * compact IF statements * compact IF statements * revert * SetMiningAddress for non-local address * combine * go fmt * private getProgramByAddress() * Avoid mining to nil addr for get-work * Roll back * Fix CI * tweak func seq --- Makefile | 2 +- account/accounts.go | 101 ++- api/accounts.go | 27 + api/api.go | 3 + api/api_test.go | 26 +- api/message.go | 2 +- api/miner.go | 3 + mining/miningpool/minepool.go | 1 + node/node.go | 7 +- vendor/github.com/btcsuite/btcd/mining/README.md | 21 - .../btcsuite/btcd/mining/cpuminer/README.md | 24 - .../btcsuite/btcd/mining/cpuminer/cpuminer.go | 642 -------------- .../btcsuite/btcd/mining/cpuminer/log.go | 30 - vendor/github.com/btcsuite/btcd/mining/log.go | 30 - vendor/github.com/btcsuite/btcd/mining/mining.go | 969 --------------------- .../github.com/btcsuite/btcd/mining/mining_test.go | 110 --- vendor/github.com/btcsuite/btcd/mining/policy.go | 133 --- .../github.com/btcsuite/btcd/mining/policy_test.go | 168 ---- 18 files changed, 130 insertions(+), 2169 deletions(-) delete mode 100644 vendor/github.com/btcsuite/btcd/mining/README.md delete mode 100644 vendor/github.com/btcsuite/btcd/mining/cpuminer/README.md delete mode 100644 vendor/github.com/btcsuite/btcd/mining/cpuminer/cpuminer.go delete mode 100644 vendor/github.com/btcsuite/btcd/mining/cpuminer/log.go delete mode 100644 vendor/github.com/btcsuite/btcd/mining/log.go delete mode 100644 vendor/github.com/btcsuite/btcd/mining/mining.go delete mode 100644 vendor/github.com/btcsuite/btcd/mining/mining_test.go delete mode 100644 vendor/github.com/btcsuite/btcd/mining/policy.go delete mode 100644 vendor/github.com/btcsuite/btcd/mining/policy_test.go diff --git a/Makefile b/Makefile index 59e34487..d62cb4b4 100644 --- a/Makefile +++ b/Makefile @@ -129,4 +129,4 @@ functional-tests: ci: test functional-tests -.PHONY: all target release-all clean test benchmark \ No newline at end of file +.PHONY: all target release-all clean test benchmark diff --git a/account/accounts.go b/account/accounts.go index 59908688..34858d18 100644 --- a/account/accounts.go +++ b/account/accounts.go @@ -46,8 +46,9 @@ var ( ErrFindCtrlProgram = errors.New("fail to find account control program") ) -func aliasKey(name string) []byte { - return append(aliasPrefix, []byte(name)...) +// ContractKey account control promgram store prefix +func ContractKey(hash common.Hash) []byte { + return append(contractPrefix, hash[:]...) } // Key account store prefix @@ -55,9 +56,8 @@ func Key(name string) []byte { return append(accountPrefix, []byte(name)...) } -// ContractKey account control promgram store prefix -func ContractKey(hash common.Hash) []byte { - return append(contractPrefix, hash[:]...) +func aliasKey(name string) []byte { + return append(aliasPrefix, []byte(name)...) } func contractIndexKey(accountID string) []byte { @@ -247,16 +247,28 @@ func (m *Manager) GetAliasByID(id string) string { // GetCoinbaseControlProgram will return a coinbase script func (m *Manager) GetCoinbaseControlProgram() ([]byte, error) { + cp, err := m.GetCoinbaseCtrlProgram() + if err == ErrFindAccount { + log.Warningf("GetCoinbaseControlProgram: can't find any account in db") + return vmutil.DefaultCoinbaseProgram() + } + if err != nil { + return nil, err + } + return cp.ControlProgram, nil +} + +// GetCoinbaseCtrlProgram will return the coinbase CtrlProgram +func (m *Manager) GetCoinbaseCtrlProgram() (*CtrlProgram, error) { if data := m.db.Get(miningAddressKey); data != nil { cp := &CtrlProgram{} - return cp.ControlProgram, json.Unmarshal(data, cp) + return cp, json.Unmarshal(data, cp) } accountIter := m.db.IteratorPrefix([]byte(accountPrefix)) defer accountIter.Release() if !accountIter.Next() { - log.Warningf("GetCoinbaseControlProgram: can't find any account in db") - return vmutil.DefaultCoinbaseProgram() + return nil, ErrFindAccount } account := &Account{} @@ -275,7 +287,7 @@ func (m *Manager) GetCoinbaseControlProgram() ([]byte, error) { } m.db.Set(miningAddressKey, rawCP) - return program.ControlProgram, nil + return program, nil } // GetContractIndex return the current index @@ -290,23 +302,9 @@ func (m *Manager) GetContractIndex(accountID string) uint64 { return index } -// GetProgramByAddress return CtrlProgram by given address -func (m *Manager) GetProgramByAddress(address string) (*CtrlProgram, error) { - addr, err := common.DecodeAddress(address, &consensus.ActiveNetParams) - if err != nil { - return nil, err - } - - redeemContract := addr.ScriptAddress() - program := []byte{} - switch addr.(type) { - case *common.AddressWitnessPubKeyHash: - program, err = vmutil.P2WPKHProgram(redeemContract) - case *common.AddressWitnessScriptHash: - program, err = vmutil.P2WSHProgram(redeemContract) - default: - return nil, ErrInvalidAddress - } +// GetLocalCtrlProgramByAddress return CtrlProgram by given address +func (m *Manager) GetLocalCtrlProgramByAddress(address string) (*CtrlProgram, error) { + program, err := m.getProgramByAddress(address) if err != nil { return nil, err } @@ -322,6 +320,15 @@ func (m *Manager) GetProgramByAddress(address string) (*CtrlProgram, error) { return cp, json.Unmarshal(rawProgram, cp) } +// GetMiningAddress will return the mining address +func (m *Manager) GetMiningAddress() (string, error) { + cp, err := m.GetCoinbaseCtrlProgram() + if err != nil { + return "", err + } + return cp.Address, nil +} + // IsLocalControlProgram check is the input control program belong to local func (m *Manager) IsLocalControlProgram(prog []byte) bool { var hash common.Hash @@ -378,6 +385,26 @@ func (m *Manager) RemoveUnconfirmedUtxo(hashes []*bc.Hash) { m.utxoKeeper.RemoveUnconfirmedUtxo(hashes) } +// SetMiningAddress will set the mining address +func (m *Manager) SetMiningAddress(miningAddress string) (string, error) { + program, err := m.getProgramByAddress(miningAddress) + if err != nil { + return "", err + } + + cp := &CtrlProgram{ + Address: miningAddress, + ControlProgram: program, + } + rawCP, err := json.Marshal(cp) + if err != nil { + return "", err + } + + m.db.Set(miningAddressKey, rawCP) + return m.GetMiningAddress() +} + // CreateAddress generate an address for the select account func (m *Manager) createAddress(account *Account, change bool) (cp *CtrlProgram, err error) { if len(account.XPubs) == 1 { @@ -471,6 +498,28 @@ func (m *Manager) getNextContractIndex(accountID string) uint64 { return nextIndex } +func (m *Manager) getProgramByAddress(address string) ([]byte, error) { + addr, err := common.DecodeAddress(address, &consensus.ActiveNetParams) + if err != nil { + return nil, err + } + + redeemContract := addr.ScriptAddress() + program := []byte{} + switch addr.(type) { + case *common.AddressWitnessPubKeyHash: + program, err = vmutil.P2WPKHProgram(redeemContract) + case *common.AddressWitnessScriptHash: + program, err = vmutil.P2WSHProgram(redeemContract) + default: + return nil, ErrInvalidAddress + } + if err != nil { + return nil, err + } + return program, nil +} + func (m *Manager) insertControlPrograms(progs ...*CtrlProgram) error { var hash common.Hash for _, prog := range progs { diff --git a/api/accounts.go b/api/accounts.go index a6560e6a..cd00d211 100644 --- a/api/accounts.go +++ b/api/accounts.go @@ -138,3 +138,30 @@ func (a *API) listAddresses(ctx context.Context, ins struct { sort.Sort(SortByIndex(addresses)) return NewSuccessResponse(addresses) } + +type minigAddressResp struct { + MiningAddress string `json:"mining_address"` +} + +func (a *API) getMiningAddress(ctx context.Context) Response { + miningAddress, err := a.wallet.AccountMgr.GetMiningAddress() + if err != nil { + return NewErrorResponse(err) + } + return NewSuccessResponse(minigAddressResp{ + MiningAddress: miningAddress, + }) +} + +// POST /set-mining-address +func (a *API) setMiningAddress(ctx context.Context, in struct { + MiningAddress string `json:"mining_address"` +}) Response { + miningAddress, err := a.wallet.AccountMgr.SetMiningAddress(in.MiningAddress) + if err != nil { + return NewErrorResponse(err) + } + return NewSuccessResponse(minigAddressResp{ + MiningAddress: miningAddress, + }) +} diff --git a/api/api.go b/api/api.go index 3882a611..0ccfa3b1 100644 --- a/api/api.go +++ b/api/api.go @@ -204,6 +204,9 @@ func (a *API) buildHandler() { m.Handle("/validate-address", jsonHandler(a.validateAddress)) m.Handle("/list-pubkeys", jsonHandler(a.listPubKeys)) + m.Handle("/get-mining-address", jsonHandler(a.getMiningAddress)) + m.Handle("/set-mining-address", jsonHandler(a.setMiningAddress)) + m.Handle("/create-asset", jsonHandler(a.createAsset)) m.Handle("/update-asset-alias", jsonHandler(a.updateAssetAlias)) m.Handle("/get-asset", jsonHandler(a.getAsset)) diff --git a/api/api_test.go b/api/api_test.go index 1060e9fe..4e633b31 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -13,8 +13,8 @@ import ( "github.com/bytom/accesstoken" "github.com/bytom/blockchain/rpc" "github.com/bytom/blockchain/txbuilder" - "github.com/bytom/testutil" "github.com/bytom/consensus" + "github.com/bytom/testutil" ) func TestAPIHandler(t *testing.T) { @@ -132,24 +132,24 @@ func TestEstimateTxGasRange(t *testing.T) { respWant *EstimateTxGasResp }{ { - path: "/estimate-transaction-gas", - tmplStr: `{"raw_transaction":"070100010160015e9a4e2bbae57dd71b6a827fb50aaeb744ce3ae6f45c4aec7494ad097213220e8affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0cea1bc5800011600144a6322008c5424251c7502c7d7d55f6389c3c358010001013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086f29b3301160014fa61b0629e5f2da2bb8b08e7fc948dbd265234f700","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":1,"keys":[{"xpub":"19204fe9172cb0eeae86b39ec7a61ddc556656c8df08fd43ef6074296f32b347349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257","derivation_path":["010100000000000000","0700000000000000"]}],"signatures":null},{"type":"data","value":"a527a92a7488c010bc42b39d6b50f0822183e51efab228af8ca8ca81ca459237"}]}],"allow_additional_actions":false}`, - respWant: &EstimateTxGasResp{ - TotalNeu: 2095 * consensus.VMGasRate, + path: "/estimate-transaction-gas", + tmplStr: `{"raw_transaction":"070100010160015e9a4e2bbae57dd71b6a827fb50aaeb744ce3ae6f45c4aec7494ad097213220e8affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0cea1bc5800011600144a6322008c5424251c7502c7d7d55f6389c3c358010001013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086f29b3301160014fa61b0629e5f2da2bb8b08e7fc948dbd265234f700","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":1,"keys":[{"xpub":"19204fe9172cb0eeae86b39ec7a61ddc556656c8df08fd43ef6074296f32b347349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257","derivation_path":["010100000000000000","0700000000000000"]}],"signatures":null},{"type":"data","value":"a527a92a7488c010bc42b39d6b50f0822183e51efab228af8ca8ca81ca459237"}]}],"allow_additional_actions":false}`, + respWant: &EstimateTxGasResp{ + TotalNeu: 2095 * consensus.VMGasRate, }, }, { - path: "/estimate-transaction-gas", - tmplStr: `{"raw_transaction":"07010001016d016bcf24f1471d67c25a01ac84482ecdd8550229180171cae22321f87fe43d4f6a13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086a6d5f2020001220020713ef71e6087a58d6055ce81e8a8ea8a60ca19aef77923859e53a1fa9df0042989010240844b99bab9f393e89ca3bb272b1ba146852124f13a2d37fc47da6a7320f5ae1a4b6df1322750906ad480796db663e35ef7fd9544718eea08e51c5388f9813d0446ae20bd609e953918ab2ce120c43486894ff38dc4b65c2c1b4e19f6b41265d76b062120508684f922c1e5eea3dcbd592b00d297b2ddf92d35d5acabea9ff491ef514abe5152ad02014affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80bef6b4cd0201220020dc794f041d19c67108a05d2a6d797a2b12029f31b2c91ec699c9477727f25315000149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80fef9b123012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac6600","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":1,"keys":[{"xpub":"5ff7f79f0fd4eb9ccb17191b0a1ac9bed5b4a03320a06d2ff8170dd51f9ad9089c4038ec7280b5eb6745ef3d36284e67f5cf2ed2a0177d462d24abf53c0399ed","derivationPath":["010200000000000000","0400000000000000"]},{"xpub":"d0e7607bec7f68ea9135fbb9e3e94ef05a034d28be847070740fcba9454a749f6e21942cfef90f1437184cb70775beb290c13852c1497631dbcb137f74788e4f","derivationPath":["010200000000000000","0400000000000000"]}],"signatures":["","844b99bab9f393e89ca3bb272b1ba146852124f13a2d37fc47da6a7320f5ae1a4b6df1322750906ad480796db663e35ef7fd9544718eea08e51c5388f9813d04"]},{"type":"data","value":"ae20bd609e953918ab2ce120c43486894ff38dc4b65c2c1b4e19f6b41265d76b062120508684f922c1e5eea3dcbd592b00d297b2ddf92d35d5acabea9ff491ef514abe5152ad"}]}],"allow_additional_actions":false}`, - respWant: &EstimateTxGasResp{ - TotalNeu: 3305 * consensus.VMGasRate, + path: "/estimate-transaction-gas", + tmplStr: `{"raw_transaction":"07010001016d016bcf24f1471d67c25a01ac84482ecdd8550229180171cae22321f87fe43d4f6a13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086a6d5f2020001220020713ef71e6087a58d6055ce81e8a8ea8a60ca19aef77923859e53a1fa9df0042989010240844b99bab9f393e89ca3bb272b1ba146852124f13a2d37fc47da6a7320f5ae1a4b6df1322750906ad480796db663e35ef7fd9544718eea08e51c5388f9813d0446ae20bd609e953918ab2ce120c43486894ff38dc4b65c2c1b4e19f6b41265d76b062120508684f922c1e5eea3dcbd592b00d297b2ddf92d35d5acabea9ff491ef514abe5152ad02014affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80bef6b4cd0201220020dc794f041d19c67108a05d2a6d797a2b12029f31b2c91ec699c9477727f25315000149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80fef9b123012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac6600","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":1,"keys":[{"xpub":"5ff7f79f0fd4eb9ccb17191b0a1ac9bed5b4a03320a06d2ff8170dd51f9ad9089c4038ec7280b5eb6745ef3d36284e67f5cf2ed2a0177d462d24abf53c0399ed","derivationPath":["010200000000000000","0400000000000000"]},{"xpub":"d0e7607bec7f68ea9135fbb9e3e94ef05a034d28be847070740fcba9454a749f6e21942cfef90f1437184cb70775beb290c13852c1497631dbcb137f74788e4f","derivationPath":["010200000000000000","0400000000000000"]}],"signatures":["","844b99bab9f393e89ca3bb272b1ba146852124f13a2d37fc47da6a7320f5ae1a4b6df1322750906ad480796db663e35ef7fd9544718eea08e51c5388f9813d04"]},{"type":"data","value":"ae20bd609e953918ab2ce120c43486894ff38dc4b65c2c1b4e19f6b41265d76b062120508684f922c1e5eea3dcbd592b00d297b2ddf92d35d5acabea9ff491ef514abe5152ad"}]}],"allow_additional_actions":false}`, + respWant: &EstimateTxGasResp{ + TotalNeu: 3305 * consensus.VMGasRate, }, }, { - path: "/estimate-transaction-gas", - tmplStr: `{"raw_transaction":"07010002016c016acf24f1471d67c25a01ac84482ecdd8550229180171cae22321f87fe43d4f6a13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b4c4c32101012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66ef020440f5baa1530bd7ded5c37f1c91360e28e736c91a7933eff961d68eebf90bdce63eb4361689759a8aa420256af565e38921985026de8d27dd7b66f0d01c90170a0440b23b44f62f3e97bcbd5f80cb9bb3d63cb154c62d402851e5b4d5d89849fef74271c8c38f594b944b75222d06ef18bddec4b6278ad3185f72ac5321ce5948e90940a00b096eef5b3bed5c6a2843d29e1820ef1413947d3e278c21cc70976c47976d1159468f071bf853b244be8f6cc55d78615ea6594c946f1a6e6622d8e9d42206a901ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad016c016a158f56c5673a52876bbbed4cd8724428b43a8d9ddd2a759c9df06b46898f101affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80fef9b12301012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66ef020440c3c4fdbe99f9266a42df767cf03c22d9d09096446a8882b9d0c0076d9c85da28add31320705452fb566a091515cedb1ea9966647201236a0da13a020f848b8084043e22fe631cee95e3185ecd0c6fc4a262689d674725abe7d7f3158d8d43c776338edeec76600776fc0dcee280bd7a1a8a2b23909c6cefa7fbb55c27522b6100640fefe403941035a66ba9b6d097dfe0ada68ae6d006272928fad2ba23341fe878690e9e2fa1d2d3992c16aa20125fb2da7f7687920c12a36e4964533ceeccd3602a901ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad020149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80ea8ed51f01220020036f3d1665dc802fd36aded656c2f4b2b2c5b00e86c44f5352257b718941a4e9000149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80fef9b12301220020e402787b2bf9749f8fcdcc132a44e86bacf36780ec5df2189a11020d590533ee00","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":3,"keys":[{"xpub":"5ff7f79f0fd4eb9ccb17191b0a1ac9bed5b4a03320a06d2ff8170dd51f9ad9089c4038ec7280b5eb6745ef3d36284e67f5cf2ed2a0177d462d24abf53c0399ed","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"7d1c7a9094ab23f432e60afbbfe2791ba9ab3daba8aaa544634218243b8659985cb0ae9fe2b0f5da8a84c6b117c9491bf38f5e59b0d05642d90ba34cf7611eec","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"b0d2d90cdee01976d51b55963ae214493708d8db44f7516d2d4853a542cba4c07fbd0ad3e7a9ff4b6fbe6b71e66f4538a9424eaf15f538d958aa7025f5f752dc","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"d0e7607bec7f68ea9135fbb9e3e94ef05a034d28be847070740fcba9454a749f6e21942cfef90f1437184cb70775beb290c13852c1497631dbcb137f74788e4f","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"e18b9d219e960d761e8d03290acddb5211fea1140c87663908ea74f212763ca8d809bb0fe861884e662429564fa0f2725b5787175054c17685a83a68e160344d","derivationPath":["010300000000000000","0100000000000000"]}],"signatures":["","f5baa1530bd7ded5c37f1c91360e28e736c91a7933eff961d68eebf90bdce63eb4361689759a8aa420256af565e38921985026de8d27dd7b66f0d01c90170a04","b23b44f62f3e97bcbd5f80cb9bb3d63cb154c62d402851e5b4d5d89849fef74271c8c38f594b944b75222d06ef18bddec4b6278ad3185f72ac5321ce5948e909","a00b096eef5b3bed5c6a2843d29e1820ef1413947d3e278c21cc70976c47976d1159468f071bf853b244be8f6cc55d78615ea6594c946f1a6e6622d8e9d42206",""]},{"type":"data","value":"ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad"}]},{"position":1,"witness_components":[{"type":"raw_tx_signature","quorum":3,"keys":[{"xpub":"5ff7f79f0fd4eb9ccb17191b0a1ac9bed5b4a03320a06d2ff8170dd51f9ad9089c4038ec7280b5eb6745ef3d36284e67f5cf2ed2a0177d462d24abf53c0399ed","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"7d1c7a9094ab23f432e60afbbfe2791ba9ab3daba8aaa544634218243b8659985cb0ae9fe2b0f5da8a84c6b117c9491bf38f5e59b0d05642d90ba34cf7611eec","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"b0d2d90cdee01976d51b55963ae214493708d8db44f7516d2d4853a542cba4c07fbd0ad3e7a9ff4b6fbe6b71e66f4538a9424eaf15f538d958aa7025f5f752dc","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"d0e7607bec7f68ea9135fbb9e3e94ef05a034d28be847070740fcba9454a749f6e21942cfef90f1437184cb70775beb290c13852c1497631dbcb137f74788e4f","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"e18b9d219e960d761e8d03290acddb5211fea1140c87663908ea74f212763ca8d809bb0fe861884e662429564fa0f2725b5787175054c17685a83a68e160344d","derivationPath":["010300000000000000","0100000000000000"]}],"signatures":["","c3c4fdbe99f9266a42df767cf03c22d9d09096446a8882b9d0c0076d9c85da28add31320705452fb566a091515cedb1ea9966647201236a0da13a020f848b808","43e22fe631cee95e3185ecd0c6fc4a262689d674725abe7d7f3158d8d43c776338edeec76600776fc0dcee280bd7a1a8a2b23909c6cefa7fbb55c27522b61006","fefe403941035a66ba9b6d097dfe0ada68ae6d006272928fad2ba23341fe878690e9e2fa1d2d3992c16aa20125fb2da7f7687920c12a36e4964533ceeccd3602",""]},{"type":"data","value":"ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad"}]}],"allow_additional_actions":false}`, - respWant: &EstimateTxGasResp{ - TotalNeu: 13556 * consensus.VMGasRate, + path: "/estimate-transaction-gas", + tmplStr: `{"raw_transaction":"07010002016c016acf24f1471d67c25a01ac84482ecdd8550229180171cae22321f87fe43d4f6a13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b4c4c32101012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66ef020440f5baa1530bd7ded5c37f1c91360e28e736c91a7933eff961d68eebf90bdce63eb4361689759a8aa420256af565e38921985026de8d27dd7b66f0d01c90170a0440b23b44f62f3e97bcbd5f80cb9bb3d63cb154c62d402851e5b4d5d89849fef74271c8c38f594b944b75222d06ef18bddec4b6278ad3185f72ac5321ce5948e90940a00b096eef5b3bed5c6a2843d29e1820ef1413947d3e278c21cc70976c47976d1159468f071bf853b244be8f6cc55d78615ea6594c946f1a6e6622d8e9d42206a901ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad016c016a158f56c5673a52876bbbed4cd8724428b43a8d9ddd2a759c9df06b46898f101affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80fef9b12301012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66ef020440c3c4fdbe99f9266a42df767cf03c22d9d09096446a8882b9d0c0076d9c85da28add31320705452fb566a091515cedb1ea9966647201236a0da13a020f848b8084043e22fe631cee95e3185ecd0c6fc4a262689d674725abe7d7f3158d8d43c776338edeec76600776fc0dcee280bd7a1a8a2b23909c6cefa7fbb55c27522b6100640fefe403941035a66ba9b6d097dfe0ada68ae6d006272928fad2ba23341fe878690e9e2fa1d2d3992c16aa20125fb2da7f7687920c12a36e4964533ceeccd3602a901ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad020149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80ea8ed51f01220020036f3d1665dc802fd36aded656c2f4b2b2c5b00e86c44f5352257b718941a4e9000149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80fef9b12301220020e402787b2bf9749f8fcdcc132a44e86bacf36780ec5df2189a11020d590533ee00","signing_instructions":[{"position":0,"witness_components":[{"type":"raw_tx_signature","quorum":3,"keys":[{"xpub":"5ff7f79f0fd4eb9ccb17191b0a1ac9bed5b4a03320a06d2ff8170dd51f9ad9089c4038ec7280b5eb6745ef3d36284e67f5cf2ed2a0177d462d24abf53c0399ed","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"7d1c7a9094ab23f432e60afbbfe2791ba9ab3daba8aaa544634218243b8659985cb0ae9fe2b0f5da8a84c6b117c9491bf38f5e59b0d05642d90ba34cf7611eec","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"b0d2d90cdee01976d51b55963ae214493708d8db44f7516d2d4853a542cba4c07fbd0ad3e7a9ff4b6fbe6b71e66f4538a9424eaf15f538d958aa7025f5f752dc","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"d0e7607bec7f68ea9135fbb9e3e94ef05a034d28be847070740fcba9454a749f6e21942cfef90f1437184cb70775beb290c13852c1497631dbcb137f74788e4f","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"e18b9d219e960d761e8d03290acddb5211fea1140c87663908ea74f212763ca8d809bb0fe861884e662429564fa0f2725b5787175054c17685a83a68e160344d","derivationPath":["010300000000000000","0100000000000000"]}],"signatures":["","f5baa1530bd7ded5c37f1c91360e28e736c91a7933eff961d68eebf90bdce63eb4361689759a8aa420256af565e38921985026de8d27dd7b66f0d01c90170a04","b23b44f62f3e97bcbd5f80cb9bb3d63cb154c62d402851e5b4d5d89849fef74271c8c38f594b944b75222d06ef18bddec4b6278ad3185f72ac5321ce5948e909","a00b096eef5b3bed5c6a2843d29e1820ef1413947d3e278c21cc70976c47976d1159468f071bf853b244be8f6cc55d78615ea6594c946f1a6e6622d8e9d42206",""]},{"type":"data","value":"ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad"}]},{"position":1,"witness_components":[{"type":"raw_tx_signature","quorum":3,"keys":[{"xpub":"5ff7f79f0fd4eb9ccb17191b0a1ac9bed5b4a03320a06d2ff8170dd51f9ad9089c4038ec7280b5eb6745ef3d36284e67f5cf2ed2a0177d462d24abf53c0399ed","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"7d1c7a9094ab23f432e60afbbfe2791ba9ab3daba8aaa544634218243b8659985cb0ae9fe2b0f5da8a84c6b117c9491bf38f5e59b0d05642d90ba34cf7611eec","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"b0d2d90cdee01976d51b55963ae214493708d8db44f7516d2d4853a542cba4c07fbd0ad3e7a9ff4b6fbe6b71e66f4538a9424eaf15f538d958aa7025f5f752dc","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"d0e7607bec7f68ea9135fbb9e3e94ef05a034d28be847070740fcba9454a749f6e21942cfef90f1437184cb70775beb290c13852c1497631dbcb137f74788e4f","derivationPath":["010300000000000000","0100000000000000"]},{"xpub":"e18b9d219e960d761e8d03290acddb5211fea1140c87663908ea74f212763ca8d809bb0fe861884e662429564fa0f2725b5787175054c17685a83a68e160344d","derivationPath":["010300000000000000","0100000000000000"]}],"signatures":["","c3c4fdbe99f9266a42df767cf03c22d9d09096446a8882b9d0c0076d9c85da28add31320705452fb566a091515cedb1ea9966647201236a0da13a020f848b808","43e22fe631cee95e3185ecd0c6fc4a262689d674725abe7d7f3158d8d43c776338edeec76600776fc0dcee280bd7a1a8a2b23909c6cefa7fbb55c27522b61006","fefe403941035a66ba9b6d097dfe0ada68ae6d006272928fad2ba23341fe878690e9e2fa1d2d3992c16aa20125fb2da7f7687920c12a36e4964533ceeccd3602",""]},{"type":"data","value":"ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad"}]}],"allow_additional_actions":false}`, + respWant: &EstimateTxGasResp{ + TotalNeu: 13556 * consensus.VMGasRate, }, }, } diff --git a/api/message.go b/api/message.go index 213ea04a..155ace30 100644 --- a/api/message.go +++ b/api/message.go @@ -24,7 +24,7 @@ func (a *API) signMessage(ctx context.Context, ins struct { Message string `json:"message"` Password string `json:"password"` }) Response { - cp, err := a.wallet.AccountMgr.GetProgramByAddress(ins.Address) + cp, err := a.wallet.AccountMgr.GetLocalCtrlProgramByAddress(ins.Address) if err != nil { return NewErrorResponse(err) } diff --git a/api/miner.go b/api/miner.go index d0b1c27d..ece13868 100644 --- a/api/miner.go +++ b/api/miner.go @@ -139,6 +139,9 @@ func (a *API) setMining(in struct { IsMining bool `json:"is_mining"` }) Response { if in.IsMining { + if _, err := a.wallet.AccountMgr.GetMiningAddress(); err != nil { + return NewErrorResponse(errors.New("Mining address does not exist")) + } return a.startMining() } return a.stopMining() diff --git a/mining/miningpool/minepool.go b/mining/miningpool/minepool.go index e1f33767..1581e4f0 100644 --- a/mining/miningpool/minepool.go +++ b/mining/miningpool/minepool.go @@ -67,6 +67,7 @@ func (m *MiningPool) blockUpdater() { } } +// generateBlock generates a block template to mine func (m *MiningPool) generateBlock() { m.mutex.Lock() defer m.mutex.Unlock() diff --git a/node/node.go b/node/node.go index 14bd8a06..509eb2c5 100644 --- a/node/node.go +++ b/node/node.go @@ -230,7 +230,12 @@ func (n *Node) initAndstartApiServer() { func (n *Node) OnStart() error { if n.miningEnable { - n.cpuMiner.Start() + if _, err := n.wallet.AccountMgr.GetMiningAddress(); err != nil { + n.miningEnable = false + log.Error(err) + } else { + n.cpuMiner.Start() + } } if !n.config.VaultMode { n.syncManager.Start() diff --git a/vendor/github.com/btcsuite/btcd/mining/README.md b/vendor/github.com/btcsuite/btcd/mining/README.md deleted file mode 100644 index 5295215f..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/README.md +++ /dev/null @@ -1,21 +0,0 @@ -mining -====== - -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) -[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/mining) - -## Overview - -This package is currently a work in progress. - -## Installation and Updating - -```bash -$ go get -u github.com/btcsuite/btcd/mining -``` - -## License - -Package mining is licensed under the [copyfree](http://copyfree.org) ISC -License. diff --git a/vendor/github.com/btcsuite/btcd/mining/cpuminer/README.md b/vendor/github.com/btcsuite/btcd/mining/cpuminer/README.md deleted file mode 100644 index 899a5aed..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/cpuminer/README.md +++ /dev/null @@ -1,24 +0,0 @@ -cpuminer -======== - -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) -[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/mining/cpuminer) - -## Overview - -This package is currently a work in progress. It works without issue since it -is used in several of the integration tests, but the API is not really ready for -public consumption as it has simply been refactored out of the main codebase for -now. - -## Installation and Updating - -```bash -$ go get -u github.com/btcsuite/btcd/mining/cpuminer -``` - -## License - -Package cpuminer is licensed under the [copyfree](http://copyfree.org) ISC -License. diff --git a/vendor/github.com/btcsuite/btcd/mining/cpuminer/cpuminer.go b/vendor/github.com/btcsuite/btcd/mining/cpuminer/cpuminer.go deleted file mode 100644 index 3d5b3b19..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/cpuminer/cpuminer.go +++ /dev/null @@ -1,642 +0,0 @@ -// Copyright (c) 2014-2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package cpuminer - -import ( - "errors" - "fmt" - "math/rand" - "runtime" - "sync" - "time" - - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/mining" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" -) - -const ( - // maxNonce is the maximum value a nonce can be in a block header. - maxNonce = ^uint32(0) // 2^32 - 1 - - // maxExtraNonce is the maximum value an extra nonce used in a coinbase - // transaction can be. - maxExtraNonce = ^uint64(0) // 2^64 - 1 - - // hpsUpdateSecs is the number of seconds to wait in between each - // update to the hashes per second monitor. - hpsUpdateSecs = 10 - - // hashUpdateSec is the number of seconds each worker waits in between - // notifying the speed monitor with how many hashes have been completed - // while they are actively searching for a solution. This is done to - // reduce the amount of syncs between the workers that must be done to - // keep track of the hashes per second. - hashUpdateSecs = 15 -) - -var ( - // defaultNumWorkers is the default number of workers to use for mining - // and is based on the number of processor cores. This helps ensure the - // system stays reasonably responsive under heavy load. - defaultNumWorkers = uint32(runtime.NumCPU()) -) - -// Config is a descriptor containing the cpu miner configuration. -type Config struct { - // ChainParams identifies which chain parameters the cpu miner is - // associated with. - ChainParams *chaincfg.Params - - // BlockTemplateGenerator identifies the instance to use in order to - // generate block templates that the miner will attempt to solve. - BlockTemplateGenerator *mining.BlkTmplGenerator - - // MiningAddrs is a list of payment addresses to use for the generated - // blocks. Each generated block will randomly choose one of them. - MiningAddrs []btcutil.Address - - // ProcessBlock defines the function to call with any solved blocks. - // It typically must run the provided block through the same set of - // rules and handling as any other block coming from the network. - ProcessBlock func(*btcutil.Block, blockchain.BehaviorFlags) (bool, error) - - // ConnectedCount defines the function to use to obtain how many other - // peers the server is connected to. This is used by the automatic - // persistent mining routine to determine whether or it should attempt - // mining. This is useful because there is no point in mining when not - // connected to any peers since there would no be anyone to send any - // found blocks to. - ConnectedCount func() int32 - - // IsCurrent defines the function to use to obtain whether or not the - // block chain is current. This is used by the automatic persistent - // mining routine to determine whether or it should attempt mining. - // This is useful because there is no point in mining if the chain is - // not current since any solved blocks would be on a side chain and and - // up orphaned anyways. - IsCurrent func() bool -} - -// CPUMiner provides facilities for solving blocks (mining) using the CPU in -// a concurrency-safe manner. It consists of two main goroutines -- a speed -// monitor and a controller for worker goroutines which generate and solve -// blocks. The number of goroutines can be set via the SetMaxGoRoutines -// function, but the default is based on the number of processor cores in the -// system which is typically sufficient. -type CPUMiner struct { - sync.Mutex - g *mining.BlkTmplGenerator - cfg Config - numWorkers uint32 - started bool - discreteMining bool - submitBlockLock sync.Mutex - wg sync.WaitGroup - workerWg sync.WaitGroup - updateNumWorkers chan struct{} - queryHashesPerSec chan float64 - updateHashes chan uint64 - speedMonitorQuit chan struct{} - quit chan struct{} -} - -// speedMonitor handles tracking the number of hashes per second the mining -// process is performing. It must be run as a goroutine. -func (m *CPUMiner) speedMonitor() { - log.Tracef("CPU miner speed monitor started") - - var hashesPerSec float64 - var totalHashes uint64 - ticker := time.NewTicker(time.Second * hpsUpdateSecs) - defer ticker.Stop() - -out: - for { - select { - // Periodic updates from the workers with how many hashes they - // have performed. - case numHashes := <-m.updateHashes: - totalHashes += numHashes - - // Time to update the hashes per second. - case <-ticker.C: - curHashesPerSec := float64(totalHashes) / hpsUpdateSecs - if hashesPerSec == 0 { - hashesPerSec = curHashesPerSec - } - hashesPerSec = (hashesPerSec + curHashesPerSec) / 2 - totalHashes = 0 - if hashesPerSec != 0 { - log.Debugf("Hash speed: %6.0f kilohashes/s", - hashesPerSec/1000) - } - - // Request for the number of hashes per second. - case m.queryHashesPerSec <- hashesPerSec: - // Nothing to do. - - case <-m.speedMonitorQuit: - break out - } - } - - m.wg.Done() - log.Tracef("CPU miner speed monitor done") -} - -// submitBlock submits the passed block to network after ensuring it passes all -// of the consensus validation rules. -func (m *CPUMiner) submitBlock(block *btcutil.Block) bool { - m.submitBlockLock.Lock() - defer m.submitBlockLock.Unlock() - - // Ensure the block is not stale since a new block could have shown up - // while the solution was being found. Typically that condition is - // detected and all work on the stale block is halted to start work on - // a new block, but the check only happens periodically, so it is - // possible a block was found and submitted in between. - msgBlock := block.MsgBlock() - if !msgBlock.Header.PrevBlock.IsEqual(&m.g.BestSnapshot().Hash) { - log.Debugf("Block submitted via CPU miner with previous "+ - "block %s is stale", msgBlock.Header.PrevBlock) - return false - } - - // Process this block using the same rules as blocks coming from other - // nodes. This will in turn relay it to the network like normal. - isOrphan, err := m.cfg.ProcessBlock(block, blockchain.BFNone) - if err != nil { - // Anything other than a rule violation is an unexpected error, - // so log that error as an internal error. - if _, ok := err.(blockchain.RuleError); !ok { - log.Errorf("Unexpected error while processing "+ - "block submitted via CPU miner: %v", err) - return false - } - - log.Debugf("Block submitted via CPU miner rejected: %v", err) - return false - } - if isOrphan { - log.Debugf("Block submitted via CPU miner is an orphan") - return false - } - - // The block was accepted. - coinbaseTx := block.MsgBlock().Transactions[0].TxOut[0] - log.Infof("Block submitted via CPU miner accepted (hash %s, "+ - "amount %v)", block.Hash(), btcutil.Amount(coinbaseTx.Value)) - return true -} - -// solveBlock attempts to find some combination of a nonce, extra nonce, and -// current timestamp which makes the passed block hash to a value less than the -// target difficulty. The timestamp is updated periodically and the passed -// block is modified with all tweaks during this process. This means that -// when the function returns true, the block is ready for submission. -// -// This function will return early with false when conditions that trigger a -// stale block such as a new block showing up or periodically when there are -// new transactions and enough time has elapsed without finding a solution. -func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32, - ticker *time.Ticker, quit chan struct{}) bool { - - // Choose a random extra nonce offset for this block template and - // worker. - enOffset, err := wire.RandomUint64() - if err != nil { - log.Errorf("Unexpected error while generating random "+ - "extra nonce offset: %v", err) - enOffset = 0 - } - - // Create some convenience variables. - header := &msgBlock.Header - targetDifficulty := blockchain.CompactToBig(header.Bits) - - // Initial state. - lastGenerated := time.Now() - lastTxUpdate := m.g.TxSource().LastUpdated() - hashesCompleted := uint64(0) - - // Note that the entire extra nonce range is iterated and the offset is - // added relying on the fact that overflow will wrap around 0 as - // provided by the Go spec. - for extraNonce := uint64(0); extraNonce < maxExtraNonce; extraNonce++ { - // Update the extra nonce in the block template with the - // new value by regenerating the coinbase script and - // setting the merkle root to the new value. - m.g.UpdateExtraNonce(msgBlock, blockHeight, extraNonce+enOffset) - - // Search through the entire nonce range for a solution while - // periodically checking for early quit and stale block - // conditions along with updates to the speed monitor. - for i := uint32(0); i <= maxNonce; i++ { - select { - case <-quit: - return false - - case <-ticker.C: - m.updateHashes <- hashesCompleted - hashesCompleted = 0 - - // The current block is stale if the best block - // has changed. - best := m.g.BestSnapshot() - if !header.PrevBlock.IsEqual(&best.Hash) { - return false - } - - // The current block is stale if the memory pool - // has been updated since the block template was - // generated and it has been at least one - // minute. - if lastTxUpdate != m.g.TxSource().LastUpdated() && - time.Now().After(lastGenerated.Add(time.Minute)) { - - return false - } - - m.g.UpdateBlockTime(msgBlock) - - default: - // Non-blocking select to fall through - } - - // Update the nonce and hash the block header. Each - // hash is actually a double sha256 (two hashes), so - // increment the number of hashes completed for each - // attempt accordingly. - header.Nonce = i - hash := header.BlockHash() - hashesCompleted += 2 - - // The block is solved when the new block hash is less - // than the target difficulty. Yay! - if blockchain.HashToBig(&hash).Cmp(targetDifficulty) <= 0 { - m.updateHashes <- hashesCompleted - return true - } - } - } - - return false -} - -// generateBlocks is a worker that is controlled by the miningWorkerController. -// It is self contained in that it creates block templates and attempts to solve -// them while detecting when it is performing stale work and reacting -// accordingly by generating a new block template. When a block is solved, it -// is submitted. -// -// It must be run as a goroutine. -func (m *CPUMiner) generateBlocks(quit chan struct{}) { - log.Tracef("Starting generate blocks worker") - - // Start a ticker which is used to signal checks for stale work and - // updates to the speed monitor. - ticker := time.NewTicker(time.Second * hashUpdateSecs) - defer ticker.Stop() -out: - for { - // Quit when the miner is stopped. - select { - case <-quit: - break out - default: - // Non-blocking select to fall through - } - - // Wait until there is a connection to at least one other peer - // since there is no way to relay a found block or receive - // transactions to work on when there are no connected peers. - if m.cfg.ConnectedCount() == 0 { - time.Sleep(time.Second) - continue - } - - // No point in searching for a solution before the chain is - // synced. Also, grab the same lock as used for block - // submission, since the current block will be changing and - // this would otherwise end up building a new block template on - // a block that is in the process of becoming stale. - m.submitBlockLock.Lock() - curHeight := m.g.BestSnapshot().Height - if curHeight != 0 && !m.cfg.IsCurrent() { - m.submitBlockLock.Unlock() - time.Sleep(time.Second) - continue - } - - // Choose a payment address at random. - rand.Seed(time.Now().UnixNano()) - payToAddr := m.cfg.MiningAddrs[rand.Intn(len(m.cfg.MiningAddrs))] - - // Create a new block template using the available transactions - // in the memory pool as a source of transactions to potentially - // include in the block. - template, err := m.g.NewBlockTemplate(payToAddr) - m.submitBlockLock.Unlock() - if err != nil { - errStr := fmt.Sprintf("Failed to create new block "+ - "template: %v", err) - log.Errorf(errStr) - continue - } - - // Attempt to solve the block. The function will exit early - // with false when conditions that trigger a stale block, so - // a new block template can be generated. When the return is - // true a solution was found, so submit the solved block. - if m.solveBlock(template.Block, curHeight+1, ticker, quit) { - block := btcutil.NewBlock(template.Block) - m.submitBlock(block) - } - } - - m.workerWg.Done() - log.Tracef("Generate blocks worker done") -} - -// miningWorkerController launches the worker goroutines that are used to -// generate block templates and solve them. It also provides the ability to -// dynamically adjust the number of running worker goroutines. -// -// It must be run as a goroutine. -func (m *CPUMiner) miningWorkerController() { - // launchWorkers groups common code to launch a specified number of - // workers for generating blocks. - var runningWorkers []chan struct{} - launchWorkers := func(numWorkers uint32) { - for i := uint32(0); i < numWorkers; i++ { - quit := make(chan struct{}) - runningWorkers = append(runningWorkers, quit) - - m.workerWg.Add(1) - go m.generateBlocks(quit) - } - } - - // Launch the current number of workers by default. - runningWorkers = make([]chan struct{}, 0, m.numWorkers) - launchWorkers(m.numWorkers) - -out: - for { - select { - // Update the number of running workers. - case <-m.updateNumWorkers: - // No change. - numRunning := uint32(len(runningWorkers)) - if m.numWorkers == numRunning { - continue - } - - // Add new workers. - if m.numWorkers > numRunning { - launchWorkers(m.numWorkers - numRunning) - continue - } - - // Signal the most recently created goroutines to exit. - for i := numRunning - 1; i >= m.numWorkers; i-- { - close(runningWorkers[i]) - runningWorkers[i] = nil - runningWorkers = runningWorkers[:i] - } - - case <-m.quit: - for _, quit := range runningWorkers { - close(quit) - } - break out - } - } - - // Wait until all workers shut down to stop the speed monitor since - // they rely on being able to send updates to it. - m.workerWg.Wait() - close(m.speedMonitorQuit) - m.wg.Done() -} - -// Start begins the CPU mining process as well as the speed monitor used to -// track hashing metrics. Calling this function when the CPU miner has -// already been started will have no effect. -// -// This function is safe for concurrent access. -func (m *CPUMiner) Start() { - m.Lock() - defer m.Unlock() - - // Nothing to do if the miner is already running or if running in - // discrete mode (using GenerateNBlocks). - if m.started || m.discreteMining { - return - } - - m.quit = make(chan struct{}) - m.speedMonitorQuit = make(chan struct{}) - m.wg.Add(2) - go m.speedMonitor() - go m.miningWorkerController() - - m.started = true - log.Infof("CPU miner started") -} - -// Stop gracefully stops the mining process by signalling all workers, and the -// speed monitor to quit. Calling this function when the CPU miner has not -// already been started will have no effect. -// -// This function is safe for concurrent access. -func (m *CPUMiner) Stop() { - m.Lock() - defer m.Unlock() - - // Nothing to do if the miner is not currently running or if running in - // discrete mode (using GenerateNBlocks). - if !m.started || m.discreteMining { - return - } - - close(m.quit) - m.wg.Wait() - m.started = false - log.Infof("CPU miner stopped") -} - -// IsMining returns whether or not the CPU miner has been started and is -// therefore currenting mining. -// -// This function is safe for concurrent access. -func (m *CPUMiner) IsMining() bool { - m.Lock() - defer m.Unlock() - - return m.started -} - -// HashesPerSecond returns the number of hashes per second the mining process -// is performing. 0 is returned if the miner is not currently running. -// -// This function is safe for concurrent access. -func (m *CPUMiner) HashesPerSecond() float64 { - m.Lock() - defer m.Unlock() - - // Nothing to do if the miner is not currently running. - if !m.started { - return 0 - } - - return <-m.queryHashesPerSec -} - -// SetNumWorkers sets the number of workers to create which solve blocks. Any -// negative values will cause a default number of workers to be used which is -// based on the number of processor cores in the system. A value of 0 will -// cause all CPU mining to be stopped. -// -// This function is safe for concurrent access. -func (m *CPUMiner) SetNumWorkers(numWorkers int32) { - if numWorkers == 0 { - m.Stop() - } - - // Don't lock until after the first check since Stop does its own - // locking. - m.Lock() - defer m.Unlock() - - // Use default if provided value is negative. - if numWorkers < 0 { - m.numWorkers = defaultNumWorkers - } else { - m.numWorkers = uint32(numWorkers) - } - - // When the miner is already running, notify the controller about the - // the change. - if m.started { - m.updateNumWorkers <- struct{}{} - } -} - -// NumWorkers returns the number of workers which are running to solve blocks. -// -// This function is safe for concurrent access. -func (m *CPUMiner) NumWorkers() int32 { - m.Lock() - defer m.Unlock() - - return int32(m.numWorkers) -} - -// GenerateNBlocks generates the requested number of blocks. It is self -// contained in that it creates block templates and attempts to solve them while -// detecting when it is performing stale work and reacting accordingly by -// generating a new block template. When a block is solved, it is submitted. -// The function returns a list of the hashes of generated blocks. -func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) { - m.Lock() - - // Respond with an error if server is already mining. - if m.started || m.discreteMining { - m.Unlock() - return nil, errors.New("Server is already CPU mining. Please call " + - "`setgenerate 0` before calling discrete `generate` commands.") - } - - m.started = true - m.discreteMining = true - - m.speedMonitorQuit = make(chan struct{}) - m.wg.Add(1) - go m.speedMonitor() - - m.Unlock() - - log.Tracef("Generating %d blocks", n) - - i := uint32(0) - blockHashes := make([]*chainhash.Hash, n) - - // Start a ticker which is used to signal checks for stale work and - // updates to the speed monitor. - ticker := time.NewTicker(time.Second * hashUpdateSecs) - defer ticker.Stop() - - for { - // Read updateNumWorkers in case someone tries a `setgenerate` while - // we're generating. We can ignore it as the `generate` RPC call only - // uses 1 worker. - select { - case <-m.updateNumWorkers: - default: - } - - // Grab the lock used for block submission, since the current block will - // be changing and this would otherwise end up building a new block - // template on a block that is in the process of becoming stale. - m.submitBlockLock.Lock() - curHeight := m.g.BestSnapshot().Height - - // Choose a payment address at random. - rand.Seed(time.Now().UnixNano()) - payToAddr := m.cfg.MiningAddrs[rand.Intn(len(m.cfg.MiningAddrs))] - - // Create a new block template using the available transactions - // in the memory pool as a source of transactions to potentially - // include in the block. - template, err := m.g.NewBlockTemplate(payToAddr) - m.submitBlockLock.Unlock() - if err != nil { - errStr := fmt.Sprintf("Failed to create new block "+ - "template: %v", err) - log.Errorf(errStr) - continue - } - - // Attempt to solve the block. The function will exit early - // with false when conditions that trigger a stale block, so - // a new block template can be generated. When the return is - // true a solution was found, so submit the solved block. - if m.solveBlock(template.Block, curHeight+1, ticker, nil) { - block := btcutil.NewBlock(template.Block) - m.submitBlock(block) - blockHashes[i] = block.Hash() - i++ - if i == n { - log.Tracef("Generated %d blocks", i) - m.Lock() - close(m.speedMonitorQuit) - m.wg.Wait() - m.started = false - m.discreteMining = false - m.Unlock() - return blockHashes, nil - } - } - } -} - -// New returns a new instance of a CPU miner for the provided configuration. -// Use Start to begin the mining process. See the documentation for CPUMiner -// type for more details. -func New(cfg *Config) *CPUMiner { - return &CPUMiner{ - g: cfg.BlockTemplateGenerator, - cfg: *cfg, - numWorkers: defaultNumWorkers, - updateNumWorkers: make(chan struct{}), - queryHashesPerSec: make(chan float64), - updateHashes: make(chan uint64), - } -} diff --git a/vendor/github.com/btcsuite/btcd/mining/cpuminer/log.go b/vendor/github.com/btcsuite/btcd/mining/cpuminer/log.go deleted file mode 100644 index 22c4dc72..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/cpuminer/log.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package cpuminer - -import ( - "github.com/btcsuite/btclog" -) - -// log is a logger that is initialized with no output filters. This -// means the package will not perform any logging by default until the caller -// requests it. -var log btclog.Logger - -// The default amount of logging is none. -func init() { - DisableLog() -} - -// DisableLog disables all library log output. Logging output is disabled -// by default until UseLogger is called. -func DisableLog() { - log = btclog.Disabled -} - -// UseLogger uses a specified Logger to output package logging info. -func UseLogger(logger btclog.Logger) { - log = logger -} diff --git a/vendor/github.com/btcsuite/btcd/mining/log.go b/vendor/github.com/btcsuite/btcd/mining/log.go deleted file mode 100644 index 5e792d9a..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/log.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package mining - -import ( - "github.com/btcsuite/btclog" -) - -// log is a logger that is initialized with no output filters. This -// means the package will not perform any logging by default until the caller -// requests it. -var log btclog.Logger - -// The default amount of logging is none. -func init() { - DisableLog() -} - -// DisableLog disables all library log output. Logging output is disabled -// by default until UseLogger is called. -func DisableLog() { - log = btclog.Disabled -} - -// UseLogger uses a specified Logger to output package logging info. -func UseLogger(logger btclog.Logger) { - log = logger -} diff --git a/vendor/github.com/btcsuite/btcd/mining/mining.go b/vendor/github.com/btcsuite/btcd/mining/mining.go deleted file mode 100644 index 37158940..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/mining.go +++ /dev/null @@ -1,969 +0,0 @@ -// Copyright (c) 2014-2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package mining - -import ( - "bytes" - "container/heap" - "fmt" - "time" - - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" -) - -const ( - // MinHighPriority is the minimum priority value that allows a - // transaction to be considered high priority. - MinHighPriority = btcutil.SatoshiPerBitcoin * 144.0 / 250 - - // blockHeaderOverhead is the max number of bytes it takes to serialize - // a block header and max possible transaction count. - blockHeaderOverhead = wire.MaxBlockHeaderPayload + wire.MaxVarIntPayload - - // CoinbaseFlags is added to the coinbase script of a generated block - // and is used to monitor BIP16 support as well as blocks that are - // generated via btcd. - CoinbaseFlags = "/P2SH/btcd/" -) - -// TxDesc is a descriptor about a transaction in a transaction source along with -// additional metadata. -type TxDesc struct { - // Tx is the transaction associated with the entry. - Tx *btcutil.Tx - - // Added is the time when the entry was added to the source pool. - Added time.Time - - // Height is the block height when the entry was added to the the source - // pool. - Height int32 - - // Fee is the total fee the transaction associated with the entry pays. - Fee int64 - - // FeePerKB is the fee the transaction pays in Satoshi per 1000 bytes. - FeePerKB int64 -} - -// TxSource represents a source of transactions to consider for inclusion in -// new blocks. -// -// The interface contract requires that all of these methods are safe for -// concurrent access with respect to the source. -type TxSource interface { - // LastUpdated returns the last time a transaction was added to or - // removed from the source pool. - LastUpdated() time.Time - - // MiningDescs returns a slice of mining descriptors for all the - // transactions in the source pool. - MiningDescs() []*TxDesc - - // HaveTransaction returns whether or not the passed transaction hash - // exists in the source pool. - HaveTransaction(hash *chainhash.Hash) bool -} - -// txPrioItem houses a transaction along with extra information that allows the -// transaction to be prioritized and track dependencies on other transactions -// which have not been mined into a block yet. -type txPrioItem struct { - tx *btcutil.Tx - fee int64 - priority float64 - feePerKB int64 - - // dependsOn holds a map of transaction hashes which this one depends - // on. It will only be set when the transaction references other - // transactions in the source pool and hence must come after them in - // a block. - dependsOn map[chainhash.Hash]struct{} -} - -// txPriorityQueueLessFunc describes a function that can be used as a compare -// function for a transaction priority queue (txPriorityQueue). -type txPriorityQueueLessFunc func(*txPriorityQueue, int, int) bool - -// txPriorityQueue implements a priority queue of txPrioItem elements that -// supports an arbitrary compare function as defined by txPriorityQueueLessFunc. -type txPriorityQueue struct { - lessFunc txPriorityQueueLessFunc - items []*txPrioItem -} - -// Len returns the number of items in the priority queue. It is part of the -// heap.Interface implementation. -func (pq *txPriorityQueue) Len() int { - return len(pq.items) -} - -// Less returns whether the item in the priority queue with index i should sort -// before the item with index j by deferring to the assigned less function. It -// is part of the heap.Interface implementation. -func (pq *txPriorityQueue) Less(i, j int) bool { - return pq.lessFunc(pq, i, j) -} - -// Swap swaps the items at the passed indices in the priority queue. It is -// part of the heap.Interface implementation. -func (pq *txPriorityQueue) Swap(i, j int) { - pq.items[i], pq.items[j] = pq.items[j], pq.items[i] -} - -// Push pushes the passed item onto the priority queue. It is part of the -// heap.Interface implementation. -func (pq *txPriorityQueue) Push(x interface{}) { - pq.items = append(pq.items, x.(*txPrioItem)) -} - -// Pop removes the highest priority item (according to Less) from the priority -// queue and returns it. It is part of the heap.Interface implementation. -func (pq *txPriorityQueue) Pop() interface{} { - n := len(pq.items) - item := pq.items[n-1] - pq.items[n-1] = nil - pq.items = pq.items[0 : n-1] - return item -} - -// SetLessFunc sets the compare function for the priority queue to the provided -// function. It also invokes heap.Init on the priority queue using the new -// function so it can immediately be used with heap.Push/Pop. -func (pq *txPriorityQueue) SetLessFunc(lessFunc txPriorityQueueLessFunc) { - pq.lessFunc = lessFunc - heap.Init(pq) -} - -// txPQByPriority sorts a txPriorityQueue by transaction priority and then fees -// per kilobyte. -func txPQByPriority(pq *txPriorityQueue, i, j int) bool { - // Using > here so that pop gives the highest priority item as opposed - // to the lowest. Sort by priority first, then fee. - if pq.items[i].priority == pq.items[j].priority { - return pq.items[i].feePerKB > pq.items[j].feePerKB - } - return pq.items[i].priority > pq.items[j].priority - -} - -// txPQByFee sorts a txPriorityQueue by fees per kilobyte and then transaction -// priority. -func txPQByFee(pq *txPriorityQueue, i, j int) bool { - // Using > here so that pop gives the highest fee item as opposed - // to the lowest. Sort by fee first, then priority. - if pq.items[i].feePerKB == pq.items[j].feePerKB { - return pq.items[i].priority > pq.items[j].priority - } - return pq.items[i].feePerKB > pq.items[j].feePerKB -} - -// newTxPriorityQueue returns a new transaction priority queue that reserves the -// passed amount of space for the elements. The new priority queue uses either -// the txPQByPriority or the txPQByFee compare function depending on the -// sortByFee parameter and is already initialized for use with heap.Push/Pop. -// The priority queue can grow larger than the reserved space, but extra copies -// of the underlying array can be avoided by reserving a sane value. -func newTxPriorityQueue(reserve int, sortByFee bool) *txPriorityQueue { - pq := &txPriorityQueue{ - items: make([]*txPrioItem, 0, reserve), - } - if sortByFee { - pq.SetLessFunc(txPQByFee) - } else { - pq.SetLessFunc(txPQByPriority) - } - return pq -} - -// BlockTemplate houses a block that has yet to be solved along with additional -// details about the fees and the number of signature operations for each -// transaction in the block. -type BlockTemplate struct { - // Block is a block that is ready to be solved by miners. Thus, it is - // completely valid with the exception of satisfying the proof-of-work - // requirement. - Block *wire.MsgBlock - - // Fees contains the amount of fees each transaction in the generated - // template pays in base units. Since the first transaction is the - // coinbase, the first entry (offset 0) will contain the negative of the - // sum of the fees of all other transactions. - Fees []int64 - - // SigOpCosts contains the number of signature operations each - // transaction in the generated template performs. - SigOpCosts []int64 - - // Height is the height at which the block template connects to the main - // chain. - Height int32 - - // ValidPayAddress indicates whether or not the template coinbase pays - // to an address or is redeemable by anyone. See the documentation on - // NewBlockTemplate for details on which this can be useful to generate - // templates without a coinbase payment address. - ValidPayAddress bool - - // WitnessCommitment is a commitment to the witness data (if any) - // within the block. This field will only be populted once segregated - // witness has been activated, and the block contains a transaction - // which has witness data. - WitnessCommitment []byte -} - -// mergeUtxoView adds all of the entries in view to viewA. The result is that -// viewA will contain all of its original entries plus all of the entries -// in viewB. It will replace any entries in viewB which also exist in viewA -// if the entry in viewA is fully spent. -func mergeUtxoView(viewA *blockchain.UtxoViewpoint, viewB *blockchain.UtxoViewpoint) { - viewAEntries := viewA.Entries() - for hash, entryB := range viewB.Entries() { - if entryA, exists := viewAEntries[hash]; !exists || - entryA == nil || entryA.IsFullySpent() { - - viewAEntries[hash] = entryB - } - } -} - -// standardCoinbaseScript returns a standard script suitable for use as the -// signature script of the coinbase transaction of a new block. In particular, -// it starts with the block height that is required by version 2 blocks and adds -// the extra nonce as well as additional coinbase flags. -func standardCoinbaseScript(nextBlockHeight int32, extraNonce uint64) ([]byte, error) { - return txscript.NewScriptBuilder().AddInt64(int64(nextBlockHeight)). - AddInt64(int64(extraNonce)).AddData([]byte(CoinbaseFlags)). - Script() -} - -// createCoinbaseTx returns a coinbase transaction paying an appropriate subsidy -// based on the passed block height to the provided address. When the address -// is nil, the coinbase transaction will instead be redeemable by anyone. -// -// See the comment for NewBlockTemplate for more information about why the nil -// address handling is useful. -func createCoinbaseTx(params *chaincfg.Params, coinbaseScript []byte, nextBlockHeight int32, addr btcutil.Address) (*btcutil.Tx, error) { - // Create the script to pay to the provided payment address if one was - // specified. Otherwise create a script that allows the coinbase to be - // redeemable by anyone. - var pkScript []byte - if addr != nil { - var err error - pkScript, err = txscript.PayToAddrScript(addr) - if err != nil { - return nil, err - } - } else { - var err error - scriptBuilder := txscript.NewScriptBuilder() - pkScript, err = scriptBuilder.AddOp(txscript.OP_TRUE).Script() - if err != nil { - return nil, err - } - } - - tx := wire.NewMsgTx(wire.TxVersion) - tx.AddTxIn(&wire.TxIn{ - // Coinbase transactions have no inputs, so previous outpoint is - // zero hash and max index. - PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{}, - wire.MaxPrevOutIndex), - SignatureScript: coinbaseScript, - Sequence: wire.MaxTxInSequenceNum, - }) - tx.AddTxOut(&wire.TxOut{ - Value: blockchain.CalcBlockSubsidy(nextBlockHeight, params), - PkScript: pkScript, - }) - return btcutil.NewTx(tx), nil -} - -// spendTransaction updates the passed view by marking the inputs to the passed -// transaction as spent. It also adds all outputs in the passed transaction -// which are not provably unspendable as available unspent transaction outputs. -func spendTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil.Tx, height int32) error { - for _, txIn := range tx.MsgTx().TxIn { - originHash := &txIn.PreviousOutPoint.Hash - originIndex := txIn.PreviousOutPoint.Index - entry := utxoView.LookupEntry(originHash) - if entry != nil { - entry.SpendOutput(originIndex) - } - } - - utxoView.AddTxOuts(tx, height) - return nil -} - -// logSkippedDeps logs any dependencies which are also skipped as a result of -// skipping a transaction while generating a block template at the trace level. -func logSkippedDeps(tx *btcutil.Tx, deps map[chainhash.Hash]*txPrioItem) { - if deps == nil { - return - } - - for _, item := range deps { - log.Tracef("Skipping tx %s since it depends on %s\n", - item.tx.Hash(), tx.Hash()) - } -} - -// MinimumMedianTime returns the minimum allowed timestamp for a block building -// on the end of the provided best chain. In particular, it is one second after -// the median timestamp of the last several blocks per the chain consensus -// rules. -func MinimumMedianTime(chainState *blockchain.BestState) time.Time { - return chainState.MedianTime.Add(time.Second) -} - -// medianAdjustedTime returns the current time adjusted to ensure it is at least -// one second after the median timestamp of the last several blocks per the -// chain consensus rules. -func medianAdjustedTime(chainState *blockchain.BestState, timeSource blockchain.MedianTimeSource) time.Time { - // The timestamp for the block must not be before the median timestamp - // of the last several blocks. Thus, choose the maximum between the - // current time and one second after the past median time. The current - // timestamp is truncated to a second boundary before comparison since a - // block timestamp does not supported a precision greater than one - // second. - newTimestamp := timeSource.AdjustedTime() - minTimestamp := MinimumMedianTime(chainState) - if newTimestamp.Before(minTimestamp) { - newTimestamp = minTimestamp - } - - return newTimestamp -} - -// BlkTmplGenerator provides a type that can be used to generate block templates -// based on a given mining policy and source of transactions to choose from. -// It also houses additional state required in order to ensure the templates -// are built on top of the current best chain and adhere to the consensus rules. -type BlkTmplGenerator struct { - policy *Policy - chainParams *chaincfg.Params - txSource TxSource - chain *blockchain.BlockChain - timeSource blockchain.MedianTimeSource - sigCache *txscript.SigCache - hashCache *txscript.HashCache -} - -// NewBlkTmplGenerator returns a new block template generator for the given -// policy using transactions from the provided transaction source. -// -// The additional state-related fields are required in order to ensure the -// templates are built on top of the current best chain and adhere to the -// consensus rules. -func NewBlkTmplGenerator(policy *Policy, params *chaincfg.Params, - txSource TxSource, chain *blockchain.BlockChain, - timeSource blockchain.MedianTimeSource, - sigCache *txscript.SigCache, - hashCache *txscript.HashCache) *BlkTmplGenerator { - - return &BlkTmplGenerator{ - policy: policy, - chainParams: params, - txSource: txSource, - chain: chain, - timeSource: timeSource, - sigCache: sigCache, - hashCache: hashCache, - } -} - -// NewBlockTemplate returns a new block template that is ready to be solved -// using the transactions from the passed transaction source pool and a coinbase -// that either pays to the passed address if it is not nil, or a coinbase that -// is redeemable by anyone if the passed address is nil. The nil address -// functionality is useful since there are cases such as the getblocktemplate -// RPC where external mining software is responsible for creating their own -// coinbase which will replace the one generated for the block template. Thus -// the need to have configured address can be avoided. -// -// The transactions selected and included are prioritized according to several -// factors. First, each transaction has a priority calculated based on its -// value, age of inputs, and size. Transactions which consist of larger -// amounts, older inputs, and small sizes have the highest priority. Second, a -// fee per kilobyte is calculated for each transaction. Transactions with a -// higher fee per kilobyte are preferred. Finally, the block generation related -// policy settings are all taken into account. -// -// Transactions which only spend outputs from other transactions already in the -// block chain are immediately added to a priority queue which either -// prioritizes based on the priority (then fee per kilobyte) or the fee per -// kilobyte (then priority) depending on whether or not the BlockPrioritySize -// policy setting allots space for high-priority transactions. Transactions -// which spend outputs from other transactions in the source pool are added to a -// dependency map so they can be added to the priority queue once the -// transactions they depend on have been included. -// -// Once the high-priority area (if configured) has been filled with -// transactions, or the priority falls below what is considered high-priority, -// the priority queue is updated to prioritize by fees per kilobyte (then -// priority). -// -// When the fees per kilobyte drop below the TxMinFreeFee policy setting, the -// transaction will be skipped unless the BlockMinSize policy setting is -// nonzero, in which case the block will be filled with the low-fee/free -// transactions until the block size reaches that minimum size. -// -// Any transactions which would cause the block to exceed the BlockMaxSize -// policy setting, exceed the maximum allowed signature operations per block, or -// otherwise cause the block to be invalid are skipped. -// -// Given the above, a block generated by this function is of the following form: -// -// ----------------------------------- -- -- -// | Coinbase Transaction | | | -// |-----------------------------------| | | -// | | | | ----- policy.BlockPrioritySize -// | High-priority Transactions | | | -// | | | | -// |-----------------------------------| | -- -// | | | -// | | | -// | | |--- policy.BlockMaxSize -// | Transactions prioritized by fee | | -// | until <= policy.TxMinFreeFee | | -// | | | -// | | | -// | | | -// |-----------------------------------| | -// | Low-fee/Non high-priority (free) | | -// | transactions (while block size | | -// | <= policy.BlockMinSize) | | -// ----------------------------------- -- -func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress btcutil.Address) (*BlockTemplate, error) { - // Extend the most recently known best block. - best := g.chain.BestSnapshot() - nextBlockHeight := best.Height + 1 - - // Create a standard coinbase transaction paying to the provided - // address. NOTE: The coinbase value will be updated to include the - // fees from the selected transactions later after they have actually - // been selected. It is created here to detect any errors early - // before potentially doing a lot of work below. The extra nonce helps - // ensure the transaction is not a duplicate transaction (paying the - // same value to the same public key address would otherwise be an - // identical transaction for block version 1). - extraNonce := uint64(0) - coinbaseScript, err := standardCoinbaseScript(nextBlockHeight, extraNonce) - if err != nil { - return nil, err - } - coinbaseTx, err := createCoinbaseTx(g.chainParams, coinbaseScript, - nextBlockHeight, payToAddress) - if err != nil { - return nil, err - } - coinbaseSigOpCost := int64(blockchain.CountSigOps(coinbaseTx)) * blockchain.WitnessScaleFactor - - // Get the current source transactions and create a priority queue to - // hold the transactions which are ready for inclusion into a block - // along with some priority related and fee metadata. Reserve the same - // number of items that are available for the priority queue. Also, - // choose the initial sort order for the priority queue based on whether - // or not there is an area allocated for high-priority transactions. - sourceTxns := g.txSource.MiningDescs() - sortedByFee := g.policy.BlockPrioritySize == 0 - priorityQueue := newTxPriorityQueue(len(sourceTxns), sortedByFee) - - // Create a slice to hold the transactions to be included in the - // generated block with reserved space. Also create a utxo view to - // house all of the input transactions so multiple lookups can be - // avoided. - blockTxns := make([]*btcutil.Tx, 0, len(sourceTxns)) - blockTxns = append(blockTxns, coinbaseTx) - blockUtxos := blockchain.NewUtxoViewpoint() - - // dependers is used to track transactions which depend on another - // transaction in the source pool. This, in conjunction with the - // dependsOn map kept with each dependent transaction helps quickly - // determine which dependent transactions are now eligible for inclusion - // in the block once each transaction has been included. - dependers := make(map[chainhash.Hash]map[chainhash.Hash]*txPrioItem) - - // Create slices to hold the fees and number of signature operations - // for each of the selected transactions and add an entry for the - // coinbase. This allows the code below to simply append details about - // a transaction as it is selected for inclusion in the final block. - // However, since the total fees aren't known yet, use a dummy value for - // the coinbase fee which will be updated later. - txFees := make([]int64, 0, len(sourceTxns)) - txSigOpCosts := make([]int64, 0, len(sourceTxns)) - txFees = append(txFees, -1) // Updated once known - txSigOpCosts = append(txSigOpCosts, coinbaseSigOpCost) - - log.Debugf("Considering %d transactions for inclusion to new block", - len(sourceTxns)) - -mempoolLoop: - for _, txDesc := range sourceTxns { - // A block can't have more than one coinbase or contain - // non-finalized transactions. - tx := txDesc.Tx - if blockchain.IsCoinBase(tx) { - log.Tracef("Skipping coinbase tx %s", tx.Hash()) - continue - } - if !blockchain.IsFinalizedTransaction(tx, nextBlockHeight, - g.timeSource.AdjustedTime()) { - - log.Tracef("Skipping non-finalized tx %s", tx.Hash()) - continue - } - - // Fetch all of the utxos referenced by the this transaction. - // NOTE: This intentionally does not fetch inputs from the - // mempool since a transaction which depends on other - // transactions in the mempool must come after those - // dependencies in the final generated block. - utxos, err := g.chain.FetchUtxoView(tx) - if err != nil { - log.Warnf("Unable to fetch utxo view for tx %s: %v", - tx.Hash(), err) - continue - } - - // Setup dependencies for any transactions which reference - // other transactions in the mempool so they can be properly - // ordered below. - prioItem := &txPrioItem{tx: tx} - for _, txIn := range tx.MsgTx().TxIn { - originHash := &txIn.PreviousOutPoint.Hash - originIndex := txIn.PreviousOutPoint.Index - utxoEntry := utxos.LookupEntry(originHash) - if utxoEntry == nil || utxoEntry.IsOutputSpent(originIndex) { - if !g.txSource.HaveTransaction(originHash) { - log.Tracef("Skipping tx %s because it "+ - "references unspent output %s "+ - "which is not available", - tx.Hash(), txIn.PreviousOutPoint) - continue mempoolLoop - } - - // The transaction is referencing another - // transaction in the source pool, so setup an - // ordering dependency. - deps, exists := dependers[*originHash] - if !exists { - deps = make(map[chainhash.Hash]*txPrioItem) - dependers[*originHash] = deps - } - deps[*prioItem.tx.Hash()] = prioItem - if prioItem.dependsOn == nil { - prioItem.dependsOn = make( - map[chainhash.Hash]struct{}) - } - prioItem.dependsOn[*originHash] = struct{}{} - - // Skip the check below. We already know the - // referenced transaction is available. - continue - } - } - - // Calculate the final transaction priority using the input - // value age sum as well as the adjusted transaction size. The - // formula is: sum(inputValue * inputAge) / adjustedTxSize - prioItem.priority = CalcPriority(tx.MsgTx(), utxos, - nextBlockHeight) - - // Calculate the fee in Satoshi/kB. - prioItem.feePerKB = txDesc.FeePerKB - prioItem.fee = txDesc.Fee - - // Add the transaction to the priority queue to mark it ready - // for inclusion in the block unless it has dependencies. - if prioItem.dependsOn == nil { - heap.Push(priorityQueue, prioItem) - } - - // Merge the referenced outputs from the input transactions to - // this transaction into the block utxo view. This allows the - // code below to avoid a second lookup. - mergeUtxoView(blockUtxos, utxos) - } - - log.Tracef("Priority queue len %d, dependers len %d", - priorityQueue.Len(), len(dependers)) - - // The starting block size is the size of the block header plus the max - // possible transaction count size, plus the size of the coinbase - // transaction. - blockWeight := uint32((blockHeaderOverhead * blockchain.WitnessScaleFactor) + - blockchain.GetTransactionWeight(coinbaseTx)) - blockSigOpCost := coinbaseSigOpCost - totalFees := int64(0) - - // Query the version bits state to see if segwit has been activated, if - // so then this means that we'll include any transactions with witness - // data in the mempool, and also add the witness commitment as an - // OP_RETURN output in the coinbase transaction. - segwitState, err := g.chain.ThresholdState(chaincfg.DeploymentSegwit) - if err != nil { - return nil, err - } - segwitActive := segwitState == blockchain.ThresholdActive - - witnessIncluded := false - - // Choose which transactions make it into the block. - for priorityQueue.Len() > 0 { - // Grab the highest priority (or highest fee per kilobyte - // depending on the sort order) transaction. - prioItem := heap.Pop(priorityQueue).(*txPrioItem) - tx := prioItem.tx - - switch { - // If segregated witness has not been activated yet, then we - // shouldn't include any witness transactions in the block. - case !segwitActive && tx.HasWitness(): - continue - - // Otherwise, Keep track of if we've included a transaction - // with witness data or not. If so, then we'll need to include - // the witness commitment as the last output in the coinbase - // transaction. - case segwitActive && !witnessIncluded && tx.HasWitness(): - // If we're about to include a transaction bearing - // witness data, then we'll also need to include a - // witness commitment in the coinbase transaction. - // Therefore, we account for the additional weight - // within the block with a model coinbase tx with a - // witness commitment. - coinbaseCopy := btcutil.NewTx(coinbaseTx.MsgTx().Copy()) - coinbaseCopy.MsgTx().TxIn[0].Witness = [][]byte{ - bytes.Repeat([]byte("a"), - blockchain.CoinbaseWitnessDataLen), - } - coinbaseCopy.MsgTx().AddTxOut(&wire.TxOut{ - PkScript: bytes.Repeat([]byte("a"), - blockchain.CoinbaseWitnessPkScriptLength), - }) - - // In order to accurately account for the weight - // addition due to this coinbase transaction, we'll add - // the difference of the transaction before and after - // the addition of the commitment to the block weight. - weightDiff := blockchain.GetTransactionWeight(coinbaseCopy) - - blockchain.GetTransactionWeight(coinbaseTx) - - blockWeight += uint32(weightDiff) - - witnessIncluded = true - } - - // Grab any transactions which depend on this one. - deps := dependers[*tx.Hash()] - - // Enforce maximum block size. Also check for overflow. - txWeight := uint32(blockchain.GetTransactionWeight(tx)) - blockPlusTxWeight := blockWeight + txWeight - if blockPlusTxWeight < blockWeight || - blockPlusTxWeight >= g.policy.BlockMaxWeight { - - log.Tracef("Skipping tx %s because it would exceed "+ - "the max block weight", tx.Hash()) - logSkippedDeps(tx, deps) - continue - } - - // Enforce maximum signature operation cost per block. Also - // check for overflow. - sigOpCost, err := blockchain.GetSigOpCost(tx, false, - blockUtxos, true, segwitActive) - if err != nil { - log.Tracef("Skipping tx %s due to error in "+ - "GetSigOpCost: %v", tx.Hash(), err) - logSkippedDeps(tx, deps) - continue - } - if blockSigOpCost+int64(sigOpCost) < blockSigOpCost || - blockSigOpCost+int64(sigOpCost) > blockchain.MaxBlockSigOpsCost { - log.Tracef("Skipping tx %s because it would "+ - "exceed the maximum sigops per block", tx.Hash()) - logSkippedDeps(tx, deps) - continue - } - - // Skip free transactions once the block is larger than the - // minimum block size. - if sortedByFee && - prioItem.feePerKB < int64(g.policy.TxMinFreeFee) && - blockPlusTxWeight >= g.policy.BlockMinWeight { - - log.Tracef("Skipping tx %s with feePerKB %d "+ - "< TxMinFreeFee %d and block weight %d >= "+ - "minBlockWeight %d", tx.Hash(), prioItem.feePerKB, - g.policy.TxMinFreeFee, blockPlusTxWeight, - g.policy.BlockMinWeight) - logSkippedDeps(tx, deps) - continue - } - - // Prioritize by fee per kilobyte once the block is larger than - // the priority size or there are no more high-priority - // transactions. - if !sortedByFee && (blockPlusTxWeight >= g.policy.BlockPrioritySize || - prioItem.priority <= MinHighPriority) { - - log.Tracef("Switching to sort by fees per "+ - "kilobyte blockSize %d >= BlockPrioritySize "+ - "%d || priority %.2f <= minHighPriority %.2f", - blockPlusTxWeight, g.policy.BlockPrioritySize, - prioItem.priority, MinHighPriority) - - sortedByFee = true - priorityQueue.SetLessFunc(txPQByFee) - - // Put the transaction back into the priority queue and - // skip it so it is re-priortized by fees if it won't - // fit into the high-priority section or the priority - // is too low. Otherwise this transaction will be the - // final one in the high-priority section, so just fall - // though to the code below so it is added now. - if blockPlusTxWeight > g.policy.BlockPrioritySize || - prioItem.priority < MinHighPriority { - - heap.Push(priorityQueue, prioItem) - continue - } - } - - // Ensure the transaction inputs pass all of the necessary - // preconditions before allowing it to be added to the block. - _, err = blockchain.CheckTransactionInputs(tx, nextBlockHeight, - blockUtxos, g.chainParams) - if err != nil { - log.Tracef("Skipping tx %s due to error in "+ - "CheckTransactionInputs: %v", tx.Hash(), err) - logSkippedDeps(tx, deps) - continue - } - err = blockchain.ValidateTransactionScripts(tx, blockUtxos, - txscript.StandardVerifyFlags, g.sigCache, - g.hashCache) - if err != nil { - log.Tracef("Skipping tx %s due to error in "+ - "ValidateTransactionScripts: %v", tx.Hash(), err) - logSkippedDeps(tx, deps) - continue - } - - // Spend the transaction inputs in the block utxo view and add - // an entry for it to ensure any transactions which reference - // this one have it available as an input and can ensure they - // aren't double spending. - spendTransaction(blockUtxos, tx, nextBlockHeight) - - // Add the transaction to the block, increment counters, and - // save the fees and signature operation counts to the block - // template. - blockTxns = append(blockTxns, tx) - blockWeight += txWeight - blockSigOpCost += int64(sigOpCost) - totalFees += prioItem.fee - txFees = append(txFees, prioItem.fee) - txSigOpCosts = append(txSigOpCosts, int64(sigOpCost)) - - log.Tracef("Adding tx %s (priority %.2f, feePerKB %.2f)", - prioItem.tx.Hash(), prioItem.priority, prioItem.feePerKB) - - // Add transactions which depend on this one (and also do not - // have any other unsatisified dependencies) to the priority - // queue. - for _, item := range deps { - // Add the transaction to the priority queue if there - // are no more dependencies after this one. - delete(item.dependsOn, *tx.Hash()) - if len(item.dependsOn) == 0 { - heap.Push(priorityQueue, item) - } - } - } - - // Now that the actual transactions have been selected, update the - // block weight for the real transaction count and coinbase value with - // the total fees accordingly. - blockWeight -= wire.MaxVarIntPayload - - (uint32(wire.VarIntSerializeSize(uint64(len(blockTxns)))) * - blockchain.WitnessScaleFactor) - coinbaseTx.MsgTx().TxOut[0].Value += totalFees - txFees[0] = -totalFees - - // If segwit is active and we included transactions with witness data, - // then we'll need to include a commitment to the witness data in an - // OP_RETURN output within the coinbase transaction. - var witnessCommitment []byte - if witnessIncluded { - // The witness of the coinbase transaction MUST be exactly 32-bytes - // of all zeroes. - var witnessNonce [blockchain.CoinbaseWitnessDataLen]byte - coinbaseTx.MsgTx().TxIn[0].Witness = wire.TxWitness{witnessNonce[:]} - - // Next, obtain the merkle root of a tree which consists of the - // wtxid of all transactions in the block. The coinbase - // transaction will have a special wtxid of all zeroes. - witnessMerkleTree := blockchain.BuildMerkleTreeStore(blockTxns, - true) - witnessMerkleRoot := witnessMerkleTree[len(witnessMerkleTree)-1] - - // The preimage to the witness commitment is: - // witnessRoot || coinbaseWitness - var witnessPreimage [64]byte - copy(witnessPreimage[:32], witnessMerkleRoot[:]) - copy(witnessPreimage[32:], witnessNonce[:]) - - // The witness commitment itself is the double-sha256 of the - // witness preimage generated above. With the commitment - // generated, the witness script for the output is: OP_RETURN - // OP_DATA_36 {0xaa21a9ed || witnessCommitment}. The leading - // prefix is refered to as the "witness magic bytes". - witnessCommitment = chainhash.DoubleHashB(witnessPreimage[:]) - witnessScript := append(blockchain.WitnessMagicBytes, witnessCommitment...) - - // Finally, create the OP_RETURN carrying witness commitment - // output as an additional output within the coinbase. - commitmentOutput := &wire.TxOut{ - Value: 0, - PkScript: witnessScript, - } - coinbaseTx.MsgTx().TxOut = append(coinbaseTx.MsgTx().TxOut, - commitmentOutput) - } - - // 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(best, g.timeSource) - reqDifficulty, err := g.chain.CalcNextRequiredDifficulty(ts) - if err != nil { - return nil, err - } - - // Calculate the next expected block version based on the state of the - // rule change deployments. - nextBlockVersion, err := g.chain.CalcNextBlockVersion() - if err != nil { - return nil, err - } - - // Create a new block ready to be solved. - merkles := blockchain.BuildMerkleTreeStore(blockTxns, false) - var msgBlock wire.MsgBlock - msgBlock.Header = wire.BlockHeader{ - Version: nextBlockVersion, - PrevBlock: best.Hash, - MerkleRoot: *merkles[len(merkles)-1], - Timestamp: ts, - Bits: reqDifficulty, - } - for _, tx := range blockTxns { - if err := msgBlock.AddTransaction(tx.MsgTx()); err != nil { - return nil, err - } - } - - // Finally, perform a full check on the created block against the chain - // consensus rules to ensure it properly connects to the current best - // chain with no issues. - block := btcutil.NewBlock(&msgBlock) - block.SetHeight(nextBlockHeight) - if err := g.chain.CheckConnectBlock(block); err != nil { - return nil, err - } - - log.Debugf("Created new block template (%d transactions, %d in "+ - "fees, %d signature operations cost, %d weight, target difficulty "+ - "%064x)", len(msgBlock.Transactions), totalFees, blockSigOpCost, - blockWeight, blockchain.CompactToBig(msgBlock.Header.Bits)) - - return &BlockTemplate{ - Block: &msgBlock, - Fees: txFees, - SigOpCosts: txSigOpCosts, - Height: nextBlockHeight, - ValidPayAddress: payToAddress != nil, - WitnessCommitment: witnessCommitment, - }, nil -} - -// UpdateBlockTime updates the timestamp in the header of the passed block to -// the current time while taking into account the median time of the last -// several blocks to ensure the new time is after that time per the chain -// consensus rules. Finally, it will update the target difficulty if needed -// based on the new time for the test networks since their target difficulty can -// change based upon time. -func (g *BlkTmplGenerator) UpdateBlockTime(msgBlock *wire.MsgBlock) error { - // The new timestamp is potentially adjusted to ensure it comes after - // the median time of the last several blocks per the chain consensus - // rules. - newTime := medianAdjustedTime(g.chain.BestSnapshot(), g.timeSource) - msgBlock.Header.Timestamp = newTime - - // Recalculate the difficulty if running on a network that requires it. - if g.chainParams.ReduceMinDifficulty { - difficulty, err := g.chain.CalcNextRequiredDifficulty(newTime) - if err != nil { - return err - } - msgBlock.Header.Bits = difficulty - } - - return nil -} - -// UpdateExtraNonce updates the extra nonce in the coinbase script of the passed -// block by regenerating the coinbase script with the passed value and block -// height. It also recalculates and updates the new merkle root that results -// from changing the coinbase script. -func (g *BlkTmplGenerator) UpdateExtraNonce(msgBlock *wire.MsgBlock, blockHeight int32, extraNonce uint64) error { - coinbaseScript, err := standardCoinbaseScript(blockHeight, extraNonce) - if err != nil { - return err - } - if len(coinbaseScript) > blockchain.MaxCoinbaseScriptLen { - return fmt.Errorf("coinbase transaction script length "+ - "of %d is out of range (min: %d, max: %d)", - len(coinbaseScript), blockchain.MinCoinbaseScriptLen, - blockchain.MaxCoinbaseScriptLen) - } - msgBlock.Transactions[0].TxIn[0].SignatureScript = coinbaseScript - - // TODO(davec): A btcutil.Block should use saved in the state to avoid - // recalculating all of the other transaction hashes. - // block.Transactions[0].InvalidateCache() - - // Recalculate the merkle root with the updated extra nonce. - block := btcutil.NewBlock(msgBlock) - merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false) - msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1] - return nil -} - -// BestSnapshot returns information about the current best chain block and -// related state as of the current point in time using the chain instance -// associated with the block template generator. The returned state must be -// treated as immutable since it is shared by all callers. -// -// This function is safe for concurrent access. -func (g *BlkTmplGenerator) BestSnapshot() *blockchain.BestState { - return g.chain.BestSnapshot() -} - -// TxSource returns the associated transaction source. -// -// This function is safe for concurrent access. -func (g *BlkTmplGenerator) TxSource() TxSource { - return g.txSource -} diff --git a/vendor/github.com/btcsuite/btcd/mining/mining_test.go b/vendor/github.com/btcsuite/btcd/mining/mining_test.go deleted file mode 100644 index 362253e5..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/mining_test.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package mining - -import ( - "container/heap" - "math/rand" - "testing" - - "github.com/btcsuite/btcutil" -) - -// TestTxFeePrioHeap ensures the priority queue for transaction fees and -// priorities works as expected. -func TestTxFeePrioHeap(t *testing.T) { - // Create some fake priority items that exercise the expected sort - // edge conditions. - testItems := []*txPrioItem{ - {feePerKB: 5678, priority: 3}, - {feePerKB: 5678, priority: 1}, - {feePerKB: 5678, priority: 1}, // Duplicate fee and prio - {feePerKB: 5678, priority: 5}, - {feePerKB: 5678, priority: 2}, - {feePerKB: 1234, priority: 3}, - {feePerKB: 1234, priority: 1}, - {feePerKB: 1234, priority: 5}, - {feePerKB: 1234, priority: 5}, // Duplicate fee and prio - {feePerKB: 1234, priority: 2}, - {feePerKB: 10000, priority: 0}, // Higher fee, smaller prio - {feePerKB: 0, priority: 10000}, // Higher prio, lower fee - } - - // Add random data in addition to the edge conditions already manually - // specified. - randSeed := rand.Int63() - defer func() { - if t.Failed() { - t.Logf("Random numbers using seed: %v", randSeed) - } - }() - prng := rand.New(rand.NewSource(randSeed)) - for i := 0; i < 1000; i++ { - testItems = append(testItems, &txPrioItem{ - feePerKB: int64(prng.Float64() * btcutil.SatoshiPerBitcoin), - priority: prng.Float64() * 100, - }) - } - - // Test sorting by fee per KB then priority. - var highest *txPrioItem - priorityQueue := newTxPriorityQueue(len(testItems), true) - for i := 0; i < len(testItems); i++ { - prioItem := testItems[i] - if highest == nil { - highest = prioItem - } - if prioItem.feePerKB >= highest.feePerKB && - prioItem.priority > highest.priority { - - highest = prioItem - } - heap.Push(priorityQueue, prioItem) - } - - for i := 0; i < len(testItems); i++ { - prioItem := heap.Pop(priorityQueue).(*txPrioItem) - if prioItem.feePerKB >= highest.feePerKB && - prioItem.priority > highest.priority { - - t.Fatalf("fee sort: item (fee per KB: %v, "+ - "priority: %v) higher than than prev "+ - "(fee per KB: %v, priority %v)", - prioItem.feePerKB, prioItem.priority, - highest.feePerKB, highest.priority) - } - highest = prioItem - } - - // Test sorting by priority then fee per KB. - highest = nil - priorityQueue = newTxPriorityQueue(len(testItems), false) - for i := 0; i < len(testItems); i++ { - prioItem := testItems[i] - if highest == nil { - highest = prioItem - } - if prioItem.priority >= highest.priority && - prioItem.feePerKB > highest.feePerKB { - - highest = prioItem - } - heap.Push(priorityQueue, prioItem) - } - - for i := 0; i < len(testItems); i++ { - prioItem := heap.Pop(priorityQueue).(*txPrioItem) - if prioItem.priority >= highest.priority && - prioItem.feePerKB > highest.feePerKB { - - t.Fatalf("priority sort: item (fee per KB: %v, "+ - "priority: %v) higher than than prev "+ - "(fee per KB: %v, priority %v)", - prioItem.feePerKB, prioItem.priority, - highest.feePerKB, highest.priority) - } - highest = prioItem - } -} diff --git a/vendor/github.com/btcsuite/btcd/mining/policy.go b/vendor/github.com/btcsuite/btcd/mining/policy.go deleted file mode 100644 index 54b5305f..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/policy.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2014-2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package mining - -import ( - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" -) - -const ( - // UnminedHeight is the height used for the "block" height field of the - // contextual transaction information provided in a transaction store - // when it has not yet been mined into a block. - UnminedHeight = 0x7fffffff -) - -// Policy houses the policy (configuration parameters) which is used to control -// the generation of block templates. See the documentation for -// NewBlockTemplate for more details on each of these parameters are used. -type Policy struct { - // BlockMinWeight is the minimum block weight to be used when - // generating a block template. - BlockMinWeight uint32 - - // BlockMaxWeight is the maximum block weight to be used when - // generating a block template. - BlockMaxWeight uint32 - - // BlockMinWeight is the minimum block size to be used when generating - // a block template. - BlockMinSize uint32 - - // BlockMaxSize is the maximum block size to be used when generating a - // block template. - BlockMaxSize uint32 - - // BlockPrioritySize is the size in bytes for high-priority / low-fee - // transactions to be used when generating a block template. - BlockPrioritySize uint32 - - // TxMinFreeFee is the minimum fee in Satoshi/1000 bytes that is - // required for a transaction to be treated as free for mining purposes - // (block template generation). - TxMinFreeFee btcutil.Amount -} - -// minInt is a helper function to return the minimum of two ints. This avoids -// a math import and the need to cast to floats. -func minInt(a, b int) int { - if a < b { - return a - } - return b -} - -// calcInputValueAge is a helper function used to calculate the input age of -// a transaction. The input age for a txin is the number of confirmations -// since the referenced txout multiplied by its output value. The total input -// age is the sum of this value for each txin. Any inputs to the transaction -// which are currently in the mempool and hence not mined into a block yet, -// contribute no additional input age to the transaction. -func calcInputValueAge(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextBlockHeight int32) float64 { - var totalInputAge float64 - for _, txIn := range tx.TxIn { - // Don't attempt to accumulate the total input age if the - // referenced transaction output doesn't exist. - originHash := &txIn.PreviousOutPoint.Hash - originIndex := txIn.PreviousOutPoint.Index - txEntry := utxoView.LookupEntry(originHash) - if txEntry != nil && !txEntry.IsOutputSpent(originIndex) { - // Inputs with dependencies currently in the mempool - // have their block height set to a special constant. - // Their input age should computed as zero since their - // parent hasn't made it into a block yet. - var inputAge int32 - originHeight := txEntry.BlockHeight() - if originHeight == UnminedHeight { - inputAge = 0 - } else { - inputAge = nextBlockHeight - originHeight - } - - // Sum the input value times age. - inputValue := txEntry.AmountByIndex(originIndex) - totalInputAge += float64(inputValue * int64(inputAge)) - } - } - - return totalInputAge -} - -// CalcPriority returns a transaction priority given a transaction and the sum -// of each of its input values multiplied by their age (# of confirmations). -// Thus, the final formula for the priority is: -// sum(inputValue * inputAge) / adjustedTxSize -func CalcPriority(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextBlockHeight int32) float64 { - // In order to encourage spending multiple old unspent transaction - // outputs thereby reducing the total set, don't count the constant - // overhead for each input as well as enough bytes of the signature - // script to cover a pay-to-script-hash redemption with a compressed - // pubkey. This makes additional inputs free by boosting the priority - // of the transaction accordingly. No more incentive is given to avoid - // encouraging gaming future transactions through the use of junk - // outputs. This is the same logic used in the reference - // implementation. - // - // The constant overhead for a txin is 41 bytes since the previous - // outpoint is 36 bytes + 4 bytes for the sequence + 1 byte the - // signature script length. - // - // A compressed pubkey pay-to-script-hash redemption with a maximum len - // signature is of the form: - // [OP_DATA_73 <73-byte sig> + OP_DATA_35 + {OP_DATA_33 - // <33 byte compresed pubkey> + OP_CHECKSIG}] - // - // Thus 1 + 73 + 1 + 1 + 33 + 1 = 110 - overhead := 0 - for _, txIn := range tx.TxIn { - // Max inputs + size can't possibly overflow here. - overhead += 41 + minInt(110, len(txIn.SignatureScript)) - } - - serializedTxSize := tx.SerializeSize() - if overhead >= serializedTxSize { - return 0.0 - } - - inputValueAge := calcInputValueAge(tx, utxoView, nextBlockHeight) - return inputValueAge / float64(serializedTxSize-overhead) -} diff --git a/vendor/github.com/btcsuite/btcd/mining/policy_test.go b/vendor/github.com/btcsuite/btcd/mining/policy_test.go deleted file mode 100644 index f66a9c8d..00000000 --- a/vendor/github.com/btcsuite/btcd/mining/policy_test.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package mining - -import ( - "encoding/hex" - "testing" - - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" -) - -// newHashFromStr converts the passed big-endian hex string into a -// chainhash.Hash. It only differs from the one available in chainhash in that -// it panics on an error since it will only (and must only) be called with -// hard-coded, and therefore known good, hashes. -func newHashFromStr(hexStr string) *chainhash.Hash { - hash, err := chainhash.NewHashFromStr(hexStr) - if err != nil { - panic("invalid hash in source file: " + hexStr) - } - return hash -} - -// hexToBytes converts the passed hex string into bytes and will panic if there -// is an error. This is only provided for the hard-coded constants so errors in -// the source code can be detected. It will only (and must only) be called with -// hard-coded values. -func hexToBytes(s string) []byte { - b, err := hex.DecodeString(s) - if err != nil { - panic("invalid hex in source file: " + s) - } - return b -} - -// newUtxoViewpoint returns a new utxo view populated with outputs of the -// provided source transactions as if there were available at the respective -// block height specified in the heights slice. The length of the source txns -// and source tx heights must match or it will panic. -func newUtxoViewpoint(sourceTxns []*wire.MsgTx, sourceTxHeights []int32) *blockchain.UtxoViewpoint { - if len(sourceTxns) != len(sourceTxHeights) { - panic("each transaction must have its block height specified") - } - - view := blockchain.NewUtxoViewpoint() - for i, tx := range sourceTxns { - view.AddTxOuts(btcutil.NewTx(tx), sourceTxHeights[i]) - } - return view -} - -// TestCalcPriority ensures the priority calculations work as intended. -func TestCalcPriority(t *testing.T) { - // commonSourceTx1 is a valid transaction used in the tests below as an - // input to transactions that are having their priority calculated. - // - // From block 7 in main blockchain. - // tx 0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9 - commonSourceTx1 := &wire.MsgTx{ - Version: 1, - TxIn: []*wire.TxIn{{ - PreviousOutPoint: wire.OutPoint{ - Hash: chainhash.Hash{}, - Index: wire.MaxPrevOutIndex, - }, - SignatureScript: hexToBytes("04ffff001d0134"), - Sequence: 0xffffffff, - }}, - TxOut: []*wire.TxOut{{ - Value: 5000000000, - PkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c5" + - "3bc1eb68a382e97b1482ecad7b148a6909a5cb2e0ead" + - "dfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8" + - "643f656b412a3ac"), - }}, - LockTime: 0, - } - - // commonRedeemTx1 is a valid transaction used in the tests below as the - // transaction to calculate the priority for. - // - // It originally came from block 170 in main blockchain. - commonRedeemTx1 := &wire.MsgTx{ - Version: 1, - TxIn: []*wire.TxIn{{ - PreviousOutPoint: wire.OutPoint{ - Hash: *newHashFromStr("0437cd7f8525ceed232435" + - "9c2d0ba26006d92d856a9c20fa0241106ee5" + - "a597c9"), - Index: 0, - }, - SignatureScript: hexToBytes("47304402204e45e16932b8af" + - "514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5f" + - "b8cd410220181522ec8eca07de4860a4acdd12909d83" + - "1cc56cbbac4622082221a8768d1d0901"), - Sequence: 0xffffffff, - }}, - TxOut: []*wire.TxOut{{ - Value: 1000000000, - PkScript: hexToBytes("4104ae1a62fe09c5f51b13905f07f06" + - "b99a2f7159b2225f374cd378d71302fa28414e7aab37" + - "397f554a7df5f142c21c1b7303b8a0626f1baded5c72" + - "a704f7e6cd84cac"), - }, { - Value: 4000000000, - PkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c5" + - "3bc1eb68a382e97b1482ecad7b148a6909a5cb2e0ead" + - "dfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8" + - "643f656b412a3ac"), - }}, - LockTime: 0, - } - - tests := []struct { - name string // test description - tx *wire.MsgTx // tx to calc priority for - utxoView *blockchain.UtxoViewpoint // inputs to tx - nextHeight int32 // height for priority calc - want float64 // expected priority - }{ - { - name: "one height 7 input, prio tx height 169", - tx: commonRedeemTx1, - utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1}, - []int32{7}), - nextHeight: 169, - want: 5e9, - }, - { - name: "one height 100 input, prio tx height 169", - tx: commonRedeemTx1, - utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1}, - []int32{100}), - nextHeight: 169, - want: 2129629629.6296296, - }, - { - name: "one height 7 input, prio tx height 100000", - tx: commonRedeemTx1, - utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1}, - []int32{7}), - nextHeight: 100000, - want: 3086203703703.7036, - }, - { - name: "one height 100 input, prio tx height 100000", - tx: commonRedeemTx1, - utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1}, - []int32{100}), - nextHeight: 100000, - want: 3083333333333.3335, - }, - } - - for i, test := range tests { - got := CalcPriority(test.tx, test.utxoView, test.nextHeight) - if got != test.want { - t.Errorf("CalcPriority #%d (%q): unexpected priority "+ - "got %v want %v", i, test.name, got, test.want) - continue - } - } -} -- 2.11.0