Commit 3d5f48a1 authored by obscuren's avatar obscuren

updated deps

parent a6e659f7
......@@ -17,13 +17,13 @@
},
{
"ImportPath": "github.com/codegangsta/cli",
"Comment": "1.2.0-81-g3e09053",
"Rev": "3e0905345cd2c5366530dbcdce62457f2ce16e7c"
"Comment": "1.2.0-95-g9b2bd2b",
"Rev": "9b2bd2b3489748d4d0a204fa4eb2ee9e89e0ebc6"
},
{
"ImportPath": "github.com/ethereum/ethash",
"Comment": "v23-16-g7ec1d23",
"Rev": "7ec1d23bece027001acc81e791911c65db9d8ae9"
"Comment": "v23.1-30-gf8a0565",
"Rev": "f8a0565cc3a20c5ad82dec3ec612645356069641"
},
{
"ImportPath": "github.com/ethereum/serpent-go",
......
......@@ -210,7 +210,7 @@ Subcommands can be defined for a more git-like command line app.
app.Commands = []cli.Command{
{
Name: "add",
ShortName: "a",
Aliases: []string{"a"},
Usage: "add a task to the list",
Action: func(c *cli.Context) {
println("added task: ", c.Args().First())
......@@ -218,7 +218,7 @@ app.Commands = []cli.Command{
},
{
Name: "complete",
ShortName: "c",
Aliases: []string{"c"},
Usage: "complete a task on the list",
Action: func(c *cli.Context) {
println("completed task: ", c.Args().First())
......@@ -226,7 +226,7 @@ app.Commands = []cli.Command{
},
{
Name: "template",
ShortName: "r",
Aliases: []string{"r"},
Usage: "options for task templates",
Subcommands: []cli.Command{
{
......@@ -263,7 +263,7 @@ app.EnableBashCompletion = true
app.Commands = []cli.Command{
{
Name: "complete",
ShortName: "c",
Aliases: []string{"c"},
Usage: "complete a task on the list",
Action: func(c *cli.Context) {
println("completed task: ", c.Args().First())
......
......@@ -5,6 +5,7 @@ import (
"io"
"io/ioutil"
"os"
"strings"
"text/tabwriter"
"text/template"
"time"
......@@ -72,17 +73,14 @@ func NewApp() *App {
BashComplete: DefaultAppComplete,
Action: helpCommand.Action,
Compiled: compileTime(),
Author: "Dr. James",
Email: "who@gmail.com",
Authors: []Author{{"Jim", "jim@corporate.com"}, {"Hank", "hank@indiepalace.com"}},
Writer: os.Stdout,
}
}
// Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination
func (a *App) Run(arguments []string) (err error) {
if a.Author != "" && a.Author != "" {
a.Authors = append(a.Authors, Author{a.Author, a.Email})
if a.Author != "" || a.Email != "" {
a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
}
if HelpPrinter == nil {
......@@ -91,8 +89,12 @@ func (a *App) Run(arguments []string) (err error) {
}()
HelpPrinter = func(templ string, data interface{}) {
funcMap := template.FuncMap{
"join": strings.Join,
}
w := tabwriter.NewWriter(a.Writer, 0, 8, 1, '\t', 0)
t := template.Must(template.New("help").Parse(templ))
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
err := t.Execute(w, data)
if err != nil {
panic(err)
......
......@@ -23,7 +23,7 @@ func ExampleApp() {
}
app.Author = "Harrison"
app.Email = "harrison@lolwut.com"
app.Authors = []cli.Author{{"Oliver Allen", "oliver@toyshop.com"}}
app.Authors = []cli.Author{cli.Author{Name: "Oliver Allen", Email: "oliver@toyshop.com"}}
app.Run(os.Args)
// Output:
// Hello Jeremy
......@@ -37,13 +37,13 @@ func ExampleAppSubcommand() {
app.Commands = []cli.Command{
{
Name: "hello",
ShortName: "hi",
Aliases: []string{"hi"},
Usage: "use it to see a description",
Description: "This is how we describe hello the function",
Subcommands: []cli.Command{
{
Name: "english",
ShortName: "en",
Aliases: []string{"en"},
Usage: "sends a greeting in english",
Description: "greets someone in english",
Flags: []cli.Flag{
......@@ -78,7 +78,7 @@ func ExampleAppHelp() {
app.Commands = []cli.Command{
{
Name: "describeit",
ShortName: "d",
Aliases: []string{"d"},
Usage: "use it to see a description",
Description: "This is how we describe describeit the function",
Action: func(c *cli.Context) {
......@@ -108,7 +108,7 @@ func ExampleAppBashComplete() {
app.Commands = []cli.Command{
{
Name: "describeit",
ShortName: "d",
Aliases: []string{"d"},
Usage: "use it to see a description",
Description: "This is how we describe describeit the function",
Action: func(c *cli.Context) {
......@@ -162,8 +162,8 @@ var commandAppTests = []struct {
func TestApp_Command(t *testing.T) {
app := cli.NewApp()
fooCommand := cli.Command{Name: "foobar", ShortName: "f"}
batCommand := cli.Command{Name: "batbaz", ShortName: "b"}
fooCommand := cli.Command{Name: "foobar", Aliases: []string{"f"}}
batCommand := cli.Command{Name: "batbaz", Aliases: []string{"b"}}
app.Commands = []cli.Command{
fooCommand,
batCommand,
......
......@@ -13,7 +13,7 @@ func Example() {
app.Commands = []cli.Command{
{
Name: "add",
ShortName: "a",
Aliases: []string{"a"},
Usage: "add a task to the list",
Action: func(c *cli.Context) {
println("added task: ", c.Args().First())
......@@ -21,7 +21,7 @@ func Example() {
},
{
Name: "complete",
ShortName: "c",
Aliases: []string{"c"},
Usage: "complete a task on the list",
Action: func(c *cli.Context) {
println("completed task: ", c.Args().First())
......@@ -38,13 +38,13 @@ func ExampleSubcommand() {
app.Commands = []cli.Command{
{
Name: "hello",
ShortName: "hi",
Aliases: []string{"hi"},
Usage: "use it to see a description",
Description: "This is how we describe hello the function",
Subcommands: []cli.Command{
{
Name: "english",
ShortName: "en",
Aliases: []string{"en"},
Usage: "sends a greeting in english",
Description: "greets someone in english",
Flags: []cli.Flag{
......@@ -59,7 +59,7 @@ func ExampleSubcommand() {
},
}, {
Name: "spanish",
ShortName: "sp",
Aliases: []string{"sp"},
Usage: "sends a greeting in spanish",
Flags: []cli.Flag{
cli.StringFlag{
......@@ -73,7 +73,7 @@ func ExampleSubcommand() {
},
}, {
Name: "french",
ShortName: "fr",
Aliases: []string{"fr"},
Usage: "sends a greeting in french",
Flags: []cli.Flag{
cli.StringFlag{
......
......@@ -10,8 +10,10 @@ import (
type Command struct {
// The name of the command
Name string
// short name of the command. Typically one character
// short name of the command. Typically one character (deprecated, use `Aliases`)
ShortName string
// A list of aliases for the command
Aliases []string
// A short description of the usage of this command
Usage string
// A longer explanation of how the command works
......@@ -117,9 +119,24 @@ func (c Command) Run(ctx *Context) error {
return nil
}
func (c Command) Names() []string {
names := []string{c.Name}
if c.ShortName != "" {
names = append(names, c.ShortName)
}
return append(names, c.Aliases...)
}
// Returns true if Command.Name or Command.ShortName matches given name
func (c Command) HasName(name string) bool {
return c.Name == name || (c.ShortName != "" && c.ShortName == name)
for _, n := range c.Names() {
if n == name {
return true
}
}
return false
}
func (c Command) startApp(ctx *Context) error {
......
......@@ -17,7 +17,7 @@ func TestCommandDoNotIgnoreFlags(t *testing.T) {
command := cli.Command{
Name: "test-cmd",
ShortName: "tc",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(_ *cli.Context) {},
......@@ -37,7 +37,7 @@ func TestCommandIgnoreFlags(t *testing.T) {
command := cli.Command{
Name: "test-cmd",
ShortName: "tc",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(_ *cli.Context) {},
......
......@@ -106,6 +106,11 @@ func (c *Context) GlobalGeneric(name string) interface{} {
return lookupGeneric(name, c.globalSet)
}
// Returns the number of flags set
func (c *Context) NumFlags() int {
return c.flagSet.NFlag()
}
// Determines if the flag was actually set
func (c *Context) IsSet(name string) bool {
if c.setFlags == nil {
......
......@@ -97,3 +97,15 @@ func TestContext_GlobalIsSet(t *testing.T) {
expect(t, c.GlobalIsSet("myflagGlobalUnset"), false)
expect(t, c.GlobalIsSet("bogusGlobal"), false)
}
func TestContext_NumFlags(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc")
set.String("otherflag", "hello world", "doc")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Bool("myflagGlobal", true, "doc")
c := cli.NewContext(nil, set, globalSet)
set.Parse([]string{"--myflag", "--otherflag=foo"})
globalSet.Parse([]string{"--myflagGlobal"})
expect(t, c.NumFlags(), 2)
}
......@@ -15,10 +15,10 @@ VERSION:
{{.Version}}
AUTHOR(S):
{{range .Authors}}{{ . }} {{end}}
{{range .Authors}}{{ . }}
{{end}}
COMMANDS:
{{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
{{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
{{end}}{{if .Flags}}
GLOBAL OPTIONS:
{{range .Flags}}{{.}}
......@@ -52,7 +52,7 @@ USAGE:
{{.Name}} command{{if .Flags}} [command options]{{end}} [arguments...]
COMMANDS:
{{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
{{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
{{end}}{{if .Flags}}
OPTIONS:
{{range .Flags}}{{.}}
......@@ -61,7 +61,7 @@ OPTIONS:
var helpCommand = Command{
Name: "help",
ShortName: "h",
Aliases: []string{"h"},
Usage: "Shows a list of commands or help for one command",
Action: func(c *Context) {
args := c.Args()
......@@ -75,7 +75,7 @@ var helpCommand = Command{
var helpSubcommand = Command{
Name: "help",
ShortName: "h",
Aliases: []string{"h"},
Usage: "Shows a list of commands or help for one command",
Action: func(c *Context) {
args := c.Args()
......@@ -102,9 +102,8 @@ func ShowAppHelp(c *Context) {
// Prints the list of subcommands as the default app completion method
func DefaultAppComplete(c *Context) {
for _, command := range c.App.Commands {
fmt.Fprintln(c.App.Writer, command.Name)
if command.ShortName != "" {
fmt.Fprintln(c.App.Writer, command.ShortName)
for _, name := range command.Names() {
fmt.Fprintln(c.App.Writer, name)
}
}
}
......
......@@ -85,7 +85,7 @@ func makeParamsAndCache(chainManager pow.ChainManager, blockNum uint64) (*Params
Epoch: blockNum / epochLength,
}
C.ethash_params_init(paramsAndCache.params, C.uint32_t(uint32(blockNum)))
paramsAndCache.cache.mem = C.malloc(paramsAndCache.params.cache_size)
paramsAndCache.cache.mem = C.malloc(C.size_t(paramsAndCache.params.cache_size))
seedHash, err := GetSeedHash(blockNum)
if err != nil {
......@@ -118,7 +118,7 @@ func (pow *Ethash) UpdateCache(force bool) error {
func makeDAG(p *ParamsAndCache) *DAG {
d := &DAG{
dag: C.malloc(p.params.full_size),
dag: C.malloc(C.size_t(p.params.full_size)),
file: false,
paramsAndCache: p,
}
......
......@@ -7,84 +7,73 @@
var Keccak = require('./keccak');
var util = require('./util');
var ethUtil = require('ethereumjs-util');
// 32-bit unsigned modulo
function mod32(x, n)
{
return (x>>>0) % (n>>>0);
function mod32(x, n) {
return (x >>> 0) % (n >>> 0);
}
function fnv(x, y)
{
function fnv(x, y) {
// js integer multiply by 0x01000193 will lose precision
return ((x*0x01000000 | 0) + (x*0x193 | 0)) ^ y;
return ((x * 0x01000000 | 0) + (x * 0x193 | 0)) ^ y;
}
function computeCache(params, seedWords)
{
function computeCache(params, seedWords) {
var cache = new Uint32Array(params.cacheSize >> 2);
var cacheNodeCount = params.cacheSize >> 6;
// Initialize cache
var keccak = new Keccak();
keccak.digestWords(cache, 0, 16, seedWords, 0, seedWords.length);
for (var n = 1; n < cacheNodeCount; ++n)
{
keccak.digestWords(cache, n<<4, 16, cache, (n-1)<<4, 16);
for (var n = 1; n < cacheNodeCount; ++n) {
keccak.digestWords(cache, n << 4, 16, cache, (n - 1) << 4, 16);
}
var tmp = new Uint32Array(16);
// Do randmemohash passes
for (var r = 0; r < params.cacheRounds; ++r)
{
for (var n = 0; n < cacheNodeCount; ++n)
{
for (var r = 0; r < params.cacheRounds; ++r) {
for (var n = 0; n < cacheNodeCount; ++n) {
var p0 = mod32(n + cacheNodeCount - 1, cacheNodeCount) << 4;
var p1 = mod32(cache[n<<4|0], cacheNodeCount) << 4;
var p1 = mod32(cache[n << 4 | 0], cacheNodeCount) << 4;
for (var w = 0; w < 16; w=(w+1)|0)
{
for (var w = 0; w < 16; w = (w + 1) | 0) {
tmp[w] = cache[p0 | w] ^ cache[p1 | w];
}
keccak.digestWords(cache, n<<4, 16, tmp, 0, tmp.length);
keccak.digestWords(cache, n << 4, 16, tmp, 0, tmp.length);
}
}
return cache;
}
function computeDagNode(o_node, params, cache, keccak, nodeIndex)
{
function computeDagNode(o_node, params, cache, keccak, nodeIndex) {
var cacheNodeCount = params.cacheSize >> 6;
var dagParents = params.dagParents;
var c = (nodeIndex % cacheNodeCount) << 4;
var mix = o_node;
for (var w = 0; w < 16; ++w)
{
mix[w] = cache[c|w];
for (var w = 0; w < 16; ++w) {
mix[w] = cache[c | w];
}
mix[0] ^= nodeIndex;
keccak.digestWords(mix, 0, 16, mix, 0, 16);
for (var p = 0; p < dagParents; ++p)
{
for (var p = 0; p < dagParents; ++p) {
// compute cache node (word) index
c = mod32(fnv(nodeIndex ^ p, mix[p&15]), cacheNodeCount) << 4;
c = mod32(fnv(nodeIndex ^ p, mix[p & 15]), cacheNodeCount) << 4;
for (var w = 0; w < 16; ++w)
{
mix[w] = fnv(mix[w], cache[c|w]);
for (var w = 0; w < 16; ++w) {
mix[w] = fnv(mix[w], cache[c | w]);
}
}
keccak.digestWords(mix, 0, 16, mix, 0, 16);
}
function computeHashInner(mix, params, cache, keccak, tempNode)
{
var mixParents = params.mixParents|0;
function computeHashInner(mix, params, cache, keccak, tempNode) {
var mixParents = params.mixParents | 0;
var mixWordCount = params.mixSize >> 2;
var mixNodeCount = mixWordCount >> 4;
var dagPageCount = (params.dagSize / params.mixSize) >> 0;
......@@ -93,30 +82,25 @@ function computeHashInner(mix, params, cache, keccak, tempNode)
var s0 = mix[0];
// initialise mix from initial 64 bytes
for (var w = 16; w < mixWordCount; ++w)
{
for (var w = 16; w < mixWordCount; ++w) {
mix[w] = mix[w & 15];
}
for (var a = 0; a < mixParents; ++a)
{
var p = mod32(fnv(s0 ^ a, mix[a & (mixWordCount-1)]), dagPageCount);
var d = (p * mixNodeCount)|0;
for (var a = 0; a < mixParents; ++a) {
var p = mod32(fnv(s0 ^ a, mix[a & (mixWordCount - 1)]), dagPageCount);
var d = (p * mixNodeCount) | 0;
for (var n = 0, w = 0; n < mixNodeCount; ++n, w += 16)
{
computeDagNode(tempNode, params, cache, keccak, (d + n)|0);
for (var n = 0, w = 0; n < mixNodeCount; ++n, w += 16) {
computeDagNode(tempNode, params, cache, keccak, (d + n) | 0);
for (var v = 0; v < 16; ++v)
{
mix[w|v] = fnv(mix[w|v], tempNode[v]);
for (var v = 0; v < 16; ++v) {
mix[w | v] = fnv(mix[w | v], tempNode[v]);
}
}
}
}
function convertSeed(seed)
{
function convertSeed(seed) {
// todo, reconcile with spec, byte ordering?
// todo, big-endian conversion
var newSeed = util.toWords(seed);
......@@ -125,22 +109,54 @@ function convertSeed(seed)
return newSeed;
}
exports.defaultParams = function()
{
var params = exports.params = {
REVISION: 23,
DATASET_BYTES_INIT: 1073741824,
DATASET_BYTES_GROWTH: 8388608,
CACHE_BYTES_INIT: 1073741824,
CACHE_BYTES_GROWTH: 131072,
EPOCH_LENGTH: 30000,
MIX_BYTES: 128,
HASH_BYTES: 64,
DATASET_PARENTS: 256,
CACHE_ROUNDS: 3,
ACCESSES: 64
};
var cache_sizes = require('./cache_sizes');
var dag_sizes = require('./dag_sizes');
exports.calcSeed = function(blockNum) {
var epoch;
var seed = new Uint8Array(32);
if (blockNum > cache_sizes.length * params.EPOCH_LENGTH) {
return new Error('Time to upgrade to POS!!!');
} else {
epoch = Math.floor(blockNum / params.EPOCH_LENGTH);
for (var i = 0; i < epoch; i++) {
seed = ethUtil.sha3(new Buffer(seed));
}
return seed;
}
};
exports.defaultParams = function() {
return {
cacheSize: 1048384,
cacheRounds: 3,
dagSize: 1073739904,
dagParents: 256,
mixSize: 128,
mixParents: 64,
mixParents: 64
};
};
exports.Ethash = function(params, seed)
{
exports.Ethash = function(params, seed) {
// precompute cache and related values
seed = convertSeed(seed);
// seed = convertSeed(seed);
var cache = computeCache(params, seed);
// preallocate buffers/etc
......@@ -154,24 +170,21 @@ exports.Ethash = function(params, seed)
var retWords = new Uint32Array(8);
var retBytes = new Uint8Array(retWords.buffer); // supposedly read-only
this.hash = function(header, nonce)
{
this.hash = function(header, nonce) {
// compute initial hash
initBytes.set(header, 0);
initBytes.set(nonce, 32);
keccak.digestWords(initWords, 0, 16, initWords, 0, 8 + nonce.length/4);
keccak.digestWords(initWords, 0, 16, initWords, 0, 8 + nonce.length / 4);
// compute mix
for (var i = 0; i != 16; ++i)
{
for (var i = 0; i !== 16; ++i) {
mixWords[i] = initWords[i];
}
computeHashInner(mixWords, params, cache, keccak, tempNode);
// compress mix and append to initWords
for (var i = 0; i != mixWords.length; i += 4)
{
initWords[16 + i/4] = fnv(fnv(fnv(mixWords[i], mixWords[i+1]), mixWords[i+2]), mixWords[i+3]);
for (var i = 0; i !== mixWords.length; i += 4) {
initWords[16 + i / 4] = fnv(fnv(fnv(mixWords[i], mixWords[i + 1]), mixWords[i + 2]), mixWords[i + 3]);
}
// final Keccak hashes
......@@ -179,12 +192,7 @@ exports.Ethash = function(params, seed)
return retBytes;
};
this.cacheDigest = function()
{
this.cacheDigest = function() {
return keccak.digest(32, new Uint8Array(cache.buffer));
};
};
{
"name": "ethash.js",
"version": "0.0.1",
"description": "",
"main": "ethash.js",
"scripts": {
"test": "node ./test/test.js"
},
"repository": {
"type": "git",
"url": "https://github.com/ethereum/ethash/tree/master/js"
},
"keywords": [
"ethereum"
],
"author": "",
"license": "mit",
"devDependencies": {
"ethereum-tests": "0.0.5"
}
}
var tape = require('tape');
const ethash = require('../ethash.js');
tape('seed hash', function(t) {
t.test('seed should match TRUTH', function(st) {
const seed = '290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563';
const blockNum = 30000;
var r = new Buffer(ethash.calcSeed(blockNum));
st.equal(r.toString('hex'), seed);
st.end();
});
t.test('seed should match TRUTH2', function(st) {
const seed = '510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61d9';
const blockNum = 60000;
var r = new Buffer(ethash.calcSeed(blockNum));
st.equal(r.toString('hex'), seed);
st.end();
});
t.test('seed should match TRUTH3', function(st) {
const seed = '510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61d9';
const blockNum = 60700;
var r = new Buffer(ethash.calcSeed(blockNum));
st.equal(r.toString('hex'), seed);
st.end();
});
t.test('randomized tests', function(st) {
for (var i = 0; i < 100; i++) {
var x = Math.floor(ethash.params.EPOCH_LENGTH * 2048 * Math.random());
st.equal(ethash.calcSeed(x).toString('hex'), ethash.calcSeed(Math.floor(x / ethash.params.EPOCH_LENGTH) * ethash.params.EPOCH_LENGTH ).toString('hex'));
}
st.end();
});
// '510e4e770828ddbf7f7b00ab00a9f6adaf81c0dc9cc85f1f8249c256942d61d9'
// [7:13:32 PM] Matthew Wampler-Doty: >>> x = randint(0,700000)
//
// >>> pyethash.get_seedhash(x).encode('hex') == pyethash.get_seedhash((x // pyethash.EPOCH_LENGTH) * pyethash.EPOCH_LENGTH).encode('hex')
});
......@@ -4,9 +4,9 @@
/*jslint node: true, shadow:true */
"use strict";
var ethash = require('./ethash');
var util = require('./util');
var Keccak = require('./keccak');
var ethash = require('../ethash');
var util = require('../util');
var Keccak = require('../keccak');
// sanity check hash functions
var src = util.stringToBytes("");
......@@ -31,7 +31,7 @@ var ethashParams = ethash.defaultParams();
var seed = util.hexStringToBytes("9410b944535a83d9adf6bbdcc80e051f30676173c16ca0d32d6f1263fc246466")
var startTime = new Date().getTime();
var hasher = new ethash.Ethash(ethashParams, seed);
console.log('Ethash startup took: '+(new Date().getTime() - startTime) + "ms");
console.log('Ethash startup took: ' + (new Date().getTime() - startTime) + "ms");
console.log('Ethash cache hash: ' + util.bytesToHexString(hasher.cacheDigest()));
var testHexString = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
......@@ -45,9 +45,8 @@ var hash;
startTime = new Date().getTime();
var trials = 10;
for (var i = 0; i < trials; ++i)
{
for (var i = 0; i < trials; ++i) {
hash = hasher.hash(header, nonce);
}
console.log("Light client hashes averaged: " + (new Date().getTime() - startTime)/trials + "ms");
console.log("Light client hashes averaged: " + (new Date().getTime() - startTime) / trials + "ms");
console.log("Hash = " + util.bytesToHexString(hash));
......@@ -25,9 +25,9 @@ setup (
author = "Matthew Wampler-Doty",
author_email = "matthew.wampler.doty@gmail.com",
license = 'GPL',
version = '23',
version = '23.1',
url = 'https://github.com/ethereum/ethash',
download_url = 'https://github.com/ethereum/ethash/tarball/v23',
download_url = 'https://github.com/ethereum/ethash/tarball/v23.1',
description = 'Python wrappers for ethash, the ethereum proof of work hashing function',
ext_modules = [pyethash],
)
......@@ -48,7 +48,7 @@ extern "C" {
// Sow[i*HashBytes]; j++]]]][[2]][[1]]
static const size_t dag_sizes[2048] = {
static const uint64_t dag_sizes[2048] = {
1073739904U, 1082130304U, 1090514816U, 1098906752U, 1107293056U,
1115684224U, 1124070016U, 1132461952U, 1140849536U, 1149232768U,
1157627776U, 1166013824U, 1174404736U, 1182786944U, 1191180416U,
......@@ -477,7 +477,7 @@ static const size_t dag_sizes[2048] = {
// While[! PrimeQ[i], i--];
// Sow[i*HashBytes]; j++]]]][[2]][[1]]
const size_t cache_sizes[2048] = {
const uint64_t cache_sizes[2048] = {
16776896U, 16907456U, 17039296U, 17170112U, 17301056U, 17432512U, 17563072U,
17693888U, 17824192U, 17955904U, 18087488U, 18218176U, 18349504U, 18481088U,
18611392U, 18742336U, 18874304U, 19004224U, 19135936U, 19267264U, 19398208U,
......
......@@ -43,8 +43,8 @@ extern "C" {
#endif
typedef struct ethash_params {
size_t full_size; // Size of full data set (in bytes, multiple of mix size (128)).
size_t cache_size; // Size of compute cache (in bytes, multiple of node size (64)).
uint64_t full_size; // Size of full data set (in bytes, multiple of mix size (128)).
uint64_t cache_size; // Size of compute cache (in bytes, multiple of node size (64)).
} ethash_params;
typedef struct ethash_return_value {
......@@ -52,45 +52,52 @@ typedef struct ethash_return_value {
uint8_t mix_hash[32];
} ethash_return_value;
size_t ethash_get_datasize(const uint32_t block_number);
size_t ethash_get_cachesize(const uint32_t block_number);
uint64_t ethash_get_datasize(const uint32_t block_number);
uint64_t ethash_get_cachesize(const uint32_t block_number);
// initialize the parameters
static inline void ethash_params_init(ethash_params *params, const uint32_t block_number) {
// Initialize the Parameters
static inline int ethash_params_init(ethash_params *params, const uint32_t block_number) {
params->full_size = ethash_get_datasize(block_number);
if (params->full_size == 0)
return 0;
params->cache_size = ethash_get_cachesize(block_number);
if (params->cache_size == 0)
return 0;
return 1;
}
typedef struct ethash_cache {
void *mem;
} ethash_cache;
void ethash_mkcache(ethash_cache *cache, ethash_params const *params, const uint8_t seed[32]);
void ethash_compute_full_data(void *mem, ethash_params const *params, ethash_cache const *cache);
void ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce);
void ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce);
int ethash_mkcache(ethash_cache *cache, ethash_params const *params, const uint8_t seed[32]);
int ethash_compute_full_data(void *mem, ethash_params const *params, ethash_cache const *cache);
int ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce);
int ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce);
void ethash_get_seedhash(uint8_t seedhash[32], const uint32_t block_number);
static inline void ethash_prep_light(void *cache, ethash_params const *params, const uint8_t seed[32]) {
static inline int ethash_prep_light(void *cache, ethash_params const *params, const uint8_t seed[32]) {
ethash_cache c;
c.mem = cache;
ethash_mkcache(&c, params, seed);
return ethash_mkcache(&c, params, seed);
}
static inline void ethash_compute_light(ethash_return_value *ret, void const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce) {
static inline int ethash_compute_light(ethash_return_value *ret, void const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce) {
ethash_cache c;
c.mem = (void *) cache;
ethash_light(ret, &c, params, header_hash, nonce);
return ethash_light(ret, &c, params, header_hash, nonce);
}
static inline void ethash_prep_full(void *full, ethash_params const *params, void const *cache) {
static inline int ethash_prep_full(void *full, ethash_params const *params, void const *cache) {
ethash_cache c;
c.mem = (void *) cache;
ethash_compute_full_data(full, params, &c);
return ethash_compute_full_data(full, params, &c);
}
static inline void ethash_compute_full(ethash_return_value *ret, void const *full, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce) {
ethash_full(ret, full, params, header_hash, nonce);
static inline int ethash_compute_full(ethash_return_value *ret, void const *full, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce) {
return ethash_full(ret, full, params, header_hash, nonce);
}
// Returns if hash is less than or equal to difficulty
......
......@@ -20,7 +20,6 @@
* @date 2015
*/
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
#include "ethash.h"
......@@ -29,6 +28,9 @@
#include "internal.h"
#include "data_sizes.h"
// Inline assembly doesn't work
#define ENABLE_SSE 0
#ifdef WITH_CRYPTOPP
#include "sha3_cryptopp.h"
......@@ -37,24 +39,29 @@
#include "sha3.h"
#endif // WITH_CRYPTOPP
size_t ethash_get_datasize(const uint32_t block_number) {
assert(block_number / EPOCH_LENGTH < 2048);
uint64_t ethash_get_datasize(const uint32_t block_number) {
if (block_number / EPOCH_LENGTH >= 2048)
return 0;
return dag_sizes[block_number / EPOCH_LENGTH];
}
size_t ethash_get_cachesize(const uint32_t block_number) {
assert(block_number / EPOCH_LENGTH < 2048);
uint64_t ethash_get_cachesize(const uint32_t block_number) {
if (block_number / EPOCH_LENGTH >= 2048)
return 0;
return cache_sizes[block_number / EPOCH_LENGTH];
}
// Follows Sergio's "STRICT MEMORY HARD HASHING FUNCTIONS" (2014)
// https://bitslog.files.wordpress.com/2013/12/memohash-v0-3.pdf
// SeqMemoHash(s, R, N)
void static ethash_compute_cache_nodes(
int static ethash_compute_cache_nodes(
node *const nodes,
ethash_params const *params,
const uint8_t seed[32]) {
assert((params->cache_size % sizeof(node)) == 0);
if ((params->cache_size % sizeof(node)) != 0)
return 0;
uint32_t const num_nodes = (uint32_t) (params->cache_size / sizeof(node));
SHA3_512(nodes[0].bytes, seed, 32);
......@@ -82,22 +89,27 @@ void static ethash_compute_cache_nodes(
nodes->words[w] = fix_endian32(nodes->words[w]);
}
#endif
return 1;
}
void ethash_mkcache(
int ethash_mkcache(
ethash_cache *cache,
ethash_params const *params,
const uint8_t seed[32]) {
node *nodes = (node *) cache->mem;
ethash_compute_cache_nodes(nodes, params, seed);
return ethash_compute_cache_nodes(nodes, params, seed);
}
void ethash_calculate_dag_item(
int ethash_calculate_dag_item(
node *const ret,
const unsigned node_index,
const uint64_t node_index,
const struct ethash_params *params,
const struct ethash_cache *cache) {
if (params->cache_size % sizeof(node) != 0)
return 0;
uint32_t num_parent_nodes = (uint32_t) (params->cache_size / sizeof(node));
node const *cache_nodes = (node const *) cache->mem;
node const *init = &cache_nodes[node_index % num_parent_nodes];
......@@ -145,23 +157,58 @@ void ethash_calculate_dag_item(
}
SHA3_512(ret->bytes, ret->bytes, sizeof(node));
return 1;
}
void ethash_compute_full_data(
int ethash_compute_full_data(
void *mem,
ethash_params const *params,
ethash_cache const *cache) {
assert((params->full_size % (sizeof(uint32_t) * MIX_WORDS)) == 0);
assert((params->full_size % sizeof(node)) == 0);
if ((params->full_size % (sizeof(uint32_t) * MIX_WORDS)) != 0)
return 0;
if ((params->full_size % sizeof(node)) != 0)
return 0;
node *full_nodes = mem;
// now compute full nodes
for (uint64_t n = 0; n != (params->full_size / sizeof(node)); ++n) {
ethash_calculate_dag_item(&(full_nodes[n]), n, params, cache);
}
return 1;
}
int ethash_compute_full_data_section(
void *mem,
ethash_params const *params,
ethash_cache const *cache,
uint64_t const start,
uint64_t const end) {
if ((params->full_size % (sizeof(uint32_t) * MIX_WORDS)) != 0)
return 0;
if ((params->full_size % sizeof(node)) != 0)
return 0;
if (end >= params->full_size)
return 0;
if (start >= end)
return 0;
node *full_nodes = mem;
// now compute full nodes
for (unsigned n = 0; n != (params->full_size / sizeof(node)); ++n) {
for (uint64_t n = start; n != end; ++n) {
ethash_calculate_dag_item(&(full_nodes[n]), n, params, cache);
}
return 1;
}
static void ethash_hash(
static int ethash_hash(
ethash_return_value *ret,
node const *full_nodes,
ethash_cache const *cache,
......@@ -169,10 +216,10 @@ static void ethash_hash(
const uint8_t header_hash[32],
const uint64_t nonce) {
assert((params->full_size % MIX_WORDS) == 0);
if ((params->full_size % MIX_WORDS) != 0)
return 0;
// pack hash and nonce together into first 40 bytes of s_mix
assert(sizeof(node) * 8 == 512);
node s_mix[MIX_NODES + 1];
memcpy(s_mix[0].bytes, header_hash, 32);
......@@ -254,6 +301,7 @@ static void ethash_hash(
memcpy(ret->mix_hash, mix->bytes, 32);
// final Keccak hash
SHA3_256(ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix)
return 1;
}
void ethash_quick_hash(
......@@ -291,10 +339,10 @@ int ethash_quick_check_difficulty(
return ethash_check_difficulty(return_hash, difficulty);
}
void ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) {
ethash_hash(ret, (node const *) full_mem, NULL, params, previous_hash, nonce);
int ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) {
return ethash_hash(ret, (node const *) full_mem, NULL, params, previous_hash, nonce);
}
void ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) {
ethash_hash(ret, NULL, cache, params, previous_hash, nonce);
int ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) {
return ethash_hash(ret, NULL, cache, params, previous_hash, nonce);
}
\ No newline at end of file
......@@ -30,9 +30,9 @@ typedef union node {
} node;
void ethash_calculate_dag_item(
int ethash_calculate_dag_item(
node *const ret,
const unsigned node_index,
const uint64_t node_index,
ethash_params const *params,
ethash_cache const *cache
);
......
......@@ -58,7 +58,7 @@ mkcache_bytes(PyObject *self, PyObject *args) {
}
ethash_params params;
params.cache_size = (size_t) cache_size;
params.cache_size = (uint64_t) cache_size;
ethash_cache cache;
cache.mem = malloc(cache_size);
ethash_mkcache(&cache, &params, (uint8_t *) seed);
......@@ -92,8 +92,8 @@ calc_dataset_bytes(PyObject *self, PyObject *args) {
}
ethash_params params;
params.cache_size = (size_t) cache_size;
params.full_size = (size_t) full_size;
params.cache_size = (uint64_t) cache_size;
params.full_size = (uint64_t) full_size;
ethash_cache cache;
cache.mem = (void *) cache_bytes;
void *mem = malloc(params.full_size);
......@@ -138,8 +138,8 @@ hashimoto_light(PyObject *self, PyObject *args) {
ethash_return_value out;
ethash_params params;
params.cache_size = (size_t) cache_size;
params.full_size = (size_t) full_size;
params.cache_size = (uint64_t) cache_size;
params.full_size = (uint64_t) full_size;
ethash_cache cache;
cache.mem = (void *) cache_bytes;
ethash_light(&out, &cache, &params, (uint8_t *) header, nonce);
......@@ -175,7 +175,7 @@ hashimoto_full(PyObject *self, PyObject *args) {
ethash_return_value out;
ethash_params params;
params.full_size = (size_t) full_size;
params.full_size = (uint64_t) full_size;
ethash_full(&out, (void *) full_bytes, &params, (uint8_t *) header, nonce);
return Py_BuildValue("{s:s#, s:s#}",
"mix digest", out.mix_hash, 32,
......@@ -216,7 +216,7 @@ mine(PyObject *self, PyObject *args) {
ethash_return_value out;
ethash_params params;
params.full_size = (size_t) full_size;
params.full_size = (uint64_t) full_size;
// TODO: Multi threading?
do {
......
......@@ -17,7 +17,7 @@
#include <boost/test/unit_test.hpp>
#include <iostream>
std::string bytesToHexString(const uint8_t *str, const size_t s) {
std::string bytesToHexString(const uint8_t *str, const uint32_t s) {
std::ostringstream ret;
for (int i = 0; i < s; ++i)
......@@ -80,9 +80,11 @@ BOOST_AUTO_TEST_CASE(ethash_params_init_genesis_check) {
BOOST_AUTO_TEST_CASE(ethash_params_init_genesis_calcifide_check) {
ethash_params params;
ethash_params_init(&params, 0);
const uint32_t expected_full_size = 1073739904;
const uint32_t expected_cache_size = 16776896;
BOOST_REQUIRE_MESSAGE(ethash_params_init(&params, 0),
"Params could not be initialized");
const uint32_t
expected_full_size = 1073739904,
expected_cache_size = 16776896;
BOOST_REQUIRE_MESSAGE(params.full_size == expected_full_size,
"\nexpected: " << expected_cache_size << "\n"
<< "actual: " << params.full_size << "\n");
......
......@@ -14,11 +14,8 @@ TEST_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
echo -e "\n################# Testing JS ##################"
# TODO: Use mocha and real testing tools instead of rolling our own
cd $TEST_DIR/../js
if [ -x "$(which nodejs)" ] ; then
nodejs test.js
fi
if [ -x "$(which node)" ] ; then
node test.js
if [ -x "$(which npm)" ] ; then
npm test
fi
echo -e "\n################# Testing C ##################"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment