forked from MintPond/hasher-kawpow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhasherkawpow_py.cc
111 lines (85 loc) · 3.6 KB
/
hasherkawpow_py.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <Python.h>
#include <stdint.h>
#include "ethash.h"
#include "ethash.hpp"
#include "progpow.hpp"
#include "keccak.hpp"
#include "uint256.h"
#include "helpers.hpp"
static PyObject* keccak_256(PyObject *self, PyObject *args) {
Py_buffer buf;
if (!PyArg_ParseTuple(args, "y*", &buf))
return NULL;
const uint8_t* buf_ptr = (uint8_t*)buf.buf;
const size_t buf_len = (size_t)buf.len;
const ethash::hash256 hash = ethash::keccak256(buf_ptr, buf_len);
PyBuffer_Release(&buf);
PyObject *hash_py = PyBytes_FromStringAndSize((const char *)&hash, sizeof(ethash::hash256));
return hash_py;
}
static ethash::epoch_context_ptr context{nullptr, nullptr};
static PyObject* pow(PyObject *self, PyObject *args) {
Py_buffer header_hash_buf, nonce64_buf;
int block_height;
if (!PyArg_ParseTuple(args, "y*y*i", &header_hash_buf, &nonce64_buf, &block_height))
return NULL;
if (header_hash_buf.len != 32 || nonce64_buf.len != 8) {
PyErr_SetString(PyExc_ValueError, "Buffer length is not correct");
return NULL;
}
const ethash::hash256* header_hash_ptr = (ethash::hash256*)header_hash_buf.buf;
uint64_t* nonce64_ptr = (uint64_t*)nonce64_buf.buf;
ethash::hash256 mix_out;
ethash::hash256 hash_out;
const auto epoch_number = ethash::get_epoch_number(block_height);
if (!context || context->epoch_number != epoch_number)
context = ethash::create_epoch_context(epoch_number);
progpow::hash_one(*context, block_height, header_hash_ptr, *nonce64_ptr, &mix_out, &hash_out);
PyBuffer_Release(&header_hash_buf);
PyBuffer_Release(&nonce64_buf);
PyObject *hash_py = PyBytes_FromStringAndSize((const char *)&hash_out, sizeof(ethash::hash256));
PyObject *mix_py = PyBytes_FromStringAndSize((const char *)&mix_out, sizeof(ethash::hash256));
PyObject *tuple = Py_BuildValue("(OO)", hash_py, mix_py);
Py_DECREF(hash_py);
Py_DECREF(mix_py);
return tuple;
}
static PyObject* pow_light(PyObject *self, PyObject *args) {
Py_buffer header_hash_buf, nonce64_buf, mix_hash_buf;
int block_height;
if (!PyArg_ParseTuple(args, "y*y*iy*", &header_hash_buf, &nonce64_buf, &block_height, &mix_hash_buf))
return NULL;
if (header_hash_buf.len != 32 || nonce64_buf.len != 8 || mix_hash_buf.len != 32) {
PyErr_SetString(PyExc_ValueError, "Buffer length is not correct");
return NULL;
}
const ethash::hash256* header_hash_ptr = (ethash::hash256*)header_hash_buf.buf;
uint64_t* nonce64_ptr = (uint64_t*)nonce64_buf.buf;
const ethash::hash256* mix_hash_ptr = (ethash::hash256*)mix_hash_buf.buf;
ethash::hash256 hash_out;
const auto epoch_number = ethash::get_epoch_number(block_height);
if (!context || context->epoch_number != epoch_number)
context = ethash::create_epoch_context(epoch_number);
progpow::hash_one_light(*context, block_height, header_hash_ptr, *nonce64_ptr, mix_hash_ptr, &hash_out);
PyBuffer_Release(&header_hash_buf);
PyBuffer_Release(&nonce64_buf);
PyBuffer_Release(&mix_hash_buf);
PyObject *hash_py = PyBytes_FromStringAndSize((const char *)&hash_out, sizeof(ethash::hash256));
return hash_py;
}
static PyMethodDef methods[] = {
{"keccak_256", (PyCFunction)keccak_256, METH_VARARGS},
{"pow", (PyCFunction)pow, METH_VARARGS},
{"pow_light", (PyCFunction)pow_light, METH_VARARGS},
{NULL, NULL}
};
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"kawpow",
NULL,
-1,
methods
};
PyMODINIT_FUNC PyInit_kawpow(void) {
return PyModule_Create(&module);
}