merged
This commit is contained in:
		| @@ -1,6 +1,6 @@ | |||||||
| language: go | language: go | ||||||
| go: | go: | ||||||
|   - tip |   - 1.4.1 | ||||||
| before_install: | before_install: | ||||||
|   - sudo add-apt-repository ppa:beineri/opt-qt54 -y |   - sudo add-apt-repository ppa:beineri/opt-qt54 -y | ||||||
|   - sudo apt-get update -qq |   - sudo apt-get update -qq | ||||||
| @@ -12,7 +12,7 @@ install: | |||||||
|   - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi |   - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi | ||||||
|   - go get github.com/mattn/goveralls |   - go get github.com/mattn/goveralls | ||||||
|   - go get -d github.com/obscuren/qml && cd $HOME/gopath/src/github.com/obscuren/qml && git checkout v1 && cd $TRAVIS_BUILD_DIR |   - go get -d github.com/obscuren/qml && cd $HOME/gopath/src/github.com/obscuren/qml && git checkout v1 && cd $TRAVIS_BUILD_DIR | ||||||
|   - ETH_DEPS=$(go list -f '{{.Imports}} {{.TestImports}} {{.XTestImports}}' github.com/ethereum/go-ethereum/... | sed -e 's/\[//g' | sed -e 's/\]//g' | sed -e 's/C //g'); if [ "$ETH_DEPS" ]; then go get $ETH_DEPS; fi |   - ETH_DEPS=$(go list -f '{{.Imports}} {{.TestImports}} {{.XTestImports}}' github.com/ethereum/go-ethereum/... | sed -e 's/\[//g' | sed -e 's/\]//g' | sed -e 's/C //g'); if [ "$ETH_DEPS" ]; then go get -d $ETH_DEPS; fi | ||||||
| before_script: | before_script: | ||||||
|   - gofmt -l -w . |   - gofmt -l -w . | ||||||
|   - goimports -l -w . |   - goimports -l -w . | ||||||
| @@ -20,8 +20,7 @@ before_script: | |||||||
|   # - go vet ./... |   # - go vet ./... | ||||||
|   # - go test -race ./... |   # - go test -race ./... | ||||||
| script: | script: | ||||||
|   - ./gocoverage.sh |   - ./gocoverage.sh && if [ "$COVERALLS_TOKEN" ]; then goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN; fi | ||||||
|   - if [ "$COVERALLS_TOKEN" ]; then goveralls -coverprofile=profile.cov -service=travis-ci -repotoken $COVERALLS_TOKEN; fi |  | ||||||
| env: | env: | ||||||
|   global: |   global: | ||||||
|     - PKG_CONFIG_PATH=/opt/qt54/lib/pkgconfig |     - PKG_CONFIG_PATH=/opt/qt54/lib/pkgconfig | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,19 +1,18 @@ | |||||||
|  | ## Ethereum Go | ||||||
|  |  | ||||||
|  | Ethereum Go Client © 2014 Jeffrey Wilcke. | ||||||
|  |  | ||||||
|  |           | Linux   | OSX | Windows | ||||||
|  | ----------|---------|-----|-------- | ||||||
|  | develop   | [](http://build.ethdev.com/builders/Linux%20Go%20develop%20branch/builds/-1) | [](http://build.ethdev.com/builders/OSX%20Go%20develop%20branch/builds/-1) | N/A | ||||||
|  | master    | [](http://build.ethdev.com/builders/Linux%20Go%20master%20branch/builds/-1) | [](http://build.ethdev.com/builders/OSX%20Go%20master%20branch/builds/-1) | N/A | ||||||
|  |  | ||||||
| [](https://waffle.io/ethereum/go-ethereum) | [](https://waffle.io/ethereum/go-ethereum) | ||||||
| [](https://waffle.io/ethereum/go-ethereum) | [](https://waffle.io/ethereum/go-ethereum) | ||||||
| [](http://waffle.io/ethereum/go-ethereum) | [](http://waffle.io/ethereum/go-ethereum) | ||||||
| [](https://gitter.im/ethereum/go-ethereum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) | [](https://gitter.im/ethereum/go-ethereum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) | ||||||
|  |  | ||||||
|  |  | ||||||
| Ethereum PoC-8 |  | ||||||
| ======== |  | ||||||
|  |  | ||||||
| * [](http://build.ethdev.com:8010/builders/Linux%20Go%20master%20branch/builds/-1) master |  | ||||||
| * [](http://build.ethdev.com:8010/builders/Linux%20Go%20develop%20branch/builds/-1) develop |  | ||||||
| * [](https://travis-ci.org/ethereum/go-ethereum) travis-ci |  | ||||||
| * [](https://coveralls.io/r/ethereum/go-ethereum?branch=develop) |  | ||||||
|  |  | ||||||
| Ethereum Go Client © 2014 Jeffrey Wilcke. |  | ||||||
|  |  | ||||||
| Build | Build | ||||||
| ===== | ===== | ||||||
|  |  | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ var ( | |||||||
| 	AddPeer         string | 	AddPeer         string | ||||||
| 	MaxPeer         int | 	MaxPeer         int | ||||||
| 	GenAddr         bool | 	GenAddr         bool | ||||||
| 	UseSeed         bool | 	SeedNode        string | ||||||
| 	SecretFile      string | 	SecretFile      string | ||||||
| 	ExportDir       string | 	ExportDir       string | ||||||
| 	NonInteractive  bool | 	NonInteractive  bool | ||||||
| @@ -96,12 +96,12 @@ func Init() { | |||||||
| 	flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)") | 	flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)") | ||||||
| 	flag.StringVar(&PMPGateway, "pmp", "", "Gateway IP for PMP") | 	flag.StringVar(&PMPGateway, "pmp", "", "Gateway IP for PMP") | ||||||
| 	flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers") | 	flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers") | ||||||
| 	flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on") | 	flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on") | ||||||
| 	flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on") | 	flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on") | ||||||
| 	flag.BoolVar(&StartRpc, "rpc", false, "start rpc server") | 	flag.BoolVar(&StartRpc, "rpc", false, "start rpc server") | ||||||
| 	flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server") | 	flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server") | ||||||
| 	flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)") | 	flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)") | ||||||
| 	flag.BoolVar(&UseSeed, "seed", true, "seed peers") | 	flag.StringVar(&SeedNode, "seednode", "poc-8.ethdev.com:30303", "ip:port of seed node to connect to. Set to blank for skip") | ||||||
| 	flag.BoolVar(&SHH, "shh", true, "whisper protocol (on)") | 	flag.BoolVar(&SHH, "shh", true, "whisper protocol (on)") | ||||||
| 	flag.BoolVar(&Dial, "dial", true, "dial out connections (on)") | 	flag.BoolVar(&Dial, "dial", true, "dial out connections (on)") | ||||||
| 	flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") | 	flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") | ||||||
|   | |||||||
| @@ -134,7 +134,7 @@ func main() { | |||||||
| 		utils.StartWebSockets(ethereum, WsPort) | 		utils.StartWebSockets(ethereum, WsPort) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	utils.StartEthereum(ethereum, UseSeed) | 	utils.StartEthereum(ethereum, SeedNode) | ||||||
|  |  | ||||||
| 	if StartJsConsole { | 	if StartJsConsole { | ||||||
| 		InitJsConsole(ethereum) | 		InitJsConsole(ethereum) | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|  |  | ||||||
| <h1>JevCoin</h1> | <h1>JevCoin <code id="address"></code></h1> | ||||||
| <div> | <div> | ||||||
| 	<strong>Balance</strong> | 	<strong>Balance</strong> | ||||||
| 	<span id="balance"></strong> | 	<span id="balance"></strong> | ||||||
| @@ -20,7 +20,11 @@ | |||||||
| 	<button onclick="transact()">Send</button> | 	<button onclick="transact()">Send</button> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
|  | <hr> | ||||||
|  |  | ||||||
| <table width="100%" id="table"> | <table width="100%" id="table"> | ||||||
|  | 	<tr><td style="width:40%;">Address</td><td>Balance</td></tr> | ||||||
|  | 	<tbody id="table_body"></tbody> | ||||||
| </table> | </table> | ||||||
|  |  | ||||||
| </body> | </body> | ||||||
| @@ -29,8 +33,8 @@ | |||||||
| 	var web3 = require('web3'); | 	var web3 = require('web3'); | ||||||
| 	var eth = web3.eth; | 	var eth = web3.eth; | ||||||
|  |  | ||||||
| 	web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); | 	web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); | ||||||
| 	var desc =  [{ | 	var desc = [{ | ||||||
| 		"name": "balance(address)", | 		"name": "balance(address)", | ||||||
| 		"type": "function", | 		"type": "function", | ||||||
| 		"inputs": [{ | 		"inputs": [{ | ||||||
| @@ -54,57 +58,89 @@ | |||||||
| 		}], | 		}], | ||||||
| 		"outputs": [] | 		"outputs": [] | ||||||
| 	}, { | 	}, { | ||||||
| 		"name":"Changed", | 		"name":"changed", | ||||||
| 		"type":"event", | 		"type":"event", | ||||||
| 		"inputs": [ | 		"inputs": [ | ||||||
| 			{"name":"to","type":"address","indexed":true}, | 			{"name":"to","type":"address","indexed":true}, | ||||||
| 			{"name":"amount","type":"uint256","indexed":false}, | 			{"name":"from","type":"address","indexed":true}, | ||||||
| 		], | 		], | ||||||
| 	}]; | 	}]; | ||||||
|  |  | ||||||
|     var address = web3.db.get("jevcoin", "address"); | 	var address = localStorage.getItem("address"); | ||||||
|     if( address.length == 0 ) { | 	// deploy if not exist | ||||||
|         var code = "0x60056011565b60b88060356000396000f35b64e8d4a51000600033600160a060020a0316600052602052604060002081905550560060e060020a6000350480637bb98a68146028578063d0679d34146034578063e3d670d714604657005b602e60b3565b60006000f35b60406004356024356059565b60006000f35b604f6004356091565b8060005260206000f35b8060005281600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660206000a25050565b6000600082600160a060020a03166000526020526040600020549050919050565b5b60008156"; | 	if (address == null) { | ||||||
|         address = web3.eth.transact({ | 		var code = "0x60056013565b610132806100356000396000f35b620f4240600033600160a060020a0316600052602052604060002081905550560060e060020a6000350480637bb98a681461002b578063d0679d3414610039578063e3d670d71461004d57005b61003361012d565b60006000f35b610047600435602435610062565b60006000f35b61005860043561010b565b8060005260206000f35b80600033600160a060020a0316600052602052604060002054106100855761008a565b610107565b80600033600160a060020a0316600052602052604060002090815403908190555080600083600160a060020a0316600052602052604060002090815401908190555081600160a060020a031633600160a060020a03167f1863989b4bb7c5c3941722099764574df7a459f9f9c6b6cdca35ddc9731792b860006000a35b5050565b6000600082600160a060020a03166000526020526040600020549050919050565b5b60008156"; | ||||||
|             data: code, | 		address = web3.eth.transact({ | ||||||
|             gasPrice: "1000000000000000", | 			data: code, | ||||||
|             gas: "10000", | 			gasPrice: "1000000000000000", | ||||||
|         }); | 			gas: "10000", | ||||||
|         web3.db.put("jevcoin", "address", address); | 		}); | ||||||
|     } |         	localStorage.setItem("address", address); | ||||||
|  | 	} | ||||||
|  | 	document.querySelector("#address").innerHTML = address.toUpperCase(); | ||||||
|  |  | ||||||
| 	var contract = web3.eth.contract(address, desc); | 	var contract = web3.eth.contract(address, desc); | ||||||
| 	contract.Changed({to: "0xaa"}).changed(function(e) { | 	contract.changed({from: eth.accounts[0]}).changed(function() { | ||||||
| 		console.log("e: " + JSON.stringify(e)); | 		refresh(); | ||||||
|  | 	}); | ||||||
|  | 	eth.watch('chain').changed(function() { | ||||||
|  | 		refresh(); | ||||||
| 	}); | 	}); | ||||||
| 	contract.send( "0xaa", 10000 ); |  | ||||||
| 	function reflesh() { |  | ||||||
|         document.querySelector("#balance").innerHTML = contract.balance(eth.coinbase); |  | ||||||
|  |  | ||||||
| 		var table = document.querySelector("#table"); | 	function refresh() { | ||||||
|  |         	document.querySelector("#balance").innerHTML = contract.balance(eth.coinbase); | ||||||
|  |  | ||||||
|  | 		var table = document.querySelector("#table_body"); | ||||||
| 		table.innerHTML = ""; // clear | 		table.innerHTML = ""; // clear | ||||||
|  |  | ||||||
| 		var storage = eth.storageAt(address); | 		var storage = eth.storageAt(address); | ||||||
|  | 		table.innerHTML = ""; | ||||||
| 		for( var item in storage ) { | 		for( var item in storage ) { | ||||||
| 			table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>"; | 			table.innerHTML += "<tr><td>"+item.toUpperCase()+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>"; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function transact() { | 	function transact() { | ||||||
| 		var to = document.querySelector("#address").value; | 		var to = document.querySelector("#address").value; | ||||||
|         if( to.length == 0 ) { |  | ||||||
|             to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3"; |  | ||||||
|         } else { |  | ||||||
|             to = "0x"+to; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         var value = parseInt( document.querySelector("#amount").value ); | 		if( to.length == 0 ) { | ||||||
|  | 			to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3"; | ||||||
|  | 		} else { | ||||||
|  | 			to = "0x"+to; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|         contract.transact({gas: "10000", gasprice: eth.gasPrice}).send( to, value ); | 		var value = parseInt( document.querySelector("#amount").value ); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     reflesh(); | 		contract.send( to, value ); | ||||||
|         </script> | 	} | ||||||
|  |  | ||||||
|  | 	refresh(); | ||||||
|  | </script> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | <!-- | ||||||
|  | contract JevCoin { | ||||||
|  |     function JevCoin() | ||||||
|  |     { | ||||||
|  |         balances[msg.sender] = 1000000; | ||||||
|  |     } | ||||||
|  |   | ||||||
|  |     event changed(address indexed from, address indexed to); | ||||||
|  |     function send(address to, uint value) | ||||||
|  |     { | ||||||
|  |         if( balances[msg.sender] < value ) return; | ||||||
|  |   | ||||||
|  |         balances[msg.sender] -= value; | ||||||
|  |         balances[to] += value; | ||||||
|  |   | ||||||
|  |         changed(msg.sender, to); | ||||||
|  |     } | ||||||
|  |   | ||||||
|  |     function balance(address who) constant returns(uint t) | ||||||
|  |     { | ||||||
|  |         t = balances[who]; | ||||||
|  |     } | ||||||
|  |   | ||||||
|  |     mapping(address => uint256) balances; | ||||||
|  |  } | ||||||
|  | -!> | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
									
									
									
									
										vendored
									
									
								
							| @@ -1043,33 +1043,16 @@ var ProviderManager = function() { | |||||||
|  |  | ||||||
|     var self = this; |     var self = this; | ||||||
|     var poll = function () { |     var poll = function () { | ||||||
|         if (self.provider) { |         self.polls.forEach(function (data) { | ||||||
|             var pollsBatch = self.polls.map(function (data) { |             var result = self.send(data.data); | ||||||
|                 return data.data; |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|             var payload = jsonrpc.toBatchPayload(pollsBatch); |             if (!(result instanceof Array) || result.length === 0) { | ||||||
|             var results = self.provider.send(payload); |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             self.polls.forEach(function (data, index) { |             data.callback(result); | ||||||
|                 var result = results[index]; |         }); | ||||||
|  |  | ||||||
|                 if (!jsonrpc.isValidResponse(result)) { |  | ||||||
|                     console.log(result); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 result = result.result; |  | ||||||
|                 // dont call the callback if result is not an array, or empty one |  | ||||||
|                 if (!(result instanceof Array) || result.length === 0) { |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 data.callback(result); |  | ||||||
|  |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|         setTimeout(poll, 1000); |         setTimeout(poll, 1000); | ||||||
|     }; |     }; | ||||||
|     poll(); |     poll(); | ||||||
|   | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -42,33 +42,16 @@ var ProviderManager = function() { | |||||||
|  |  | ||||||
|     var self = this; |     var self = this; | ||||||
|     var poll = function () { |     var poll = function () { | ||||||
|         if (self.provider) { |         self.polls.forEach(function (data) { | ||||||
|             var pollsBatch = self.polls.map(function (data) { |             var result = self.send(data.data); | ||||||
|                 return data.data; |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|             var payload = jsonrpc.toBatchPayload(pollsBatch); |             if (!(result instanceof Array) || result.length === 0) { | ||||||
|             var results = self.provider.send(payload); |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             self.polls.forEach(function (data, index) { |             data.callback(result); | ||||||
|                 var result = results[index]; |         }); | ||||||
|  |  | ||||||
|                 if (!jsonrpc.isValidResponse(result)) { |  | ||||||
|                     console.log(result); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 result = result.result; |  | ||||||
|                 // dont call the callback if result is not an array, or empty one |  | ||||||
|                 if (!(result instanceof Array) || result.length === 0) { |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 data.callback(result); |  | ||||||
|  |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|         setTimeout(poll, 1000); |         setTimeout(poll, 1000); | ||||||
|     }; |     }; | ||||||
|     poll(); |     poll(); | ||||||
|   | |||||||
| @@ -1,75 +1,83 @@ | |||||||
| <!doctype> | <!doctype> | ||||||
| <html> | <html> | ||||||
|     <head> | <head> | ||||||
|         <title>Ethereum</title> | <title>Ethereum</title> | ||||||
|         <script type="text/javascript" src="../ext/bignumber.min.js"></script> | <script type="text/javascript" src="../ext/bignumber.min.js"></script> | ||||||
|         <script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> | <script type="text/javascript" src="../ext/ethereum.js/dist/ethereum.js"></script> | ||||||
|         <style type="text/css"> | <style type="text/css"> | ||||||
|             body { |     body { | ||||||
|                 font-family: Helvetica; |         font-family: Helvetica; | ||||||
|             } |     } | ||||||
|         div.logo { |     div.logo { | ||||||
|             width: 192px; |         width: 192px; | ||||||
|             margin: 40px auto; |         margin: 40px auto; | ||||||
|         } |     } | ||||||
|         </style> | </style> | ||||||
|     </head> | </head> | ||||||
|     <body> | <body> | ||||||
|         <div class="logo"><img src="logo.png"></img></div> |     <div class="logo"><img src="logo.png"></img></div> | ||||||
|         <h1>Info</h1> |     <h1>Info</h1> | ||||||
|  |  | ||||||
|         <table width="100%"> | 	<table width="100%"> | ||||||
|             <tr> | 		<tr> | ||||||
|                 <td>Block number</td> | 			<td>Block number</td> | ||||||
|                 <td id="number"></td> | 			<td id="number"></td> | ||||||
|             </tr> | 		</tr> | ||||||
|  |  | ||||||
|             <tr> | 		<tr> | ||||||
|                 <td>Peer count</td> | 			<td>Peer count</td> | ||||||
|                 <td id="peer_count"></td> | 			<td id="peer_count"></td> | ||||||
|             </tr> | 		</tr> | ||||||
|  |  | ||||||
|             <tr> | 		<tr> | ||||||
|                 <td>Accounts</td> | 			<td>Accounts</td> | ||||||
|                 <td id="accounts"></td> | 			<td id="accounts"></td> | ||||||
|             </tr> | 		</tr> | ||||||
|  |  | ||||||
|             <tr> | 		<tr> | ||||||
|                 <td>Gas price</td> | 			<td>Gas price</td> | ||||||
|                 <td id="gas_price"></td> | 			<td id="gas_price"></td> | ||||||
|             </tr> | 		</tr> | ||||||
|  |  | ||||||
|             <tr> | 		<tr> | ||||||
|                 <td>Mining</td> | 			<td>Mining</td> | ||||||
|                 <td id="mining"></td> | 			<td id="mining"></td> | ||||||
|             </tr> | 		</tr> | ||||||
|  |  | ||||||
|             <tr> | 		<tr> | ||||||
|                 <td>Listening</td> | 			<td>Listening</td> | ||||||
|                 <td id="listening"></td> | 			<td id="listening"></td> | ||||||
|             </tr> | 		</tr> | ||||||
|  |  | ||||||
|             <tr> | 		<tr> | ||||||
|                 <td>Coinbase</td> | 			<td>Coinbase</td> | ||||||
|                 <td id="coinbase"></td> | 			<td id="coinbase"></td> | ||||||
|             </tr> | 		</tr> | ||||||
|         </table> | 	</table> | ||||||
|     </body> | </body> | ||||||
|  |  | ||||||
|     <script type="text/javascript"> | <script type="text/javascript"> | ||||||
|         var web3 = require('web3'); |     var web3 = require('web3'); | ||||||
|         var eth = web3.eth; |     var eth = web3.eth; | ||||||
|  |  | ||||||
|         web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8080')); |     web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); | ||||||
|  |  | ||||||
|  |     document.querySelector("#number").innerHTML = eth.number; | ||||||
|  |     document.querySelector("#coinbase").innerHTML = eth.coinbase | ||||||
|  |     document.querySelector("#peer_count").innerHTML = eth.peerCount; | ||||||
|  |     document.querySelector("#accounts").innerHTML = eth.accounts; | ||||||
|  |     document.querySelector("#gas_price").innerHTML = eth.gasPrice; | ||||||
|  |     document.querySelector("#mining").innerHTML = eth.mining; | ||||||
|  |     document.querySelector("#listening").innerHTML = eth.listening; | ||||||
|  |  | ||||||
|  |     eth.watch('pending').changed(function() { | ||||||
|  |         console.log("pending changed"); | ||||||
|  |     }); | ||||||
|  |     eth.watch('chain').changed(function() { | ||||||
|         document.querySelector("#number").innerHTML = eth.number; |         document.querySelector("#number").innerHTML = eth.number; | ||||||
|         document.querySelector("#coinbase").innerHTML = eth.coinbase |     }); | ||||||
|         document.querySelector("#peer_count").innerHTML = eth.peerCount; |  | ||||||
|         document.querySelector("#accounts").innerHTML = eth.accounts; | </script> | ||||||
|         document.querySelector("#gas_price").innerHTML = eth.gasPrice; |  | ||||||
|         document.querySelector("#mining").innerHTML = eth.mining; |  | ||||||
|         document.querySelector("#listening").innerHTML = eth.listening; |  | ||||||
|         </script> |  | ||||||
|  |  | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ var ( | |||||||
| 	AddPeer         string | 	AddPeer         string | ||||||
| 	MaxPeer         int | 	MaxPeer         int | ||||||
| 	GenAddr         bool | 	GenAddr         bool | ||||||
| 	UseSeed         bool | 	SeedNode        string | ||||||
| 	SecretFile      string | 	SecretFile      string | ||||||
| 	ExportDir       string | 	ExportDir       string | ||||||
| 	NonInteractive  bool | 	NonInteractive  bool | ||||||
| @@ -111,12 +111,12 @@ func Init() { | |||||||
| 	flag.StringVar(&OutboundPort, "port", "30303", "listening port") | 	flag.StringVar(&OutboundPort, "port", "30303", "listening port") | ||||||
| 	flag.BoolVar(&UseUPnP, "upnp", true, "enable UPnP support") | 	flag.BoolVar(&UseUPnP, "upnp", true, "enable UPnP support") | ||||||
| 	flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers") | 	flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers") | ||||||
| 	flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on") | 	flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on") | ||||||
| 	flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on") | 	flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on") | ||||||
| 	flag.BoolVar(&StartRpc, "rpc", true, "start rpc server") | 	flag.BoolVar(&StartRpc, "rpc", true, "start rpc server") | ||||||
| 	flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server") | 	flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server") | ||||||
| 	flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)") | 	flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)") | ||||||
| 	flag.BoolVar(&UseSeed, "seed", true, "seed peers") | 	flag.StringVar(&SeedNode, "seednode", "poc-8.ethdev.com:30303", "ip:port of seed node to connect to. Set to blank for skip") | ||||||
| 	flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") | 	flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") | ||||||
| 	flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)") | 	flag.StringVar(&NatType, "nat", "", "NAT support (UPNP|PMP) (none)") | ||||||
| 	flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") | 	flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") | ||||||
|   | |||||||
| @@ -84,7 +84,7 @@ func run() error { | |||||||
| 	utils.RegisterInterrupt(func(os.Signal) { | 	utils.RegisterInterrupt(func(os.Signal) { | ||||||
| 		gui.Stop() | 		gui.Stop() | ||||||
| 	}) | 	}) | ||||||
| 	go utils.StartEthereum(ethereum, UseSeed) | 	go utils.StartEthereum(ethereum, SeedNode) | ||||||
|  |  | ||||||
| 	fmt.Println("ETH stack took", time.Since(tstart)) | 	fmt.Println("ETH stack took", time.Since(tstart)) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -136,7 +136,7 @@ func (ui *UiLib) Muted(content string) { | |||||||
|  |  | ||||||
| func (ui *UiLib) Connect(button qml.Object) { | func (ui *UiLib) Connect(button qml.Object) { | ||||||
| 	if !ui.connected { | 	if !ui.connected { | ||||||
| 		ui.eth.Start(true) | 		ui.eth.Start(SeedNode) | ||||||
| 		ui.connected = true | 		ui.connected = true | ||||||
| 		button.Set("enabled", false) | 		button.Set("enabled", false) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -121,9 +121,9 @@ func exit(err error) { | |||||||
| 	os.Exit(status) | 	os.Exit(status) | ||||||
| } | } | ||||||
|  |  | ||||||
| func StartEthereum(ethereum *eth.Ethereum, UseSeed bool) { | func StartEthereum(ethereum *eth.Ethereum, SeedNode string) { | ||||||
| 	clilogger.Infof("Starting %s", ethereum.ClientIdentity()) | 	clilogger.Infof("Starting %s", ethereum.ClientIdentity()) | ||||||
| 	err := ethereum.Start(UseSeed) | 	err := ethereum.Start(SeedNode) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		exit(err) | 		exit(err) | ||||||
| 	} | 	} | ||||||
| @@ -205,7 +205,7 @@ func StartWebSockets(eth *eth.Ethereum, wsPort int) { | |||||||
| 	clilogger.Infoln("Starting WebSockets") | 	clilogger.Infoln("Starting WebSockets") | ||||||
|  |  | ||||||
| 	var err error | 	var err error | ||||||
| 	eth.WsServer, err = rpcws.NewWebSocketServer(eth, wsPort) | 	eth.WsServer, err = rpcws.NewWebSocketServer(xeth.New(eth), wsPort) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		clilogger.Errorf("Could not start RPC interface (port %v): %v", wsPort, err) | 		clilogger.Errorf("Could not start RPC interface (port %v): %v", wsPort, err) | ||||||
| 	} else { | 	} else { | ||||||
|   | |||||||
| @@ -20,6 +20,10 @@ import ( | |||||||
| 	"gopkg.in/fatih/set.v0" | 	"gopkg.in/fatih/set.v0" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type PendingBlockEvent struct { | ||||||
|  | 	Block *types.Block | ||||||
|  | } | ||||||
|  |  | ||||||
| var statelogger = logger.NewLogger("BLOCK") | var statelogger = logger.NewLogger("BLOCK") | ||||||
|  |  | ||||||
| type EthManager interface { | type EthManager interface { | ||||||
| @@ -126,20 +130,14 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state | |||||||
| 		cumulativeSum      = new(big.Int) | 		cumulativeSum      = new(big.Int) | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| done: | 	for _, tx := range txs { | ||||||
| 	for i, tx := range txs { |  | ||||||
| 		receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess) | 		receipt, txGas, err := self.ApplyTransaction(coinbase, state, block, tx, totalUsedGas, transientProcess) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, nil, nil, nil, err |  | ||||||
|  |  | ||||||
| 			switch { | 			switch { | ||||||
| 			case IsNonceErr(err): | 			case IsNonceErr(err): | ||||||
| 				err = nil // ignore error | 				return nil, nil, nil, nil, err | ||||||
| 				continue |  | ||||||
| 			case IsGasLimitErr(err): | 			case IsGasLimitErr(err): | ||||||
| 				unhandled = txs[i:] | 				return nil, nil, nil, nil, err | ||||||
|  |  | ||||||
| 				break done |  | ||||||
| 			default: | 			default: | ||||||
| 				statelogger.Infoln(err) | 				statelogger.Infoln(err) | ||||||
| 				erroneous = append(erroneous, tx) | 				erroneous = append(erroneous, tx) | ||||||
| @@ -155,6 +153,10 @@ done: | |||||||
| 	block.Reward = cumulativeSum | 	block.Reward = cumulativeSum | ||||||
| 	block.Header().GasUsed = totalUsedGas | 	block.Header().GasUsed = totalUsedGas | ||||||
|  |  | ||||||
|  | 	if transientProcess { | ||||||
|  | 		go self.eventMux.Post(PendingBlockEvent{block}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return receipts, handled, unhandled, erroneous, err | 	return receipts, handled, unhandled, erroneous, err | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -213,7 +215,7 @@ func (sm *BlockProcessor) ProcessWithParent(block, parent *types.Block) (td *big | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err = sm.AccumelateRewards(state, block, parent); err != nil { | 	if err = sm.AccumulateRewards(state, block, parent); err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -253,9 +255,8 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { | |||||||
| 		return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd) | 		return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	diff := block.Header().Time - parent.Header().Time | 	if block.Time() < parent.Time() { | ||||||
| 	if diff < 0 { | 		return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time) | ||||||
| 		return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Header().Time, sm.bc.CurrentBlock().Header().Time) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if block.Time() > time.Now().Unix() { | 	if block.Time() > time.Now().Unix() { | ||||||
| @@ -270,7 +271,7 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (sm *BlockProcessor) AccumelateRewards(statedb *state.StateDB, block, parent *types.Block) error { | func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, parent *types.Block) error { | ||||||
| 	reward := new(big.Int).Set(BlockReward) | 	reward := new(big.Int).Set(BlockReward) | ||||||
|  |  | ||||||
| 	ancestors := set.New() | 	ancestors := set.New() | ||||||
| @@ -328,7 +329,7 @@ func (sm *BlockProcessor) GetMessages(block *types.Block) (messages []*state.Mes | |||||||
| 	defer state.Reset() | 	defer state.Reset() | ||||||
|  |  | ||||||
| 	sm.TransitionState(state, parent, block) | 	sm.TransitionState(state, parent, block) | ||||||
| 	sm.AccumelateRewards(state, block, parent) | 	sm.AccumulateRewards(state, block, parent) | ||||||
|  |  | ||||||
| 	return state.Manifest().Messages, nil | 	return state.Manifest().Messages, nil | ||||||
| } | } | ||||||
| @@ -349,7 +350,7 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro | |||||||
| 	defer state.Reset() | 	defer state.Reset() | ||||||
|  |  | ||||||
| 	sm.TransitionState(state, parent, block) | 	sm.TransitionState(state, parent, block) | ||||||
| 	sm.AccumelateRewards(state, block, parent) | 	sm.AccumulateRewards(state, block, parent) | ||||||
|  |  | ||||||
| 	return state.Logs(), nil | 	return state.Logs(), nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -33,8 +33,9 @@ type Filter struct { | |||||||
| 	max      int | 	max      int | ||||||
| 	topics   [][]byte | 	topics   [][]byte | ||||||
|  |  | ||||||
| 	BlockCallback func(*types.Block) | 	BlockCallback   func(*types.Block) | ||||||
| 	LogsCallback  func(state.Logs) | 	PendingCallback func(*types.Block) | ||||||
|  | 	LogsCallback    func(state.Logs) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Create a new filter which uses a bloom filter on blocks to figure out whether a particular block | // Create a new filter which uses a bloom filter on blocks to figure out whether a particular block | ||||||
| @@ -144,7 +145,7 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs { | |||||||
| 	// Filter the logs for interesting stuff | 	// Filter the logs for interesting stuff | ||||||
| Logs: | Logs: | ||||||
| 	for _, log := range logs { | 	for _, log := range logs { | ||||||
| 		if len(self.address) > 0 && !bytes.Equal(self.address, log.Address()) { | 		if !bytes.Equal(self.address, log.Address()) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,10 +17,6 @@ import ( | |||||||
| 	"github.com/ethereum/go-ethereum/whisper" | 	"github.com/ethereum/go-ethereum/whisper" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	seedNodeAddress = "poc-8.ethdev.com:30303" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type Config struct { | type Config struct { | ||||||
| 	Name       string | 	Name       string | ||||||
| 	Version    string | 	Version    string | ||||||
| @@ -223,7 +219,7 @@ func (s *Ethereum) Coinbase() []byte { | |||||||
| } | } | ||||||
|  |  | ||||||
| // Start the ethereum | // Start the ethereum | ||||||
| func (s *Ethereum) Start(seed bool) error { | func (s *Ethereum) Start(seedNode string) error { | ||||||
| 	err := s.net.Start() | 	err := s.net.Start() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| @@ -246,9 +242,9 @@ func (s *Ethereum) Start(seed bool) error { | |||||||
| 	go s.blockBroadcastLoop() | 	go s.blockBroadcastLoop() | ||||||
|  |  | ||||||
| 	// TODO: read peers here | 	// TODO: read peers here | ||||||
| 	if seed { | 	if len(seedNode) > 0 { | ||||||
| 		logger.Infof("Connect to seed node %v", seedNodeAddress) | 		logger.Infof("Connect to seed node %v", seedNode) | ||||||
| 		if err := s.SuggestPeer(seedNodeAddress); err != nil { | 		if err := s.SuggestPeer(seedNode); err != nil { | ||||||
| 			logger.Infoln(err) | 			logger.Infoln(err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| // XXX This is the old filter system specifically for messages. This is till in used and could use some refactoring |  | ||||||
| package filter | package filter | ||||||
| 
 | 
 | ||||||
|  | // TODO make use of the generic filtering system | ||||||
|  | 
 | ||||||
| import ( | import ( | ||||||
| 	"sync" | 	"sync" | ||||||
| 
 | 
 | ||||||
| @@ -59,7 +60,7 @@ func (self *FilterManager) GetFilter(id int) *core.Filter { | |||||||
| 
 | 
 | ||||||
| func (self *FilterManager) filterLoop() { | func (self *FilterManager) filterLoop() { | ||||||
| 	// Subscribe to events | 	// Subscribe to events | ||||||
| 	events := self.eventMux.Subscribe(core.NewBlockEvent{}, state.Logs(nil)) | 	events := self.eventMux.Subscribe(core.PendingBlockEvent{}, core.NewBlockEvent{}, state.Logs(nil)) | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	for { | 	for { | ||||||
| @@ -77,6 +78,15 @@ out: | |||||||
| 				} | 				} | ||||||
| 				self.filterMu.RUnlock() | 				self.filterMu.RUnlock() | ||||||
| 
 | 
 | ||||||
|  | 			case core.PendingBlockEvent: | ||||||
|  | 				self.filterMu.RLock() | ||||||
|  | 				for _, filter := range self.filters { | ||||||
|  | 					if filter.PendingCallback != nil { | ||||||
|  | 						filter.PendingCallback(event.Block) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				self.filterMu.RUnlock() | ||||||
|  | 
 | ||||||
| 			case state.Logs: | 			case state.Logs: | ||||||
| 				self.filterMu.RLock() | 				self.filterMu.RLock() | ||||||
| 				for _, filter := range self.filters { | 				for _, filter := range self.filters { | ||||||
| @@ -15,7 +15,7 @@ if ls $dir/*.go &> /dev/null; then | |||||||
|     # echo $dir |     # echo $dir | ||||||
|     if [[ $dir != "./tests/vm" ]] |     if [[ $dir != "./tests/vm" ]] | ||||||
|     then |     then | ||||||
|         $GOROOT/bin/go test -covermode=count -coverprofile=$dir/profile.tmp $dir |         go test -covermode=count -coverprofile=$dir/profile.tmp $dir | ||||||
|     fi |     fi | ||||||
|     if [ -f $dir/profile.tmp ] |     if [ -f $dir/profile.tmp ] | ||||||
|     then |     then | ||||||
| @@ -25,5 +25,5 @@ if ls $dir/*.go &> /dev/null; then | |||||||
| fi | fi | ||||||
| done | done | ||||||
|  |  | ||||||
| $GOROOT/bin/go tool cover -func profile.cov | go tool cover -func profile.cov | ||||||
|  |  | ||||||
|   | |||||||
| @@ -225,7 +225,7 @@ func (self *Miner) mine() { | |||||||
| 	block.SetReceipts(receipts) | 	block.SetReceipts(receipts) | ||||||
|  |  | ||||||
| 	// Accumulate the rewards included for this block | 	// Accumulate the rewards included for this block | ||||||
| 	blockProcessor.AccumelateRewards(state, block, parent) | 	blockProcessor.AccumulateRewards(state, block, parent) | ||||||
|  |  | ||||||
| 	state.Update(ethutil.Big0) | 	state.Update(ethutil.Big0) | ||||||
| 	block.SetRoot(state.Root()) | 	block.SetRoot(state.Root()) | ||||||
|   | |||||||
| @@ -84,6 +84,7 @@ func (s *RpcHttpServer) Start() { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (s *RpcHttpServer) apiHandler(api *rpc.EthereumApi) http.Handler { | func (s *RpcHttpServer) apiHandler(api *rpc.EthereumApi) http.Handler { | ||||||
|  | 	var jsonrpcver string = "2.0" | ||||||
| 	fn := func(w http.ResponseWriter, req *http.Request) { | 	fn := func(w http.ResponseWriter, req *http.Request) { | ||||||
| 		w.Header().Set("Access-Control-Allow-Origin", "*") | 		w.Header().Set("Access-Control-Allow-Origin", "*") | ||||||
|  |  | ||||||
| @@ -91,20 +92,22 @@ func (s *RpcHttpServer) apiHandler(api *rpc.EthereumApi) http.Handler { | |||||||
|  |  | ||||||
| 		reqParsed, reqerr := JSON.ParseRequestBody(req) | 		reqParsed, reqerr := JSON.ParseRequestBody(req) | ||||||
| 		if reqerr != nil { | 		if reqerr != nil { | ||||||
| 			JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: true, ErrorText: rpc.ErrorParseRequest}) | 			jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest} | ||||||
|  | 			JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr}) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		var response interface{} | 		var response interface{} | ||||||
| 		reserr := api.GetRequestReply(&reqParsed, &response) | 		reserr := api.GetRequestReply(&reqParsed, &response) | ||||||
| 		if reserr != nil { | 		if reserr != nil { | ||||||
| 			rpchttplogger.Errorln(reserr) | 			rpchttplogger.Warnln(reserr) | ||||||
| 			JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: true, ErrorText: reserr.Error()}) | 			jsonerr := &rpc.RpcErrorObject{-32603, reserr.Error()} | ||||||
|  | 			JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: &reqParsed.ID, Error: jsonerr}) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		rpchttplogger.DebugDetailf("Generated response: %T %s", response, response) | 		rpchttplogger.DebugDetailf("Generated response: %T %s", response, response) | ||||||
| 		JSON.Send(w, &rpc.RpcSuccessResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: false, Result: response}) | 		JSON.Send(w, &rpc.RpcSuccessResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Result: response}) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return http.HandlerFunc(fn) | 	return http.HandlerFunc(fn) | ||||||
|   | |||||||
| @@ -33,25 +33,6 @@ const ( | |||||||
| 	ErrorDecodeArgs     = "Error: Could not decode arguments" | 	ErrorDecodeArgs     = "Error: Could not decode arguments" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ErrorResponse struct { |  | ||||||
| 	Error     bool   `json:"error"` |  | ||||||
| 	ErrorText string `json:"errorText"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type RpcSuccessResponse struct { |  | ||||||
| 	ID      int         `json:"id"` |  | ||||||
| 	JsonRpc string      `json:"jsonrpc"` |  | ||||||
| 	Error   bool        `json:"error"` |  | ||||||
| 	Result  interface{} `json:"result"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type RpcErrorResponse struct { |  | ||||||
| 	ID        int    `json:"id"` |  | ||||||
| 	JsonRpc   string `json:"jsonrpc"` |  | ||||||
| 	Error     bool   `json:"error"` |  | ||||||
| 	ErrorText string `json:"errortext"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type RpcRequest struct { | type RpcRequest struct { | ||||||
| 	JsonRpc string            `json:"jsonrpc"` | 	JsonRpc string            `json:"jsonrpc"` | ||||||
| 	ID      int               `json:"id"` | 	ID      int               `json:"id"` | ||||||
| @@ -59,6 +40,24 @@ type RpcRequest struct { | |||||||
| 	Params  []json.RawMessage `json:"params"` | 	Params  []json.RawMessage `json:"params"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type RpcSuccessResponse struct { | ||||||
|  | 	ID      int         `json:"id"` | ||||||
|  | 	JsonRpc string      `json:"jsonrpc"` | ||||||
|  | 	Result  interface{} `json:"result"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type RpcErrorResponse struct { | ||||||
|  | 	ID      *int            `json:"id"` | ||||||
|  | 	JsonRpc string          `json:"jsonrpc"` | ||||||
|  | 	Error   *RpcErrorObject `json:"error"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type RpcErrorObject struct { | ||||||
|  | 	Code    int    `json:"code"` | ||||||
|  | 	Message string `json:"message"` | ||||||
|  | 	// Data    interface{} `json:"data"` | ||||||
|  | } | ||||||
|  |  | ||||||
| func NewErrorResponse(msg string) error { | func NewErrorResponse(msg string) error { | ||||||
| 	return errors.New(msg) | 	return errors.New(msg) | ||||||
| } | } | ||||||
| @@ -206,7 +205,6 @@ func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) { | |||||||
| 	if len(req.Params) < 1 { | 	if len(req.Params) < 1 { | ||||||
| 		return nil, NewErrorResponse(ErrorArguments) | 		return nil, NewErrorResponse(ErrorArguments) | ||||||
| 	} | 	} | ||||||
| 	fmt.Println("FILTER PARAMS", string(req.Params[0])) |  | ||||||
|  |  | ||||||
| 	args := new(FilterOptions) | 	args := new(FilterOptions) | ||||||
| 	r := bytes.NewReader(req.Params[0]) | 	r := bytes.NewReader(req.Params[0]) | ||||||
| @@ -218,6 +216,21 @@ func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) { | |||||||
| 	return args, nil | 	return args, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (req *RpcRequest) ToFilterStringArgs() (string, error) { | ||||||
|  | 	if len(req.Params) < 1 { | ||||||
|  | 		return "", NewErrorResponse(ErrorArguments) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var args string | ||||||
|  | 	err := json.Unmarshal(req.Params[0], &args) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", NewErrorResponse(ErrorDecodeArgs) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	rpclogger.DebugDetailf("%T %v", args, args) | ||||||
|  | 	return args, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (req *RpcRequest) ToFilterChangedArgs() (int, error) { | func (req *RpcRequest) ToFilterChangedArgs() (int, error) { | ||||||
| 	if len(req.Params) < 1 { | 	if len(req.Params) < 1 { | ||||||
| 		return 0, NewErrorResponse(ErrorArguments) | 		return 0, NewErrorResponse(ErrorArguments) | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ import ( | |||||||
| 	"sync" | 	"sync" | ||||||
|  |  | ||||||
| 	"github.com/ethereum/go-ethereum/core" | 	"github.com/ethereum/go-ethereum/core" | ||||||
|  | 	"github.com/ethereum/go-ethereum/core/types" | ||||||
| 	"github.com/ethereum/go-ethereum/crypto" | 	"github.com/ethereum/go-ethereum/crypto" | ||||||
| 	"github.com/ethereum/go-ethereum/ethdb" | 	"github.com/ethereum/go-ethereum/ethdb" | ||||||
| 	"github.com/ethereum/go-ethereum/ethutil" | 	"github.com/ethereum/go-ethereum/ethutil" | ||||||
| @@ -88,6 +89,25 @@ func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) erro | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error { | ||||||
|  | 	var id int | ||||||
|  | 	filter := core.NewFilter(self.xeth.Backend()) | ||||||
|  |  | ||||||
|  | 	callback := func(block *types.Block) { | ||||||
|  | 		self.logs[id] = append(self.logs[id], &state.StateLog{}) | ||||||
|  | 	} | ||||||
|  | 	if args == "pending" { | ||||||
|  | 		filter.PendingCallback = callback | ||||||
|  | 	} else if args == "chain" { | ||||||
|  | 		filter.BlockCallback = callback | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	id = self.filterManager.InstallFilter(filter) | ||||||
|  | 	*reply = id | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (self *EthereumApi) FilterChanged(id int, reply *interface{}) error { | func (self *EthereumApi) FilterChanged(id int, reply *interface{}) error { | ||||||
| 	self.logMut.RLock() | 	self.logMut.RLock() | ||||||
| 	defer self.logMut.RUnlock() | 	defer self.logMut.RUnlock() | ||||||
| @@ -389,6 +409,12 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error | |||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		return p.NewFilter(args, reply) | 		return p.NewFilter(args, reply) | ||||||
|  | 	case "eth_newFilterString": | ||||||
|  | 		args, err := req.ToFilterStringArgs() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		return p.NewFilterString(args, reply) | ||||||
| 	case "eth_changed": | 	case "eth_changed": | ||||||
| 		args, err := req.ToFilterChangedArgs() | 		args, err := req.ToFilterChangedArgs() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|   | |||||||
| @@ -22,35 +22,30 @@ import ( | |||||||
| 	"net/http" | 	"net/http" | ||||||
|  |  | ||||||
| 	"code.google.com/p/go.net/websocket" | 	"code.google.com/p/go.net/websocket" | ||||||
| 	"github.com/ethereum/go-ethereum/eth" |  | ||||||
| 	"github.com/ethereum/go-ethereum/event/filter" |  | ||||||
| 	"github.com/ethereum/go-ethereum/logger" | 	"github.com/ethereum/go-ethereum/logger" | ||||||
| 	"github.com/ethereum/go-ethereum/rpc" | 	"github.com/ethereum/go-ethereum/rpc" | ||||||
| 	"github.com/ethereum/go-ethereum/xeth" | 	"github.com/ethereum/go-ethereum/xeth" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var wslogger = logger.NewLogger("RPC-WS") | var wslogger = logger.NewLogger("RPC-WS") | ||||||
|  | var JSON rpc.JsonWrapper | ||||||
|  |  | ||||||
| type WebSocketServer struct { | type WebSocketServer struct { | ||||||
| 	eth           *eth.Ethereum | 	pipe     *xeth.XEth | ||||||
| 	filterManager *filter.FilterManager | 	port     int | ||||||
| 	port          int | 	doneCh   chan bool | ||||||
| 	doneCh        chan bool | 	listener net.Listener | ||||||
| 	listener      net.Listener |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewWebSocketServer(eth *eth.Ethereum, port int) (*WebSocketServer, error) { | func NewWebSocketServer(pipe *xeth.XEth, port int) (*WebSocketServer, error) { | ||||||
| 	sport := fmt.Sprintf(":%d", port) | 	sport := fmt.Sprintf(":%d", port) | ||||||
| 	l, err := net.Listen("tcp", sport) | 	l, err := net.Listen("tcp", sport) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	filterManager := filter.NewFilterManager(eth.EventMux()) | 	return &WebSocketServer{ | ||||||
| 	go filterManager.Start() | 		pipe, | ||||||
|  |  | ||||||
| 	return &WebSocketServer{eth, |  | ||||||
| 		filterManager, |  | ||||||
| 		port, | 		port, | ||||||
| 		make(chan bool), | 		make(chan bool), | ||||||
| 		l, | 		l, | ||||||
| @@ -75,7 +70,7 @@ func (self *WebSocketServer) Start() { | |||||||
| 	wslogger.Infof("Starting RPC-WS server on port %d", self.port) | 	wslogger.Infof("Starting RPC-WS server on port %d", self.port) | ||||||
| 	go self.handlerLoop() | 	go self.handlerLoop() | ||||||
|  |  | ||||||
| 	api := rpc.NewEthereumApi(xeth.New(self.eth)) | 	api := rpc.NewEthereumApi(self.pipe) | ||||||
| 	h := self.apiHandler(api) | 	h := self.apiHandler(api) | ||||||
| 	http.Handle("/ws", h) | 	http.Handle("/ws", h) | ||||||
|  |  | ||||||
| @@ -96,27 +91,29 @@ func (s *WebSocketServer) apiHandler(api *rpc.EthereumApi) http.Handler { | |||||||
| } | } | ||||||
|  |  | ||||||
| func sockHandler(api *rpc.EthereumApi) websocket.Handler { | func sockHandler(api *rpc.EthereumApi) websocket.Handler { | ||||||
|  | 	var jsonrpcver string = "2.0" | ||||||
| 	fn := func(conn *websocket.Conn) { | 	fn := func(conn *websocket.Conn) { | ||||||
| 		for { | 		for { | ||||||
| 			wslogger.Debugln("Handling request") | 			wslogger.Debugln("Handling request") | ||||||
| 			var reqParsed rpc.RpcRequest | 			var reqParsed rpc.RpcRequest | ||||||
|  |  | ||||||
| 			if err := websocket.JSON.Receive(conn, &reqParsed); err != nil { | 			if err := websocket.JSON.Receive(conn, &reqParsed); err != nil { | ||||||
| 				wslogger.Debugln(rpc.ErrorParseRequest) | 				jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest} | ||||||
| 				websocket.JSON.Send(conn, rpc.RpcErrorResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: true, ErrorText: rpc.ErrorParseRequest}) | 				JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr}) | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			var response interface{} | 			var response interface{} | ||||||
| 			reserr := api.GetRequestReply(&reqParsed, &response) | 			reserr := api.GetRequestReply(&reqParsed, &response) | ||||||
| 			if reserr != nil { | 			if reserr != nil { | ||||||
| 				wslogger.Errorln(reserr) | 				wslogger.Warnln(reserr) | ||||||
| 				websocket.JSON.Send(conn, rpc.RpcErrorResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: true, ErrorText: reserr.Error()}) | 				jsonerr := &rpc.RpcErrorObject{-32603, reserr.Error()} | ||||||
|  | 				JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: &reqParsed.ID, Error: jsonerr}) | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			wslogger.Debugf("Generated response: %T %s", response, response) | 			wslogger.Debugf("Generated response: %T %s", response, response) | ||||||
| 			websocket.JSON.Send(conn, rpc.RpcSuccessResponse{JsonRpc: reqParsed.JsonRpc, ID: reqParsed.ID, Error: false, Result: response}) | 			JSON.Send(conn, &rpc.RpcSuccessResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Result: response}) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return websocket.Handler(fn) | 	return websocket.Handler(fn) | ||||||
|   | |||||||
| @@ -23,7 +23,6 @@ func (self *Iterator) Next() bool { | |||||||
| 	self.Key = []byte(DecodeCompact(k)) | 	self.Key = []byte(DecodeCompact(k)) | ||||||
|  |  | ||||||
| 	return len(k) > 0 | 	return len(k) > 0 | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (self *Iterator) next(node Node, key []byte) []byte { | func (self *Iterator) next(node Node, key []byte) []byte { | ||||||
| @@ -67,7 +66,7 @@ func (self *Iterator) next(node Node, key []byte) []byte { | |||||||
| 			if BeginsWith(key, k) { | 			if BeginsWith(key, k) { | ||||||
| 				ret = self.next(cnode, skey) | 				ret = self.next(cnode, skey) | ||||||
| 			} else if bytes.Compare(k, key[:len(k)]) > 0 { | 			} else if bytes.Compare(k, key[:len(k)]) > 0 { | ||||||
| 				ret = self.key(node) | 				return self.key(node) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if ret != nil { | 			if ret != nil { | ||||||
|   | |||||||
| @@ -257,3 +257,42 @@ func BenchmarkUpdate(b *testing.B) { | |||||||
| 	} | 	} | ||||||
| 	trie.Hash() | 	trie.Hash() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type kv struct { | ||||||
|  | 	k, v []byte | ||||||
|  | 	t    bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestLargeData(t *testing.T) { | ||||||
|  | 	trie := NewEmpty() | ||||||
|  | 	vals := make(map[string]*kv) | ||||||
|  |  | ||||||
|  | 	for i := byte(1); i < 255; i++ { | ||||||
|  | 		value := &kv{ethutil.LeftPadBytes([]byte{i}, 32), []byte{i}, false} | ||||||
|  | 		value2 := &kv{ethutil.LeftPadBytes([]byte{10, i}, 32), []byte{i}, false} | ||||||
|  | 		trie.Update(value.k, value.v) | ||||||
|  | 		trie.Update(value2.k, value2.v) | ||||||
|  | 		vals[string(value.k)] = value | ||||||
|  | 		vals[string(value2.k)] = value2 | ||||||
|  | 		fmt.Println(value, "\n", value2) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	it := trie.Iterator() | ||||||
|  | 	for it.Next() { | ||||||
|  | 		vals[string(it.Key)].t = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var untouched []*kv | ||||||
|  | 	for _, value := range vals { | ||||||
|  | 		if !value.t { | ||||||
|  | 			untouched = append(untouched, value) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(untouched) > 0 { | ||||||
|  | 		t.Errorf("Missed %d nodes", len(untouched)) | ||||||
|  | 		for _, value := range untouched { | ||||||
|  | 			t.Error(value) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -106,7 +106,7 @@ func (self *Whisper) Messages(id int) (messages *ethutil.List) { | |||||||
|  |  | ||||||
| func filterFromMap(opts map[string]interface{}) (f whisper.Filter) { | func filterFromMap(opts map[string]interface{}) (f whisper.Filter) { | ||||||
| 	if to, ok := opts["to"].(string); ok { | 	if to, ok := opts["to"].(string); ok { | ||||||
| 		f.To = crypto.ToECDSA(fromHex(to)) | 		f.To = crypto.ToECDSAPub(fromHex(to)) | ||||||
| 	} | 	} | ||||||
| 	if from, ok := opts["from"].(string); ok { | 	if from, ok := opts["from"].(string); ok { | ||||||
| 		f.From = crypto.ToECDSAPub(fromHex(from)) | 		f.From = crypto.ToECDSAPub(fromHex(from)) | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ package whisper | |||||||
| import "crypto/ecdsa" | import "crypto/ecdsa" | ||||||
|  |  | ||||||
| type Filter struct { | type Filter struct { | ||||||
| 	To     *ecdsa.PrivateKey | 	To     *ecdsa.PublicKey | ||||||
| 	From   *ecdsa.PublicKey | 	From   *ecdsa.PublicKey | ||||||
| 	Topics [][]byte | 	Topics [][]byte | ||||||
| 	Fn     func(*Message) | 	Fn     func(*Message) | ||||||
|   | |||||||
| @@ -118,7 +118,7 @@ func (self *Whisper) GetIdentity(key *ecdsa.PublicKey) *ecdsa.PrivateKey { | |||||||
|  |  | ||||||
| func (self *Whisper) Watch(opts Filter) int { | func (self *Whisper) Watch(opts Filter) int { | ||||||
| 	return self.filters.Install(filter.Generic{ | 	return self.filters.Install(filter.Generic{ | ||||||
| 		Str1: string(crypto.FromECDSA(opts.To)), | 		Str1: string(crypto.FromECDSAPub(opts.To)), | ||||||
| 		Str2: string(crypto.FromECDSAPub(opts.From)), | 		Str2: string(crypto.FromECDSAPub(opts.From)), | ||||||
| 		Data: bytesToMap(opts.Topics), | 		Data: bytesToMap(opts.Topics), | ||||||
| 		Fn: func(data interface{}) { | 		Fn: func(data interface{}) { | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ func TestEvent(t *testing.T) { | |||||||
| 	whisper := New() | 	whisper := New() | ||||||
| 	id := whisper.NewIdentity() | 	id := whisper.NewIdentity() | ||||||
| 	whisper.Watch(Filter{ | 	whisper.Watch(Filter{ | ||||||
| 		To: id, | 		To: &id.PublicKey, | ||||||
| 		Fn: func(msg *Message) { | 		Fn: func(msg *Message) { | ||||||
| 			res <- msg | 			res <- msg | ||||||
| 		}, | 		}, | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ func (self *Whisper) HasIdentity(key string) bool { | |||||||
|  |  | ||||||
| func (self *Whisper) Watch(opts *Options) int { | func (self *Whisper) Watch(opts *Options) int { | ||||||
| 	filter := whisper.Filter{ | 	filter := whisper.Filter{ | ||||||
| 		To:     crypto.ToECDSA(fromHex(opts.To)), | 		To:     crypto.ToECDSAPub(fromHex(opts.To)), | ||||||
| 		From:   crypto.ToECDSAPub(fromHex(opts.From)), | 		From:   crypto.ToECDSAPub(fromHex(opts.From)), | ||||||
| 		Topics: whisper.TopicsFromString(opts.Topics...), | 		Topics: whisper.TopicsFromString(opts.Topics...), | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user