Permalink
Browse files

Latest updates.

  • Loading branch information...
1 parent 276ec46 commit 1b0369b1fbfee0e35db47cdd32811eecbd6e2474 @travist committed Feb 13, 2014
Showing with 248 additions and 51 deletions.
  1. +3 −0 .gitignore
  2. +2 −1 lib/dartminer.dart
  3. +10 −17 lib/src/bitcoin.dart
  4. +191 −25 lib/src/util.dart
  5. +5 −5 lib/src/work.dart
  6. +4 −3 pubspec.yaml
  7. +26 −0 test/dartminer.dart
  8. +7 −0 test/getwork.json
View
@@ -0,0 +1,3 @@
+pubspec.lock
+.idea
+packages
View
@@ -2,8 +2,9 @@ library dartminer;
import 'dart:async';
import 'dart:io';
-import 'package:json/json.dart' as JSON;
+import 'dart:convert';
import 'package:utf/utf.dart' as UTF;
+import 'package:crypto/crypto.dart' as Crypto;
part 'src/util.dart';
part 'src/sha256.dart';
View
@@ -26,29 +26,22 @@ class Bitcoin {
);
}
- /**
- * Get the information.
- */
- Future<Map<String, String>> getinfo() {
- return call("getinfo");
- }
-
- /**
- * Get the work for mining.
- */
- Future<Map<String, String>> getwork() {
- return call("getwork");
- }
+ // The bitcoind api's.
+ Future<dynamic> getinfo({params: const[]}) => call('getinfo', params: params);
+ Future<dynamic> getwork({params: const[]}) => call('getwork', params: params);
+ Future<dynamic> getblockhash({params: const[]}) => call('getblockhash', params: params);
+ Future<dynamic> getblock({params: const []}) => call('getblock', params: params);
+ Future<dynamic> getblocktemplate({params: const []}) => call("getblocktemplate", params: params);
/**
* Make a json-rpc call to our bitcoin daemon.
*/
- Future<Map<String, String>> call(String method, {params: const []}) {
+ Future<dynamic> call(String method, {params: const []}) {
// Create a new completer.
final Completer completer = new Completer();
// Set the message.
- String message = JSON.stringify({
+ String message = JSON.encode({
'jsonrpc': '1.0',
"id": id,
"method": method,
@@ -68,8 +61,8 @@ class Bitcoin {
// Listen to the response.
res.listen((data) {
- // Get the result.
- Map<String, String> result = JSON.parse(UTF.codepointsToString(data));
+ // Parse the response.
+ dynamic result = JSON.decode(UTF.codepointsToString(data));
// If the result is set, then complete the future.
if (result["result"] != null) {
View
@@ -1,6 +1,119 @@
part of dartminer;
/**
+ * Reverses the bytes in a half word.
+ *
+ * @param int halfword
+ * The 16 bit integer word to reverse the bytes.
+ *
+ * @return int
+ * The integer with all of the bytes reversed.
+ */
+int reverseBytesInHalfWord(int halfword) {
+ return (
+ ((halfword >> 8) & 0xFF) |
+ ((halfword & 0xFF) << 8)
+ );
+}
+
+/**
+ * Reverses the bytes in an integer word.
+ *
+ * @param int word
+ * The 32 bit integer word to reverse the bytes.
+ *
+ * @return int
+ * The integer with all of the bytes reversed.
+ */
+int reverseBytesInWord(int word) {
+ return (
+ ((word << 24) & 0xFF000000) |
+ ((word << 8) & 0x00FF0000) |
+ ((word >> 8) & 0x0000FF00) |
+ ((word >> 24) & 0x000000FF)
+ );
+}
+
+/**
+ * Reverses the bytes in an 64 bit integer.
+ *
+ * @param int word
+ * The 64 bit integer word to reverse the bytes.
+ *
+ * @return int
+ * The integer with all of the bytes reversed.
+ */
+int reverseBytesInBigWord(int bigword) {
+ return (
+ ((bigword & 0xFF00000000000000) >> 56) |
+ ((bigword & 0x00FF000000000000) >> 40) |
+ ((bigword & 0x0000FF0000000000) >> 24) |
+ ((bigword & 0x000000FF00000000) >> 8) |
+ ((bigword & 0x00000000FF000000) << 8) |
+ ((bigword & 0x0000000000FF0000) << 24) |
+ ((bigword & 0x000000000000FF00) << 40) |
+ ((bigword & 0x00000000000000FF) << 56)
+ );
+}
+
+/**
+ * Add padding to a number string.
+ *
+ * @param num
+ * The number to add the padding to.
+ *
+ * @param len
+ * The length that the string should be.
+ */
+String padNumString(String num, int len) {
+
+ // If the length is the same return the string.
+ if (num.length == len) {
+ return num;
+ }
+
+ // Append a '0' to the beginning of the string.
+ StringBuffer buf = new StringBuffer();
+ for (int i = len; i > num.length; i--) {
+ buf.write('0');
+ }
+ buf.write(num);
+ return buf.toString();
+}
+
+// Convert functions.
+String toHex(int num) => num.toRadixString(16).toLowerCase();
+String int2PaddedHex(int num, int len) => padNumString(toHex(num), len);
+String byte2LEHex(int byte) => padNumString(toHex((byte & 0xFF)), 2);
+String halfWord2LEHex(int halfword) => padNumString(toHex(reverseBytesInHalfWord(halfword)), 4);
+String word2LEHex(int word) => padNumString(toHex(reverseBytesInWord(word)), 8);
+String bigword2LEHex(int bigword) => padNumString(toHex(reverseBytesInBigWord(bigword)), 16);
+
+/**
+ * Convert an unsigned integer to little endian varint ASCII Hex
+ *
+ * @param int value
+ * The integer to create the LE variant hex.
+ *
+ * @return String
+ * The LE variant hex.
+ */
+String int2VarIntHex(int x) {
+ if (x < 0xfd) {
+ return byte2LEHex(x);
+ }
+ else if (x <= 0xffff) {
+ return 'fd' + halfWord2LEHex(x);
+ }
+ else if (x <= 0xffffffff) {
+ return 'fe' + word2LEHex(x);
+ }
+ else {
+ return 'ff' + bigword2LEHex(x);
+ }
+}
+
+/**
* Convert a hexidecimal string to an array of 32bit unsigned integers.
*
* @param String hex
@@ -9,7 +122,7 @@ part of dartminer;
* @return List<int>
* The array of 32bit unsigned integers.
*/
-List<int> hexStringToList(String hex) {
+List<int> hex2ReversedList(String hex) {
int listSize = (hex.length / 8).ceil();
List<int> arr = new List(listSize);
int index = 0;
@@ -23,21 +136,27 @@ List<int> hexStringToList(String hex) {
}
/**
- * Reverses the bytes in an integer word.
+ * Convert a hexidecimal string to a list of codeUnits.
*
- * @param int word
- * The integer word to reverse the bytes.
+ * @param String hex
+ * The hexidecimal string.
*
- * @return int
- * The integer with all of the bytes reversed.
+ * @return List<int>
+ * The list of code units for the hex string.
*/
-int reverseBytesInWord(int word) {
- return (
- ((word << 24) & 0xFF000000) |
- ((word << 8) & 0x00FF0000) |
- ((word >> 8) & 0x0000FF00) |
- ((word >> 24) & 0x000000FF)
- );
+List<int> hex2CodeUnits(String hex) {
+ if ((hex.length % 2) != 0) {
+ hex = '0' + hex;
+ }
+ int listSize = (hex.length / 2).ceil();
+ List<int> arr = new List(listSize);
+ int index = 0;
+ int word = 0;
+ for (var i = 0; i < hex.length; i += 2) {
+ arr[index] = int.parse(hex.substring(i, (i + 2)), radix: 16);
+ index++;
+ }
+ return arr;
}
/**
@@ -47,12 +166,7 @@ String listToReversedHex(List<int> list) {
var buf = new StringBuffer();
String value = '';
for (var part in list) {
- part = reverseBytesInWord(part);
- value = part.toRadixString(16).toLowerCase();
- for (var i = 8; i > value.length; i--) {
- buf.write("0");
- }
- buf.write(value);
+ buf.write(word2LEHex(part));
}
return buf.toString();
}
@@ -63,12 +177,64 @@ String listToReversedHex(List<int> list) {
String listToHex(List<int> list) {
var buf = new StringBuffer();
String value = '';
- for (var part in list) {
- value = part.toRadixString(16).toLowerCase();
- for (var i = 8; i > value.length; i--) {
- buf.write("0");
- }
- buf.write(value);
+ for (int part in list) {
+ buf.write(int2PaddedHex(part, 8));
}
return buf.toString();
+}
+
+/**
+ * Reverse a string.
+ */
+String reverseString(String str) {
+ return new String.fromCharCodes(str.codeUnits.reversed.toList());
+}
+
+/**
+ * Return a json object from a file.
+ *
+ * @param String fileName
+ * The name of the file you wish to get the JSON from.
+ *
+ * @return Object
+ * A JSON object from the file.
+ */
+Future<dynamic> getJSON(String fileName) {
+ Completer completer = new Completer();
+ var file = new File(fileName);
+ Future<String> finishedReading = file.readAsString(encoding: ASCII);
+ finishedReading.then((String content) {
+ completer.complete(JSON.decode(content));
+ });
+ return completer.future;
+}
+
+/**
+ * Compute the doubleSHA of a list of string codeUnits.
+ *
+ * @param List<int> codeUnits
+ * The code units from a string.
+ *
+ * @return List<int>
+ * The code units from the encrypted string.
+ */
+List<int> doubleSHA256(List<int> codeUnits) {
+ Crypto.SHA256 h1 = new Crypto.SHA256();
+ Crypto.SHA256 h2 = new Crypto.SHA256();
+ h1.add(codeUnits);
+ h2.add(h1.close());
+ return h2.close();
+}
+
+/**
+ * Compute the double hash of a Hex string.
+ *
+ * @param String data
+ * The string to hash.
+ *
+ * @return String
+ * The double hashed hex string.
+ */
+String doubleHash(String data) {
+ return Crypto.CryptoUtils.bytesToHex(doubleSHA256(hex2CodeUnits(data)).reversed.toList());
}
View
@@ -28,11 +28,11 @@ class Work {
sha256 = new SHA256();
nonce = 0;
golden = false;
- midstate = hexStringToList(work["midstate"]);
- half = hexStringToList(work["data"].substring(0, 128));
- data = hexStringToList(work["data"].substring(128, 256));
- hash1 = hexStringToList(work["hash1"]);
- target = hexStringToList(work["target"]);
+ midstate = hex2ReversedList(work["midstate"]);
+ half = hex2ReversedList(work["data"].substring(0, 128));
+ data = hex2ReversedList(work["data"].substring(128, 256));
+ hash1 = hex2ReversedList(work["hash1"]);
+ target = hex2ReversedList(work["target"]);
print(this);
}
View
@@ -1,8 +1,9 @@
name: dartminer
author: Travis Tidwell <travist349@gmail.com>
-version: 0.0.3
+version: 0.0.4
homepage: https://github.com/travist/dartminer
description: A Bitcoin miner with Dart language.
dependencies:
- json: ">=0.9.1 <0.9.2"
- utf: ">=0.9.0 <0.9.1"
+ crypto: any
+ unittest: any
+ utf: '>=0.9.0 <0.9.1'
View
@@ -0,0 +1,26 @@
+import 'package:unittest/unittest.dart';
+import 'package:dartminer/dartminer.dart';
+
+void main() {
+
+ // Test a mining operation.
+ test('Test Mining', () {
+
+ // Get the work.
+ getJSON('getwork.json').then((dynamic work) {
+
+ // Create the miner.
+ Miner miner = new Miner(work);
+
+ // Set the nonce to a value close to the solution.
+ miner.work.nonce = hex2ReversedList('200e2e35')[0];
+
+ // Mine for gold!
+ String result = listToHex(miner.mine());
+
+ // Print the result.
+ print(result);
+ expect(result, '01000000378da709d01338204d85458bcd0f4751dfd688b56e94beab7e20ad920000000002aea838751547f70c0d12aa880ca185ad98136af5ad1f8220374c128577b60c8703064ef8ff071d352e9531800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280');
+ });
+ });
+}
View
@@ -0,0 +1,7 @@
+{
+ "midstate":"eae773ad01907880889ac5629af0c35438376e8c4ae77906301c65fa89c2779c",
+ "data":"0000000109a78d37203813d08b45854d51470fcdb588d6dfabbe946e92ad207e0000000038a8ae02f7471575aa120d0c85a10c886a1398ad821fadf5124c37200cb677854e0603871d07fff800000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000",
+ "hash1":"00000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000010000",
+ "target":"0000000000000000000000000000000000000000000000000000f8ff07000000",
+ "sol" : "31952e35"
+}

0 comments on commit 1b0369b

Please sign in to comment.