Skip to content
This repository has been archived by the owner on May 22, 2022. It is now read-only.

Commit

Permalink
Added Entangled PoW (written in C), it is 5-6x faster than Swift
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalbros committed May 26, 2018
1 parent 4599586 commit 0818d7e
Show file tree
Hide file tree
Showing 37 changed files with 1,115 additions and 8 deletions.
154 changes: 152 additions & 2 deletions IotaKit.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Expand Up @@ -43,7 +43,7 @@
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
Expand Down
3 changes: 2 additions & 1 deletion Package.swift
Expand Up @@ -15,9 +15,10 @@ let package = Package(
],
targets: [
.target(name: "sha3", dependencies: []),
.target(name: "cpow", dependencies: []),
.target(
name: "IotaKit",
dependencies: ["sha3"]),
dependencies: ["sha3", "cpow"]),
.testTarget(
name: "IotaKitTests",
dependencies: ["IotaKit"]),
Expand Down
2 changes: 1 addition & 1 deletion Sources/IotaKit/Iota.swift
Expand Up @@ -27,7 +27,7 @@ public class Iota: IotaDebuggable {
public var debug = false

/// Local PoW instance, setting it to `nil` will delegate the PoW to the node.
public var localPoW: IotaLocalPoW? = PearlDiverLocalPoW()
public var localPoW: IotaLocalPoW? = CPearlDiver()

/// Initializer for Iota class with automatic node selection.
///
Expand Down
Expand Up @@ -20,8 +20,8 @@ public extension IotaTransaction {
curl.reset()
_ = curl.absorb(trits: transactionTrits)
_ = curl.squeeze(trits: &hash, offset: 0, length: hash.count)
self.hash = IotaConverter.trytes(trits: hash)

self.hash = IotaConverter.trytes(trits: hash)
self.address = trytes.substring(from: 2187, to: 2268)
self.tag = trytes.substring(from: 2592, to: 2619)
self.value = IotaConverter.longValue(transactionTrits.slice(from: 6804, to: 6837))
Expand Down
31 changes: 31 additions & 0 deletions Sources/IotaKit/Pow/CPow.swift
@@ -0,0 +1,31 @@
//
// CPow.swift
// IotaKit
//
// Created by Pasquale Ambrosini on 26/05/18.
//

import CoreFoundation
import cpow
public class CPearlDiver: IotaLocalPoW {

public init() { }

public func performPoW(trytes: String, minWeightMagnitude: Int) -> String {
let cTrytes = trytes.cString(using: .utf8)
if let resultC = iota_pow(cTrytes, UInt8(minWeightMagnitude)) {
let result = String(cString: resultC)
resultC.deallocate()
var tx = IotaTransaction(trytes: trytes)
tx.nonce = result
return tx.trytes
}
return ""
}

public func performPoW(trytes: String, minWeightMagnitude: Int, result: @escaping (String) -> ()) {

}


}
26 changes: 26 additions & 0 deletions Sources/cpow/_pow.c
@@ -0,0 +1,26 @@
#include "include/_pow.h"
#include <string.h>
#include <stdlib.h>
#include "include/hashcash.h"
#include "include/trit_tryte.h"


#define NONCE_LENGTH 27 * 3


char* do_pow(Curl* curl, const char* trits_in, size_t trits_len, uint8_t mwm) {

tryte_t* nonce_trits =
(tryte_t*)calloc(NONCE_LENGTH + 1, sizeof(tryte_t));

curl_absorb(curl, trits_in, trits_len - HASH_LENGTH);
memcpy(curl->state, trits_in + trits_len - HASH_LENGTH, HASH_LENGTH);

// FIXME(th0br0) deal with result value of `hashcash` call
hashcash(curl, BODY, HASH_LENGTH - NONCE_LENGTH, HASH_LENGTH, mwm);

memcpy(nonce_trits, curl->state + HASH_LENGTH - NONCE_LENGTH, NONCE_LENGTH);

return (char*)nonce_trits;
}

109 changes: 109 additions & 0 deletions Sources/cpow/curl.c
@@ -0,0 +1,109 @@
/*
* (c) 2016 Paul Handy, based on code from come-from-beyond
*/

#include "include/curl.h"
#include "include/hash.h"
#include "include/constants.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define __TRUTH_TABLE 1, 0, -1, 2, 1, -1, 0, 2, -1, 1, 0

#define __INDEX_TABLE \
0, 364, 728, 363, 727, 362, 726, 361, 725, 360, 724, 359, 723, 358, 722,\
357, 721, 356, 720, 355, 719, 354, 718, 353, 717, 352, 716, 351, 715, 350,\
714, 349, 713, 348, 712, 347, 711, 346, 710, 345, 709, 344, 708, 343, 707,\
342, 706, 341, 705, 340, 704, 339, 703, 338, 702, 337, 701, 336, 700, 335,\
699, 334, 698, 333, 697, 332, 696, 331, 695, 330, 694, 329, 693, 328, 692,\
327, 691, 326, 690, 325, 689, 324, 688, 323, 687, 322, 686, 321, 685, 320,\
684, 319, 683, 318, 682, 317, 681, 316, 680, 315, 679, 314, 678, 313, 677,\
312, 676, 311, 675, 310, 674, 309, 673, 308, 672, 307, 671, 306, 670, 305,\
669, 304, 668, 303, 667, 302, 666, 301, 665, 300, 664, 299, 663, 298, 662,\
297, 661, 296, 660, 295, 659, 294, 658, 293, 657, 292, 656, 291, 655, 290,\
654, 289, 653, 288, 652, 287, 651, 286, 650, 285, 649, 284, 648, 283, 647,\
282, 646, 281, 645, 280, 644, 279, 643, 278, 642, 277, 641, 276, 640, 275,\
639, 274, 638, 273, 637, 272, 636, 271, 635, 270, 634, 269, 633, 268, 632,\
267, 631, 266, 630, 265, 629, 264, 628, 263, 627, 262, 626, 261, 625, 260,\
624, 259, 623, 258, 622, 257, 621, 256, 620, 255, 619, 254, 618, 253, 617,\
252, 616, 251, 615, 250, 614, 249, 613, 248, 612, 247, 611, 246, 610, 245,\
609, 244, 608, 243, 607, 242, 606, 241, 605, 240, 604, 239, 603, 238, 602,\
237, 601, 236, 600, 235, 599, 234, 598, 233, 597, 232, 596, 231, 595, 230,\
594, 229, 593, 228, 592, 227, 591, 226, 590, 225, 589, 224, 588, 223, 587,\
222, 586, 221, 585, 220, 584, 219, 583, 218, 582, 217, 581, 216, 580, 215,\
579, 214, 578, 213, 577, 212, 576, 211, 575, 210, 574, 209, 573, 208, 572,\
207, 571, 206, 570, 205, 569, 204, 568, 203, 567, 202, 566, 201, 565, 200,\
564, 199, 563, 198, 562, 197, 561, 196, 560, 195, 559, 194, 558, 193, 557,\
192, 556, 191, 555, 190, 554, 189, 553, 188, 552, 187, 551, 186, 550, 185,\
549, 184, 548, 183, 547, 182, 546, 181, 545, 180, 544, 179, 543, 178, 542,\
177, 541, 176, 540, 175, 539, 174, 538, 173, 537, 172, 536, 171, 535, 170,\
534, 169, 533, 168, 532, 167, 531, 166, 530, 165, 529, 164, 528, 163, 527,\
162, 526, 161, 525, 160, 524, 159, 523, 158, 522, 157, 521, 156, 520, 155,\
519, 154, 518, 153, 517, 152, 516, 151, 515, 150, 514, 149, 513, 148, 512,\
147, 511, 146, 510, 145, 509, 144, 508, 143, 507, 142, 506, 141, 505, 140,\
504, 139, 503, 138, 502, 137, 501, 136, 500, 135, 499, 134, 498, 133, 497,\
132, 496, 131, 495, 130, 494, 129, 493, 128, 492, 127, 491, 126, 490, 125,\
489, 124, 488, 123, 487, 122, 486, 121, 485, 120, 484, 119, 483, 118, 482,\
117, 481, 116, 480, 115, 479, 114, 478, 113, 477, 112, 476, 111, 475, 110,\
474, 109, 473, 108, 472, 107, 471, 106, 470, 105, 469, 104, 468, 103, 467,\
102, 466, 101, 465, 100, 464, 99, 463, 98, 462, 97, 461, 96, 460, 95,\
459, 94, 458, 93, 457, 92, 456, 91, 455, 90, 454, 89, 453, 88, 452,\
87, 451, 86, 450, 85, 449, 84, 448, 83, 447, 82, 446, 81, 445, 80,\
444, 79, 443, 78, 442, 77, 441, 76, 440, 75, 439, 74, 438, 73, 437,\
72, 436, 71, 435, 70, 434, 69, 433, 68, 432, 67, 431, 66, 430, 65,\
429, 64, 428, 63, 427, 62, 426, 61, 425, 60, 424, 59, 423, 58, 422,\
57, 421, 56, 420, 55, 419, 54, 418, 53, 417, 52, 416, 51, 415, 50,\
414, 49, 413, 48, 412, 47, 411, 46, 410, 45, 409, 44, 408, 43, 407,\
42, 406, 41, 405, 40, 404, 39, 403, 38, 402, 37, 401, 36, 400, 35,\
399, 34, 398, 33, 397, 32, 396, 31, 395, 30, 394, 29, 393, 28, 392,\
27, 391, 26, 390, 25, 389, 24, 388, 23, 387, 22, 386, 21, 385, 20,\
384, 19, 383, 18, 382, 17, 381, 16, 380, 15, 379, 14, 378, 13, 377,\
12, 376, 11, 375, 10, 374, 9, 373, 8, 372, 7, 371, 6, 370, 5,\
369, 4, 368, 3, 367, 2, 366, 1, 365, 0


static const size_t TRUTH_TABLE[11] = {__TRUTH_TABLE};
static const size_t INDEX[STATE_LENGTH+1] = {__INDEX_TABLE};

void transform(curl_t* ctx);

void init_curl(curl_t* ctx) {
memset(ctx->state, 0, STATE_LENGTH * sizeof(char));
}
int i = 0;
void absorb(curl_t* ctx, char* const trits, int length) {
int offset = 0;
do {
memcpy(ctx->state, trits + offset,
(length < HASH_LENGTH ? length : HASH_LENGTH) * sizeof(char));
transform(ctx);
offset += HASH_LENGTH;
} while ((length -= HASH_LENGTH) > 0);
}

void squeeze(curl_t* ctx, char* trits, int length) {
int offset = 0;
do {
// memcpy(trits+offset, ctx->state, (length < HASH_LENGTH? length:
// HASH_LENGTH) * sizeof(char));
memcpy(&(trits[offset]), ctx->state,
(length < HASH_LENGTH ? length : HASH_LENGTH) * sizeof(char));
transform(ctx);
offset += HASH_LENGTH;
} while ((length -= HASH_LENGTH) > 0);
}

void transform(curl_t* ctx) {
int round, stateIndex;
char scratchpad[STATE_LENGTH];
for (round = 0; round < NUMBER_OF_ROUNDS; round++) {
memcpy(scratchpad, ctx->state, STATE_LENGTH * sizeof(char));
for (stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) {
ctx->state[stateIndex] = TRUTH_TABLE[scratchpad[INDEX[stateIndex]] +
(scratchpad[INDEX[stateIndex+1]]<<2) +5 ];
}
}
}

void reset(curl_t* ctx) { memset(ctx->state, 0, STATE_LENGTH * sizeof(char)); }
61 changes: 61 additions & 0 deletions Sources/cpow/curl_p.c
@@ -0,0 +1,61 @@
/*
* (c) 2016 Paul Handy, based on code from come-from-beyond
*/

#include <stdio.h>
#include <string.h>

#include "include/indices.h"
#include "include/trit.h"

#define __TRUTH_TABLE 1, 0, -1, 2, 1, -1, 0, 2, -1, 1, 0

static const size_t CURL_INDEX[STATE_LENGTH + 1] = {__INDEX_TABLE};

static const trit_t TRUTH_TABLE[11] = {__TRUTH_TABLE};

void transform(Curl *ctx);
void sbox(Curl *const, Curl *const);

void init_curl(Curl *ctx) { memset(ctx->state, 0, sizeof(ctx->state)); }

void curl_absorb(Curl *ctx, trit_t *const trits, size_t length) {
size_t numChunks = length / HASH_LENGTH + ((length % HASH_LENGTH) ? 1 : 0);
size_t i = 0;
for (; i < numChunks; ++i) {
memcpy(ctx->state, trits + i * HASH_LENGTH * sizeof(trit_t),
(length < HASH_LENGTH ? length : HASH_LENGTH) * sizeof(trit_t));
transform(ctx);
length = length < HASH_LENGTH ? 0 : length - HASH_LENGTH;
}
}

void curl_squeeze(Curl *ctx, trit_t *const trits, size_t length) {
size_t numChunks = length / HASH_LENGTH + ((length % HASH_LENGTH) ? 1 : 0);
size_t i = 0;
for (; i < numChunks; ++i) {
memcpy(trits + i * HASH_LENGTH * sizeof(trit_t), ctx->state,
(length < HASH_LENGTH ? length : HASH_LENGTH) * sizeof(trit_t));
transform(ctx);
length = length < HASH_LENGTH ? 0 : length - HASH_LENGTH;
}
}

void transform(Curl *const ctx) {
Curl s;
size_t round = 0;
for (; round < ctx->type; ++round) {
memcpy(s.state, ctx->state, sizeof(ctx->state));
sbox(ctx, &s);
}
}

void sbox(Curl *const c, Curl *const s) {
size_t i = 0;
for (; i < STATE_LENGTH; ++i) {
c->state[i] = TRUTH_TABLE[s->state[CURL_INDEX[i]] +
((unsigned)s->state[CURL_INDEX[i + 1]] << 2) + 5];
}
}

void curl_reset(Curl *ctx) { memset(ctx->state, 0, sizeof(ctx->state)); }
74 changes: 74 additions & 0 deletions Sources/cpow/curl_p_ptrit.c
@@ -0,0 +1,74 @@
/*
* (c) 2016 Paul Handy, based on code from come-from-beyond
*/

#include <stdlib.h>
#include <string.h>

#include "include/const.h"
#include "include/indices.h"
#include "include/pcurl_ptrit.h"

static const size_t CURL_INDEX[STATE_LENGTH + 1] = {__INDEX_TABLE};

void ptrit_transform_round(PCurl *const, PCurl *const, size_t const);
void ptrit_sbox(ptrit_t *const, ptrit_t *const, size_t const);

void init_ptrit_curl(PCurl *ctx) { ptrit_curl_reset(ctx); }

void ptrit_curl_absorb(PCurl *ctx, ptrit_t *const trits, size_t length) {
memcpy(ctx->state, trits,
(length < HASH_LENGTH ? length : HASH_LENGTH) * sizeof(ptrit_t));
ptrit_transform(ctx);
if (length <= HASH_LENGTH) {
return;
}
ptrit_curl_absorb(ctx, trits + HASH_LENGTH * sizeof(ptrit_t),
length - HASH_LENGTH);
}

void ptrit_curl_squeeze(PCurl *ctx, ptrit_t *const trits, size_t length) {
memcpy(trits, ctx->state,
(length < HASH_LENGTH ? length : HASH_LENGTH) * sizeof(ptrit_t));

ptrit_transform(ctx);
if (length <= HASH_LENGTH) {
return;
}
ptrit_curl_squeeze(ctx, trits + HASH_LENGTH * sizeof(ptrit_t),
length - HASH_LENGTH);
}

void ptrit_transform(PCurl *const ctx) {
PCurl s;
ptrit_transform_round(ctx, &s, ctx->type);
memcpy(ctx->state, s.state, sizeof(ptrit_t) * STATE_LENGTH);
ptrit_curl_reset(&s);
}

void ptrit_transform_round(PCurl *const ctx, PCurl *const s, size_t const i) {
if (i == 0) {
return;
}
ptrit_sbox(s->state, ctx->state, 0);
ptrit_transform_round(s, ctx, i - 1);
}
void ptrit_sbox(ptrit_t *const c, ptrit_t *const s, size_t const i) {
if (i == STATE_LENGTH) {
return;
}
ptrit_s alpha, beta, gamma, delta;
alpha = s[CURL_INDEX[i]].low;
beta = s[CURL_INDEX[i]].high;
gamma = s[CURL_INDEX[i + 1]].high;
delta = (alpha | (~gamma)) & (s[CURL_INDEX[i + 1]].low ^ beta);

c->low = ~delta;
c->high = (alpha ^ gamma) | delta;

ptrit_sbox(&c[1], s, i + 1);
}

void ptrit_curl_reset(PCurl *ctx) {
memset(ctx->state, 0, sizeof(ptrit_t) * STATE_LENGTH);
}
23 changes: 23 additions & 0 deletions Sources/cpow/hashcash.c
@@ -0,0 +1,23 @@
#include <stdio.h>

#include "include/hashcash.h"
#include "include/ptrit.h"
#include "include/search.h"

short test(PCurl *curl, unsigned short mwm) {
unsigned short i;
ptrit_s probe = HIGH_BITS;
for (i = HASH_LENGTH; i-- > HASH_LENGTH - mwm && probe != 0;) {
probe &= ~(curl->state[i].low ^ curl->state[i].high);
}
if (probe == 0) {
return -1;
}
return __builtin_ctzll(probe);
}

PearlDiverStatus hashcash(Curl *const ctx, SearchType type,
unsigned short const offset, unsigned short const end,
unsigned short const min_weight) {
return pd_search(ctx, offset, end, &test, min_weight);
}
18 changes: 18 additions & 0 deletions Sources/cpow/include/_pow.h
@@ -0,0 +1,18 @@
#ifndef __CURL_POW_H
#define __CURL_POW_H


#include <stddef.h>
#include "trit.h"

#ifdef __cplusplus
extern "C" {
#endif
char* do_pow(Curl* curl, const char* trits, size_t trits_len, uint8_t mwm);

#ifdef __cplusplus
}
#endif


#endif //__CURL_POW_H

0 comments on commit 0818d7e

Please sign in to comment.