Implemented new miner w/ ui interface for merged mining. Closes #177
* Miner has been rewritten * Added new miner pane * Added option for local txs * Added option to read from MergeMining contract and list them for merged mining
This commit is contained in:
parent
48488017e4
commit
429dd2a100
@ -315,9 +315,12 @@ out:
|
|||||||
// otherwise process and don't emit anything
|
// otherwise process and don't emit anything
|
||||||
if len(blocks) > 0 {
|
if len(blocks) > 0 {
|
||||||
chainManager := self.eth.ChainManager()
|
chainManager := self.eth.ChainManager()
|
||||||
|
// Test and import
|
||||||
chain := chain.NewChain(blocks)
|
chain := chain.NewChain(blocks)
|
||||||
_, err := chainManager.TestChain(chain)
|
_, err := chainManager.TestChain(chain, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
poollogger.Debugln(err)
|
||||||
|
|
||||||
self.Reset()
|
self.Reset()
|
||||||
|
|
||||||
poollogger.Debugf("Punishing peer for supplying bad chain (%v)\n", self.peer.conn.RemoteAddr())
|
poollogger.Debugf("Punishing peer for supplying bad chain (%v)\n", self.peer.conn.RemoteAddr())
|
||||||
@ -327,7 +330,7 @@ out:
|
|||||||
self.td = ethutil.Big0
|
self.td = ethutil.Big0
|
||||||
self.peer = nil
|
self.peer = nil
|
||||||
} else {
|
} else {
|
||||||
chainManager.InsertChain(chain)
|
//chainManager.InsertChain(chain)
|
||||||
for _, block := range blocks {
|
for _, block := range blocks {
|
||||||
self.Remove(block.Hash())
|
self.Remove(block.Hash())
|
||||||
}
|
}
|
||||||
|
@ -228,7 +228,7 @@ func (sm *BlockManager) Process(block *Block) (td *big.Int, err error) {
|
|||||||
func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, err error) {
|
func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, err error) {
|
||||||
sm.lastAttemptedBlock = block
|
sm.lastAttemptedBlock = block
|
||||||
|
|
||||||
state := parent.State()
|
state := parent.State().Copy()
|
||||||
|
|
||||||
// Defer the Undo on the Trie. If the block processing happened
|
// Defer the Undo on the Trie. If the block processing happened
|
||||||
// we don't want to undo but since undo only happens on dirty
|
// we don't want to undo but since undo only happens on dirty
|
||||||
@ -240,20 +240,22 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, er
|
|||||||
fmt.Printf("## %x %x ##\n", block.Hash(), block.Number)
|
fmt.Printf("## %x %x ##\n", block.Hash(), block.Number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = sm.ApplyDiff(state, parent, block)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go and C++ don't have consensus here. FIXME
|
||||||
txSha := DeriveSha(block.transactions)
|
txSha := DeriveSha(block.transactions)
|
||||||
if bytes.Compare(txSha, block.TxSha) != 0 {
|
if bytes.Compare(txSha, block.TxSha) != 0 {
|
||||||
return nil, fmt.Errorf("Error validating transaction sha. Received %x, got %x", block.TxSha, txSha)
|
return nil, fmt.Errorf("Error validating transaction sha. Received %x, got %x", block.TxSha, txSha)
|
||||||
}
|
}
|
||||||
|
|
||||||
receipts, err := sm.ApplyDiff(state, parent, block)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
receiptSha := DeriveSha(receipts)
|
receiptSha := DeriveSha(receipts)
|
||||||
if bytes.Compare(receiptSha, block.ReceiptSha) != 0 {
|
if bytes.Compare(receiptSha, block.ReceiptSha) != 0 {
|
||||||
return nil, fmt.Errorf("Error validating receipt sha. Received %x, got %x", block.ReceiptSha, receiptSha)
|
return nil, fmt.Errorf("Error validating receipt sha. Received %x, got %x", block.ReceiptSha, receiptSha)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Block validation
|
// Block validation
|
||||||
if err = sm.ValidateBlock(block, parent); err != nil {
|
if err = sm.ValidateBlock(block, parent); err != nil {
|
||||||
@ -374,7 +376,7 @@ func (sm *BlockManager) AccumelateRewards(state *state.State, block, parent *Blo
|
|||||||
|
|
||||||
uncleParent := sm.bc.GetBlock(uncle.PrevHash)
|
uncleParent := sm.bc.GetBlock(uncle.PrevHash)
|
||||||
if uncleParent == nil {
|
if uncleParent == nil {
|
||||||
return UncleError("Uncle's parent unknown")
|
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.PrevHash[0:4]))
|
||||||
}
|
}
|
||||||
|
|
||||||
if uncleParent.Number.Cmp(new(big.Int).Sub(parent.Number, big.NewInt(6))) < 0 {
|
if uncleParent.Number.Cmp(new(big.Int).Sub(parent.Number, big.NewInt(6))) < 0 {
|
||||||
|
@ -23,6 +23,8 @@ type ChainManager struct {
|
|||||||
|
|
||||||
CurrentBlock *Block
|
CurrentBlock *Block
|
||||||
LastBlockHash []byte
|
LastBlockHash []byte
|
||||||
|
|
||||||
|
workingChain *BlockChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChainManager(ethereum EthManager) *ChainManager {
|
func NewChainManager(ethereum EthManager) *ChainManager {
|
||||||
@ -225,9 +227,18 @@ func (self *ChainManager) CalcTotalDiff(block *Block) (*big.Int, error) {
|
|||||||
return td, nil
|
return td, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *ChainManager) GetBlock(hash []byte) *Block {
|
func (self *ChainManager) GetBlock(hash []byte) *Block {
|
||||||
data, _ := ethutil.Config.Db.Get(hash)
|
data, _ := ethutil.Config.Db.Get(hash)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
|
if self.workingChain != nil {
|
||||||
|
// Check the temp chain
|
||||||
|
for e := self.workingChain.Front(); e != nil; e = e.Next() {
|
||||||
|
if bytes.Compare(e.Value.(*link).block.Hash(), hash) == 0 {
|
||||||
|
return e.Value.(*link).block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,6 +321,7 @@ func NewChain(blocks Blocks) *BlockChain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This function assumes you've done your checking. No checking is done at this stage anymore
|
// This function assumes you've done your checking. No checking is done at this stage anymore
|
||||||
|
/*
|
||||||
func (self *ChainManager) InsertChain(chain *BlockChain) {
|
func (self *ChainManager) InsertChain(chain *BlockChain) {
|
||||||
for e := chain.Front(); e != nil; e = e.Next() {
|
for e := chain.Front(); e != nil; e = e.Next() {
|
||||||
link := e.Value.(*link)
|
link := e.Value.(*link)
|
||||||
@ -318,8 +330,11 @@ func (self *ChainManager) InsertChain(chain *BlockChain) {
|
|||||||
self.add(link.block)
|
self.add(link.block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (self *ChainManager) TestChain(chain *BlockChain, imp bool) (td *big.Int, err error) {
|
||||||
|
self.workingChain = chain
|
||||||
|
|
||||||
func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error) {
|
|
||||||
for e := chain.Front(); e != nil; e = e.Next() {
|
for e := chain.Front(); e != nil; e = e.Next() {
|
||||||
var (
|
var (
|
||||||
l = e.Value.(*link)
|
l = e.Value.(*link)
|
||||||
@ -348,12 +363,21 @@ func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
l.td = td
|
l.td = td
|
||||||
|
|
||||||
|
if imp {
|
||||||
|
self.SetTotalDifficulty(td)
|
||||||
|
self.add(block)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !imp {
|
||||||
if td.Cmp(self.TD) <= 0 {
|
if td.Cmp(self.TD) <= 0 {
|
||||||
err = &TDError{td, self.TD}
|
err = &TDError{td, self.TD}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.workingChain = nil
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ func (pow *EasyPow) Search(block *Block, stop <-chan struct{}) []byte {
|
|||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-stop:
|
||||||
powlogger.Infoln("Breaking from mining")
|
powlogger.Infoln("Breaking from mining")
|
||||||
|
pow.HashRate = 0
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
i++
|
i++
|
||||||
@ -55,7 +56,7 @@ func (pow *EasyPow) Search(block *Block, stop <-chan struct{}) []byte {
|
|||||||
elapsed := time.Now().UnixNano() - start
|
elapsed := time.Now().UnixNano() - start
|
||||||
hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000
|
hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000
|
||||||
pow.HashRate = int64(hashes)
|
pow.HashRate = int64(hashes)
|
||||||
powlogger.Infoln("Hashing @", int64(pow.HashRate), "khash")
|
powlogger.Infoln("Hashing @", pow.HashRate, "khash")
|
||||||
|
|
||||||
t = time.Now()
|
t = time.Now()
|
||||||
}
|
}
|
||||||
|
BIN
cmd/mist/assets/miner.png
Normal file
BIN
cmd/mist/assets/miner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
@ -12,7 +12,6 @@ import "../ext/http.js" as Http
|
|||||||
ApplicationWindow {
|
ApplicationWindow {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias miningButtonText: miningButton.text
|
|
||||||
property var ethx : Eth.ethx
|
property var ethx : Eth.ethx
|
||||||
property var browser
|
property var browser
|
||||||
|
|
||||||
@ -47,6 +46,7 @@ ApplicationWindow {
|
|||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true});
|
var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true});
|
||||||
var browser = addPlugin("./webapp.qml", {noAdd: true, close: false, section: "ethereum", active: true});
|
var browser = addPlugin("./webapp.qml", {noAdd: true, close: false, section: "ethereum", active: true});
|
||||||
|
var browser = addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true});
|
||||||
root.browser = browser;
|
root.browser = browser;
|
||||||
|
|
||||||
addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"});
|
addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"});
|
||||||
@ -252,29 +252,18 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
statusBar: StatusBar {
|
statusBar: StatusBar {
|
||||||
height: 32
|
//height: 32
|
||||||
id: statusBar
|
id: statusBar
|
||||||
RowLayout {
|
|
||||||
Button {
|
|
||||||
id: miningButton
|
|
||||||
text: "Start Mining"
|
|
||||||
onClicked: {
|
|
||||||
gui.toggleMining()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Label {
|
Label {
|
||||||
|
//y: 6
|
||||||
id: walletValueLabel
|
id: walletValueLabel
|
||||||
|
|
||||||
font.pixelSize: 10
|
font.pixelSize: 10
|
||||||
styleColor: "#797979"
|
styleColor: "#797979"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
y: 6
|
//y: 6
|
||||||
objectName: "miningLabel"
|
objectName: "miningLabel"
|
||||||
visible: true
|
visible: true
|
||||||
font.pixelSize: 10
|
font.pixelSize: 10
|
||||||
@ -283,7 +272,7 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
y: 6
|
//y: 6
|
||||||
id: lastBlockLabel
|
id: lastBlockLabel
|
||||||
objectName: "lastBlockLabel"
|
objectName: "lastBlockLabel"
|
||||||
visible: true
|
visible: true
|
||||||
@ -297,14 +286,14 @@ ApplicationWindow {
|
|||||||
id: downloadIndicator
|
id: downloadIndicator
|
||||||
value: 0
|
value: 0
|
||||||
objectName: "downloadIndicator"
|
objectName: "downloadIndicator"
|
||||||
y: 3
|
y: -4
|
||||||
x: statusBar.width / 2 - this.width / 2
|
x: statusBar.width / 2 - this.width / 2
|
||||||
width: 160
|
width: 160
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
objectName: "downloadLabel"
|
objectName: "downloadLabel"
|
||||||
y: 7
|
//y: 7
|
||||||
anchors.left: downloadIndicator.right
|
anchors.left: downloadIndicator.right
|
||||||
anchors.leftMargin: 5
|
anchors.leftMargin: 5
|
||||||
font.pixelSize: 10
|
font.pixelSize: 10
|
||||||
@ -314,7 +303,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: peerGroup
|
id: peerGroup
|
||||||
y: 7
|
//y: 7
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
MouseArea {
|
MouseArea {
|
||||||
onDoubleClicked: peerWindow.visible = true
|
onDoubleClicked: peerWindow.visible = true
|
||||||
@ -323,14 +312,9 @@ ApplicationWindow {
|
|||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: peerLabel
|
id: peerLabel
|
||||||
font.pixelSize: 8
|
font.pixelSize: 10
|
||||||
text: "0 / 0"
|
text: "0 / 0"
|
||||||
}
|
}
|
||||||
Image {
|
|
||||||
id: peerImage
|
|
||||||
width: 10; height: 10
|
|
||||||
source: "../network.png"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
254
cmd/mist/assets/qml/views/miner.qml
Normal file
254
cmd/mist/assets/qml/views/miner.qml
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.0;
|
||||||
|
import QtQuick.Layouts 1.0;
|
||||||
|
import QtQuick.Dialogs 1.0;
|
||||||
|
import QtQuick.Window 2.1;
|
||||||
|
import QtQuick.Controls.Styles 1.1
|
||||||
|
import Ethereum 1.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
property var title: "Miner"
|
||||||
|
property var iconSource: "../miner.png"
|
||||||
|
property var menuItem
|
||||||
|
|
||||||
|
color: "#00000000"
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 10
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: mainPane
|
||||||
|
color: "#00000000"
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
bottom: localTxPane.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: menu
|
||||||
|
height: 25
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: tools
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Start"
|
||||||
|
onClicked: {
|
||||||
|
eth.setGasPrice(minGasPrice.text || "10000000000000");
|
||||||
|
if (eth.toggleMining()) {
|
||||||
|
this.text = "Stop";
|
||||||
|
} else {
|
||||||
|
this.text = "Start";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 2
|
||||||
|
width: 200
|
||||||
|
TextField {
|
||||||
|
id: minGasPrice
|
||||||
|
placeholderText: "Min Gas: 10000000000000"
|
||||||
|
width: 200
|
||||||
|
validator: RegExpValidator { regExp: /\d*/ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: menu.bottom
|
||||||
|
topMargin: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "<b>Merged mining options</b>"
|
||||||
|
}
|
||||||
|
|
||||||
|
TableView {
|
||||||
|
id: mergedMiningTable
|
||||||
|
height: 300
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
Component {
|
||||||
|
id: checkBoxDelegate
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: test
|
||||||
|
CheckBox {
|
||||||
|
anchors.fill: parent
|
||||||
|
checked: styleData.value
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
var model = mergedMiningModel.get(styleData.row)
|
||||||
|
|
||||||
|
if (this.checked) {
|
||||||
|
model.id = txModel.createLocalTx(model.address, "0", "5000", "0", "")
|
||||||
|
} else {
|
||||||
|
txModel.removeWithId(model.id);
|
||||||
|
model.id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TableViewColumn{ role: "checked" ; title: "" ; width: 40 ; delegate: checkBoxDelegate }
|
||||||
|
TableViewColumn{ role: "name" ; title: "Name" ; width: 480 }
|
||||||
|
model: ListModel {
|
||||||
|
objectName: "mergedMiningModel"
|
||||||
|
id: mergedMiningModel
|
||||||
|
function addMergedMiningOption(model) {
|
||||||
|
this.append(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
/* interface test stuff
|
||||||
|
// XXX Temp. replace with above eventually
|
||||||
|
var tmpItems = ["JEVCoin", "Some coin", "Other coin", "Etc coin"];
|
||||||
|
var address = "e6716f9544a56c530d868e4bfbacb172315bdead";
|
||||||
|
for (var i = 0; i < tmpItems.length; i++) {
|
||||||
|
mergedMiningModel.append({checked: false, name: tmpItems[i], address: address, id: 0, itemId: i});
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: localTxPane
|
||||||
|
color: "#ececec"
|
||||||
|
border.color: "#cccccc"
|
||||||
|
border.width: 1
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
height: 300
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 10
|
||||||
|
anchors.fill: parent
|
||||||
|
RowLayout {
|
||||||
|
id: newLocalTx
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: 5
|
||||||
|
top: parent.top
|
||||||
|
topMargin: 5
|
||||||
|
bottomMargin: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Local tx"
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 250
|
||||||
|
color: "#00000000"
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 2
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: to
|
||||||
|
placeholderText: "To"
|
||||||
|
width: 250
|
||||||
|
validator: RegExpValidator { regExp: /[abcdefABCDEF1234567890]*/ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
property var defaultGas: "5000"
|
||||||
|
id: gas
|
||||||
|
placeholderText: "Gas"
|
||||||
|
text: defaultGas
|
||||||
|
validator: RegExpValidator { regExp: /\d*/ }
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: gasPrice
|
||||||
|
placeholderText: "Price"
|
||||||
|
validator: RegExpValidator { regExp: /\d*/ }
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: value
|
||||||
|
placeholderText: "Amount"
|
||||||
|
text: "0"
|
||||||
|
validator: RegExpValidator { regExp: /\d*/ }
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: data
|
||||||
|
placeholderText: "Data"
|
||||||
|
validator: RegExpValidator { regExp: /[abcdefABCDEF1234567890]*/ }
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "Create"
|
||||||
|
onClicked: {
|
||||||
|
if (to.text.length == 40 && gasPrice.text.length != 0 && value.text.length != 0 && gas.text.length != 0) {
|
||||||
|
txModel.createLocalTx(to.text, gasPrice.text, gas.text, value.text, data.text);
|
||||||
|
|
||||||
|
to.text = ""; gasPrice.text = "";
|
||||||
|
gas.text = gas.defaultGas;
|
||||||
|
value.text = "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TableView {
|
||||||
|
id: txTableView
|
||||||
|
anchors {
|
||||||
|
top: newLocalTx.bottom
|
||||||
|
topMargin: 5
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
TableViewColumn{ role: "to" ; title: "To" ; width: 480 }
|
||||||
|
TableViewColumn{ role: "gas" ; title: "Gas" ; width: 100 }
|
||||||
|
TableViewColumn{ role: "gasPrice" ; title: "Gas Price" ; width: 100 }
|
||||||
|
TableViewColumn{ role: "value" ; title: "Amount" ; width: 100 }
|
||||||
|
TableViewColumn{ role: "data" ; title: "Data" ; width: 100 }
|
||||||
|
|
||||||
|
model: ListModel {
|
||||||
|
id: txModel
|
||||||
|
Component.onCompleted: {
|
||||||
|
}
|
||||||
|
function removeWithId(id) {
|
||||||
|
for (var i = 0; i < this.count; i++) {
|
||||||
|
if (txModel.get(i).id == id) {
|
||||||
|
this.remove(i);
|
||||||
|
eth.removeLocalTransaction(id)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLocalTx(to, gasPrice, gas, value, data) {
|
||||||
|
var id = eth.addLocalTransaction(to, data, gas, gasPrice, value)
|
||||||
|
txModel.insert(0, {to: to, gas: gas, gasPrice: gasPrice, value: value, data: data, id: id});
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -70,10 +70,6 @@ func (gui *Gui) GetCustomIdentifier() string {
|
|||||||
return gui.clientIdentity.GetCustomIdentifier()
|
return gui.clientIdentity.GetCustomIdentifier()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) ToggleTurboMining() {
|
|
||||||
gui.miner.ToggleTurbo()
|
|
||||||
}
|
|
||||||
|
|
||||||
// functions that allow Gui to implement interface guilogger.LogSystem
|
// functions that allow Gui to implement interface guilogger.LogSystem
|
||||||
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
|
func (gui *Gui) SetLogLevel(level logger.LogLevel) {
|
||||||
gui.logLevel = level
|
gui.logLevel = level
|
||||||
@ -137,20 +133,3 @@ func (self *Gui) DumpState(hash, path string) {
|
|||||||
|
|
||||||
file.Write(stateDump)
|
file.Write(stateDump)
|
||||||
}
|
}
|
||||||
func (gui *Gui) ToggleMining() {
|
|
||||||
var txt string
|
|
||||||
if gui.eth.Mining {
|
|
||||||
utils.StopMining(gui.eth)
|
|
||||||
txt = "Start mining"
|
|
||||||
|
|
||||||
gui.getObjectByName("miningLabel").Set("visible", false)
|
|
||||||
} else {
|
|
||||||
utils.StartMining(gui.eth)
|
|
||||||
gui.miner = utils.GetMiner()
|
|
||||||
txt = "Stop mining"
|
|
||||||
|
|
||||||
gui.getObjectByName("miningLabel").Set("visible", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.win.Root().Set("miningButtonText", txt)
|
|
||||||
}
|
|
||||||
|
@ -272,8 +272,6 @@ type address struct {
|
|||||||
|
|
||||||
func (gui *Gui) loadAddressBook() {
|
func (gui *Gui) loadAddressBook() {
|
||||||
view := gui.getObjectByName("infoView")
|
view := gui.getObjectByName("infoView")
|
||||||
view.Call("clearAddress")
|
|
||||||
|
|
||||||
nameReg := gui.pipe.World().Config().Get("NameReg")
|
nameReg := gui.pipe.World().Config().Get("NameReg")
|
||||||
if nameReg != nil {
|
if nameReg != nil {
|
||||||
nameReg.EachStorage(func(name string, value *ethutil.Value) {
|
nameReg.EachStorage(func(name string, value *ethutil.Value) {
|
||||||
@ -286,6 +284,28 @@ func (gui *Gui) loadAddressBook() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Gui) loadMergedMiningOptions() {
|
||||||
|
view := self.getObjectByName("mergedMiningModel")
|
||||||
|
|
||||||
|
nameReg := self.pipe.World().Config().Get("MergeMining")
|
||||||
|
if nameReg != nil {
|
||||||
|
i := 0
|
||||||
|
nameReg.EachStorage(func(name string, value *ethutil.Value) {
|
||||||
|
if name[0] != 0 {
|
||||||
|
value.Decode()
|
||||||
|
|
||||||
|
view.Call("addMergedMiningOption", struct {
|
||||||
|
Checked bool
|
||||||
|
Name, Address string
|
||||||
|
Id, ItemId int
|
||||||
|
}{false, name, ethutil.Bytes2Hex(value.Bytes()), 0, i})
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) insertTransaction(window string, tx *chain.Transaction) {
|
func (gui *Gui) insertTransaction(window string, tx *chain.Transaction) {
|
||||||
pipe := xeth.New(gui.eth)
|
pipe := xeth.New(gui.eth)
|
||||||
nameReg := pipe.World().Config().Get("NameReg")
|
nameReg := pipe.World().Config().Get("NameReg")
|
||||||
@ -382,6 +402,7 @@ func (gui *Gui) update() {
|
|||||||
go func() {
|
go func() {
|
||||||
go gui.setInitialChainManager()
|
go gui.setInitialChainManager()
|
||||||
gui.loadAddressBook()
|
gui.loadAddressBook()
|
||||||
|
gui.loadMergedMiningOptions()
|
||||||
gui.setPeerInfo()
|
gui.setPeerInfo()
|
||||||
gui.readPreviousTransactions()
|
gui.readPreviousTransactions()
|
||||||
}()
|
}()
|
||||||
@ -410,7 +431,6 @@ func (gui *Gui) update() {
|
|||||||
chain.NewBlockEvent{},
|
chain.NewBlockEvent{},
|
||||||
chain.TxPreEvent{},
|
chain.TxPreEvent{},
|
||||||
chain.TxPostEvent{},
|
chain.TxPostEvent{},
|
||||||
miner.Event{},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// nameReg := gui.pipe.World().Config().Get("NameReg")
|
// nameReg := gui.pipe.World().Config().Get("NameReg")
|
||||||
@ -469,12 +489,14 @@ func (gui *Gui) update() {
|
|||||||
case eth.PeerListEvent:
|
case eth.PeerListEvent:
|
||||||
gui.setPeerInfo()
|
gui.setPeerInfo()
|
||||||
|
|
||||||
|
/*
|
||||||
case miner.Event:
|
case miner.Event:
|
||||||
if ev.Type == miner.Started {
|
if ev.Type == miner.Started {
|
||||||
gui.miner = ev.Miner
|
gui.miner = ev.Miner
|
||||||
} else {
|
} else {
|
||||||
gui.miner = nil
|
gui.miner = nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-peerUpdateTicker.C:
|
case <-peerUpdateTicker.C:
|
||||||
@ -483,10 +505,13 @@ func (gui *Gui) update() {
|
|||||||
statusText := "#" + gui.eth.ChainManager().CurrentBlock.Number.String()
|
statusText := "#" + gui.eth.ChainManager().CurrentBlock.Number.String()
|
||||||
lastBlockLabel.Set("text", statusText)
|
lastBlockLabel.Set("text", statusText)
|
||||||
|
|
||||||
|
miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash")
|
||||||
|
/*
|
||||||
if gui.miner != nil {
|
if gui.miner != nil {
|
||||||
pow := gui.miner.GetPow()
|
pow := gui.miner.GetPow()
|
||||||
miningLabel.Set("text", "Mining @ "+strconv.FormatInt(pow.GetHashrate(), 10)+"Khash")
|
miningLabel.Set("text", "Mining @ "+strconv.FormatInt(pow.GetHashrate(), 10)+"Khash")
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
blockLength := gui.eth.BlockPool().BlocksProcessed
|
blockLength := gui.eth.BlockPool().BlocksProcessed
|
||||||
chainLength := gui.eth.BlockPool().ChainLength
|
chainLength := gui.eth.BlockPool().ChainLength
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
"github.com/ethereum/go-ethereum/javascript"
|
"github.com/ethereum/go-ethereum/javascript"
|
||||||
|
"github.com/ethereum/go-ethereum/miner"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
"github.com/ethereum/go-ethereum/state"
|
||||||
"github.com/ethereum/go-ethereum/ui/qt"
|
"github.com/ethereum/go-ethereum/ui/qt"
|
||||||
"github.com/ethereum/go-ethereum/xeth"
|
"github.com/ethereum/go-ethereum/xeth"
|
||||||
@ -55,10 +56,15 @@ type UiLib struct {
|
|||||||
jsEngine *javascript.JSRE
|
jsEngine *javascript.JSRE
|
||||||
|
|
||||||
filterCallbacks map[int][]int
|
filterCallbacks map[int][]int
|
||||||
|
|
||||||
|
miner *miner.Miner
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
|
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
|
||||||
return &UiLib{JSXEth: xeth.NewJSXEth(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*xeth.JSFilter)}
|
lib := &UiLib{JSXEth: xeth.NewJSXEth(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*xeth.JSFilter)}
|
||||||
|
lib.miner = miner.New(eth.KeyManager().Address(), eth)
|
||||||
|
|
||||||
|
return lib
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *UiLib) Notef(args []interface{}) {
|
func (self *UiLib) Notef(args []interface{}) {
|
||||||
@ -328,3 +334,33 @@ func (self *UiLib) Call(params map[string]interface{}) (string, error) {
|
|||||||
object["data"],
|
object["data"],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *UiLib) AddLocalTransaction(to, data, gas, gasPrice, value string) int {
|
||||||
|
return self.miner.AddLocalTx(&miner.LocalTx{
|
||||||
|
To: ethutil.Hex2Bytes(to),
|
||||||
|
Data: ethutil.Hex2Bytes(data),
|
||||||
|
Gas: gas,
|
||||||
|
GasPrice: gasPrice,
|
||||||
|
Value: value,
|
||||||
|
}) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *UiLib) RemoveLocalTransaction(id int) {
|
||||||
|
self.miner.RemoveLocalTx(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *UiLib) SetGasPrice(price string) {
|
||||||
|
self.miner.MinAcceptedGasPrice = ethutil.Big(price)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *UiLib) ToggleMining() bool {
|
||||||
|
if !self.miner.Mining() {
|
||||||
|
self.miner.Start()
|
||||||
|
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
self.miner.Stop()
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -266,7 +266,7 @@ func StartMining(ethereum *eth.Ethereum) bool {
|
|||||||
go func() {
|
go func() {
|
||||||
clilogger.Infoln("Start mining")
|
clilogger.Infoln("Start mining")
|
||||||
if gminer == nil {
|
if gminer == nil {
|
||||||
gminer = miner.NewDefaultMiner(addr, ethereum)
|
gminer = miner.New(addr, ethereum)
|
||||||
}
|
}
|
||||||
// Give it some time to connect with peers
|
// Give it some time to connect with peers
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
|
306
miner/miner.go
306
miner/miner.go
@ -1,220 +1,230 @@
|
|||||||
package miner
|
package miner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum"
|
||||||
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/chain"
|
"github.com/ethereum/go-ethereum/chain"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/wire"
|
"github.com/ethereum/go-ethereum/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type LocalTx struct {
|
||||||
|
To []byte `json:"to"`
|
||||||
|
Data []byte `json:"data"`
|
||||||
|
Gas string `json:"gas"`
|
||||||
|
GasPrice string `json:"gasPrice"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *LocalTx) Sign(key []byte) *chain.Transaction {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var minerlogger = logger.NewLogger("MINER")
|
var minerlogger = logger.NewLogger("MINER")
|
||||||
|
|
||||||
type Miner struct {
|
type Miner struct {
|
||||||
pow chain.PoW
|
eth *eth.Ethereum
|
||||||
ethereum chain.EthManager
|
|
||||||
coinbase []byte
|
|
||||||
txs chain.Transactions
|
|
||||||
uncles []*chain.Block
|
|
||||||
block *chain.Block
|
|
||||||
|
|
||||||
events event.Subscription
|
events event.Subscription
|
||||||
powQuitChan chan struct{}
|
|
||||||
powDone chan struct{}
|
|
||||||
|
|
||||||
turbo bool
|
uncles chain.Blocks
|
||||||
|
localTxs map[int]*LocalTx
|
||||||
|
localTxId int
|
||||||
|
|
||||||
|
pow chain.PoW
|
||||||
|
quitCh chan struct{}
|
||||||
|
powQuitCh chan struct{}
|
||||||
|
|
||||||
|
Coinbase []byte
|
||||||
|
|
||||||
|
mining bool
|
||||||
|
|
||||||
|
MinAcceptedGasPrice *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
func New(coinbase []byte, eth *eth.Ethereum) *Miner {
|
||||||
Started = iota
|
return &Miner{
|
||||||
Stopped
|
eth: eth,
|
||||||
)
|
powQuitCh: make(chan struct{}),
|
||||||
|
pow: &chain.EasyPow{},
|
||||||
type Event struct {
|
mining: false,
|
||||||
Type int // Started || Stopped
|
localTxs: make(map[int]*LocalTx),
|
||||||
Miner *Miner
|
MinAcceptedGasPrice: big.NewInt(10000000000000),
|
||||||
|
Coinbase: coinbase,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Miner) GetPow() chain.PoW {
|
func (self *Miner) GetPow() chain.PoW {
|
||||||
return self.pow
|
return self.pow
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultMiner(coinbase []byte, ethereum chain.EthManager) *Miner {
|
func (self *Miner) AddLocalTx(tx *LocalTx) int {
|
||||||
miner := Miner{
|
minerlogger.Infof("Added local tx (%x %v / %v)\n", tx.To[0:4], tx.GasPrice, tx.Value)
|
||||||
pow: &chain.EasyPow{},
|
|
||||||
ethereum: ethereum,
|
self.localTxId++
|
||||||
coinbase: coinbase,
|
self.localTxs[self.localTxId] = tx
|
||||||
|
self.eth.EventMux().Post(tx)
|
||||||
|
|
||||||
|
return self.localTxId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Miner) RemoveLocalTx(id int) {
|
||||||
|
if tx := self.localTxs[id]; tx != nil {
|
||||||
|
minerlogger.Infof("Removed local tx (%x %v / %v)\n", tx.To[0:4], tx.GasPrice, tx.Value)
|
||||||
|
}
|
||||||
|
self.eth.EventMux().Post(&LocalTx{})
|
||||||
|
|
||||||
|
delete(self.localTxs, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Miner) Start() {
|
||||||
|
if self.mining {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return &miner
|
minerlogger.Infoln("Starting mining operations")
|
||||||
|
self.mining = true
|
||||||
|
self.quitCh = make(chan struct{})
|
||||||
|
self.powQuitCh = make(chan struct{})
|
||||||
|
|
||||||
|
mux := self.eth.EventMux()
|
||||||
|
self.events = mux.Subscribe(chain.NewBlockEvent{}, chain.TxPreEvent{}, &LocalTx{})
|
||||||
|
|
||||||
|
go self.update()
|
||||||
|
go self.mine()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Miner) ToggleTurbo() {
|
func (self *Miner) Stop() {
|
||||||
self.turbo = !self.turbo
|
if !self.mining {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
self.pow.Turbo(self.turbo)
|
self.mining = false
|
||||||
|
|
||||||
|
minerlogger.Infoln("Stopping mining operations")
|
||||||
|
|
||||||
|
self.events.Unsubscribe()
|
||||||
|
|
||||||
|
close(self.quitCh)
|
||||||
|
close(self.powQuitCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (miner *Miner) Start() {
|
func (self *Miner) Mining() bool {
|
||||||
|
return self.mining
|
||||||
// Insert initial TXs in our little miner 'pool'
|
|
||||||
miner.txs = miner.ethereum.TxPool().Flush()
|
|
||||||
miner.block = miner.ethereum.ChainManager().NewBlock(miner.coinbase)
|
|
||||||
|
|
||||||
mux := miner.ethereum.EventMux()
|
|
||||||
miner.events = mux.Subscribe(chain.NewBlockEvent{}, chain.TxPreEvent{})
|
|
||||||
|
|
||||||
// Prepare inital block
|
|
||||||
//miner.ethereum.BlockManager().Prepare(miner.block.State(), miner.block.State())
|
|
||||||
go miner.listener()
|
|
||||||
|
|
||||||
minerlogger.Infoln("Started")
|
|
||||||
mux.Post(Event{Started, miner})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (miner *Miner) Stop() {
|
func (self *Miner) update() {
|
||||||
minerlogger.Infoln("Stopping...")
|
out:
|
||||||
miner.events.Unsubscribe()
|
|
||||||
miner.ethereum.EventMux().Post(Event{Stopped, miner})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (miner *Miner) listener() {
|
|
||||||
miner.startMining()
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case event := <-miner.events.Chan():
|
case event := <-self.events.Chan():
|
||||||
switch event := event.(type) {
|
switch event := event.(type) {
|
||||||
case chain.NewBlockEvent:
|
case chain.NewBlockEvent:
|
||||||
miner.stopMining()
|
|
||||||
|
|
||||||
block := event.Block
|
block := event.Block
|
||||||
//minerlogger.Infoln("Got new block via Reactor")
|
if self.eth.ChainManager().HasBlock(block.Hash()) {
|
||||||
if bytes.Compare(miner.ethereum.ChainManager().CurrentBlock.Hash(), block.Hash()) == 0 {
|
self.reset()
|
||||||
// TODO: Perhaps continue mining to get some uncle rewards
|
self.eth.TxPool().RemoveSet(block.Transactions())
|
||||||
//minerlogger.Infoln("New top block found resetting state")
|
go self.mine()
|
||||||
|
} else if true {
|
||||||
// Filter out which Transactions we have that were not in this block
|
// do uncle stuff
|
||||||
var newtxs []*chain.Transaction
|
|
||||||
for _, tx := range miner.txs {
|
|
||||||
found := false
|
|
||||||
for _, othertx := range block.Transactions() {
|
|
||||||
if bytes.Compare(tx.Hash(), othertx.Hash()) == 0 {
|
|
||||||
found = true
|
|
||||||
}
|
}
|
||||||
|
case chain.TxPreEvent, *LocalTx:
|
||||||
|
self.reset()
|
||||||
|
go self.mine()
|
||||||
}
|
}
|
||||||
if found == false {
|
case <-self.quitCh:
|
||||||
newtxs = append(newtxs, tx)
|
break out
|
||||||
}
|
|
||||||
}
|
|
||||||
miner.txs = newtxs
|
|
||||||
} else {
|
|
||||||
if bytes.Compare(block.PrevHash, miner.ethereum.ChainManager().CurrentBlock.PrevHash) == 0 {
|
|
||||||
minerlogger.Infoln("Adding uncle block")
|
|
||||||
miner.uncles = append(miner.uncles, block)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
miner.startMining()
|
|
||||||
|
|
||||||
case chain.TxPreEvent:
|
|
||||||
miner.stopMining()
|
|
||||||
|
|
||||||
found := false
|
|
||||||
for _, ctx := range miner.txs {
|
|
||||||
if found = bytes.Compare(ctx.Hash(), event.Tx.Hash()) == 0; found {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
miner.startMining()
|
|
||||||
}
|
|
||||||
if found == false {
|
|
||||||
// Undo all previous commits
|
|
||||||
miner.block.Undo()
|
|
||||||
// Apply new transactions
|
|
||||||
miner.txs = append(miner.txs, event.Tx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-miner.powDone:
|
|
||||||
miner.startMining()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (miner *Miner) startMining() {
|
func (self *Miner) reset() {
|
||||||
if miner.powDone == nil {
|
println("reset")
|
||||||
miner.powDone = make(chan struct{})
|
close(self.powQuitCh)
|
||||||
}
|
self.powQuitCh = make(chan struct{})
|
||||||
miner.powQuitChan = make(chan struct{})
|
|
||||||
go miner.mineNewBlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (miner *Miner) stopMining() {
|
func (self *Miner) mine() {
|
||||||
println("stop mining")
|
var (
|
||||||
_, isopen := <-miner.powQuitChan
|
blockManager = self.eth.BlockManager()
|
||||||
if isopen {
|
chainMan = self.eth.ChainManager()
|
||||||
close(miner.powQuitChan)
|
block = chainMan.NewBlock(self.Coinbase)
|
||||||
}
|
)
|
||||||
//<-miner.powDone
|
block.MinGasPrice = self.MinAcceptedGasPrice
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Miner) mineNewBlock() {
|
|
||||||
blockManager := self.ethereum.BlockManager()
|
|
||||||
chainMan := self.ethereum.ChainManager()
|
|
||||||
|
|
||||||
self.block = chainMan.NewBlock(self.coinbase)
|
|
||||||
|
|
||||||
// Apply uncles
|
// Apply uncles
|
||||||
if len(self.uncles) > 0 {
|
if len(self.uncles) > 0 {
|
||||||
self.block.SetUncles(self.uncles)
|
block.SetUncles(self.uncles)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the transactions by nonce in case of odd network propagation
|
parent := chainMan.GetBlock(block.PrevHash)
|
||||||
sort.Sort(chain.TxByNonce{self.txs})
|
coinbase := block.State().GetOrNewStateObject(block.Coinbase)
|
||||||
|
coinbase.SetGasPool(block.CalcGasLimit(parent))
|
||||||
|
|
||||||
|
transactions := self.finiliseTxs()
|
||||||
|
|
||||||
// Accumulate all valid transactions and apply them to the new state
|
// Accumulate all valid transactions and apply them to the new state
|
||||||
// Error may be ignored. It's not important during mining
|
// Error may be ignored. It's not important during mining
|
||||||
parent := self.ethereum.ChainManager().GetBlock(self.block.PrevHash)
|
receipts, txs, _, erroneous, err := blockManager.ProcessTransactions(coinbase, block.State(), block, block, transactions)
|
||||||
coinbase := self.block.State().GetOrNewStateObject(self.block.Coinbase)
|
|
||||||
coinbase.SetGasPool(self.block.CalcGasLimit(parent))
|
|
||||||
receipts, txs, unhandledTxs, erroneous, err := blockManager.ProcessTransactions(coinbase, self.block.State(), self.block, self.block, self.txs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
minerlogger.Debugln(err)
|
minerlogger.Debugln(err)
|
||||||
}
|
}
|
||||||
self.ethereum.TxPool().RemoveSet(erroneous)
|
self.eth.TxPool().RemoveSet(erroneous)
|
||||||
self.txs = append(txs, unhandledTxs...)
|
|
||||||
|
|
||||||
self.block.SetTransactions(txs)
|
block.SetTransactions(txs)
|
||||||
self.block.SetReceipts(receipts)
|
block.SetReceipts(receipts)
|
||||||
|
|
||||||
// Accumulate the rewards included for this block
|
// Accumulate the rewards included for this block
|
||||||
blockManager.AccumelateRewards(self.block.State(), self.block, parent)
|
blockManager.AccumelateRewards(block.State(), block, parent)
|
||||||
|
|
||||||
self.block.State().Update()
|
block.State().Update()
|
||||||
|
|
||||||
minerlogger.Infof("Mining on block. Includes %v transactions", len(self.txs))
|
minerlogger.Infof("Mining on block. Includes %v transactions", len(transactions))
|
||||||
|
|
||||||
// Find a valid nonce
|
// Find a valid nonce
|
||||||
nonce := self.pow.Search(self.block, self.powQuitChan)
|
nonce := self.pow.Search(block, self.powQuitCh)
|
||||||
if nonce != nil {
|
if nonce != nil {
|
||||||
self.block.Nonce = nonce
|
block.Nonce = nonce
|
||||||
lchain := chain.NewChain(chain.Blocks{self.block})
|
lchain := chain.NewChain(chain.Blocks{block})
|
||||||
_, err := chainMan.TestChain(lchain)
|
_, err := chainMan.TestChain(lchain, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
minerlogger.Infoln(err)
|
minerlogger.Infoln(err)
|
||||||
} else {
|
} else {
|
||||||
self.ethereum.ChainManager().InsertChain(lchain)
|
//chainMan.InsertChain(lchain)
|
||||||
self.ethereum.Broadcast(wire.MsgBlockTy, []interface{}{self.block.Value().Val})
|
self.eth.EventMux().Post(chain.NewBlockEvent{block})
|
||||||
minerlogger.Infof("🔨 Mined block %x\n", self.block.Hash())
|
self.eth.Broadcast(wire.MsgBlockTy, []interface{}{block.Value().Val})
|
||||||
minerlogger.Infoln(self.block)
|
|
||||||
// Gather the new batch of transactions currently in the tx pool
|
minerlogger.Infof("🔨 Mined block %x\n", block.Hash())
|
||||||
self.txs = self.ethereum.TxPool().CurrentTransactions()
|
minerlogger.Infoln(block)
|
||||||
self.ethereum.EventMux().Post(chain.NewBlockEvent{self.block})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue mining on the next block
|
go self.mine()
|
||||||
self.startMining()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Miner) finiliseTxs() chain.Transactions {
|
||||||
|
// Sort the transactions by nonce in case of odd network propagation
|
||||||
|
var txs chain.Transactions
|
||||||
|
|
||||||
|
state := self.eth.BlockManager().TransState()
|
||||||
|
// XXX This has to change. Coinbase is, for new, same as key.
|
||||||
|
key := self.eth.KeyManager()
|
||||||
|
for _, ltx := range self.localTxs {
|
||||||
|
tx := chain.NewTransactionMessage(ltx.To, ethutil.Big(ltx.Value), ethutil.Big(ltx.Gas), ethutil.Big(ltx.GasPrice), ltx.Data)
|
||||||
|
tx.Nonce = state.GetNonce(self.Coinbase)
|
||||||
|
state.SetNonce(self.Coinbase, tx.Nonce+1)
|
||||||
|
|
||||||
|
tx.Sign(key.PrivateKey())
|
||||||
|
|
||||||
|
txs = append(txs, tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
txs = append(txs, self.eth.TxPool().CurrentTransactions()...)
|
||||||
|
sort.Sort(chain.TxByNonce{txs})
|
||||||
|
|
||||||
|
return txs
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/eth-go/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Connection struct {
|
type Connection struct {
|
||||||
|
@ -2,7 +2,7 @@ package p2p
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
// "fmt"
|
// "fmt"
|
||||||
"github.com/ethereum/eth-go/ethutil"
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MsgCode uint8
|
type MsgCode uint8
|
||||||
|
@ -3,9 +3,10 @@ package p2p
|
|||||||
import (
|
import (
|
||||||
// "fmt"
|
// "fmt"
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/ethereum/eth-go/ethutil"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/ethutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupMessenger(handlers Handlers) (*TestNetworkConnection, chan *PeerError, *Messenger) {
|
func setupMessenger(handlers Handlers) (*TestNetworkConnection, chan *PeerError, *Messenger) {
|
||||||
|
4
peer.go
4
peer.go
@ -24,7 +24,7 @@ const (
|
|||||||
// The size of the output buffer for writing messages
|
// The size of the output buffer for writing messages
|
||||||
outputBufferSize = 50
|
outputBufferSize = 50
|
||||||
// Current protocol version
|
// Current protocol version
|
||||||
ProtocolVersion = 37
|
ProtocolVersion = 39
|
||||||
// Current P2P version
|
// Current P2P version
|
||||||
P2PVersion = 2
|
P2PVersion = 2
|
||||||
// Ethereum network version
|
// Ethereum network version
|
||||||
@ -863,7 +863,7 @@ func (p *Peer) String() string {
|
|||||||
strConnectType = "disconnected"
|
strConnectType = "disconnected"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("[%s] (%s) %v %s [%s]", strConnectType, strBoundType, p.conn.RemoteAddr(), p.version, p.caps)
|
return fmt.Sprintf("[%s] (%s) %v %s", strConnectType, strBoundType, p.conn.RemoteAddr(), p.version)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ func (self *Config) Get(name string) *Object {
|
|||||||
objectAddr := configCtrl.GetStorage(ethutil.BigD([]byte{0}))
|
objectAddr := configCtrl.GetStorage(ethutil.BigD([]byte{0}))
|
||||||
domainAddr := (&Object{self.pipe.World().safeGet(objectAddr.Bytes())}).StorageString("DnsReg").Bytes()
|
domainAddr := (&Object{self.pipe.World().safeGet(objectAddr.Bytes())}).StorageString("DnsReg").Bytes()
|
||||||
return &Object{self.pipe.World().safeGet(domainAddr)}
|
return &Object{self.pipe.World().safeGet(domainAddr)}
|
||||||
|
case "MergeMining":
|
||||||
|
addr = []byte{4}
|
||||||
default:
|
default:
|
||||||
addr = ethutil.RightPadBytes([]byte(name), 32)
|
addr = ethutil.RightPadBytes([]byte(name), 32)
|
||||||
}
|
}
|
||||||
|
@ -254,6 +254,10 @@ func (self *JSXEth) CompileMutan(code string) string {
|
|||||||
return ethutil.Bytes2Hex(data)
|
return ethutil.Bytes2Hex(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *JSXEth) FindInConfig(str string) string {
|
||||||
|
return ethutil.Bytes2Hex(self.World().Config().Get(str).Address())
|
||||||
|
}
|
||||||
|
|
||||||
func ToJSMessages(messages state.Messages) *ethutil.List {
|
func ToJSMessages(messages state.Messages) *ethutil.List {
|
||||||
var msgs []JSMessage
|
var msgs []JSMessage
|
||||||
for _, m := range messages {
|
for _, m := range messages {
|
||||||
|
Loading…
Reference in New Issue
Block a user