Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #146 from HelixNetwork/dev
Browse files Browse the repository at this point in the history
0.6.3
  • Loading branch information
oracle58 authored Sep 20, 2019
2 parents c571eac + 0fb044b commit 28ba078
Show file tree
Hide file tree
Showing 22 changed files with 302 additions and 66 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## 0.6.3
- Added test for Round model
- Update Round Model
- Add test for hashes
- Sha3 getStandardHash() returns zeros for 0-length input array
- Hashes model was updated to support reading with offset
- HashPrefix length set to 32
- Fix #143 Entry point failed consistency check exception at node start-up

## 0.6.2
- Fix replayMilestonesInconsistentTest
- Nominee setting (#135)
- Key generation with a prebuilt jar (#136)

## 0.6.1
- Curator-less implementation
- Set initial nominees
Expand Down
72 changes: 71 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Helix

A Quorum based Tangle implementation forked from [**IRI**](https://github.com/iotaledger/iri/).
- **Latest release:** 0.6.1 pre-release
- **Latest release:** 0.6.3 pre-release
- **License:** GPLv3

Special thanks to all of the [IOTA Contributors](https://github.com/iotaledger/iri/graphs/contributors)!
Expand Down Expand Up @@ -38,6 +38,76 @@ Build an executable jar at the `target` directory using maven.
Launching a node as a nominee first requires to generate a 64 character hex string, that is used as a seed for key generation. You will find the public key in the last line of the `nominee.key` file contained in the resources directory. If you wish to act as a nominee, please send a request to [email protected] containing your public key.

java -jar target/helix-<VERSION>.jar -p 8085 --nominee <pathToNomineeSeed>


### Nginx cluster sample config

For production-level applications we recommend exposing a single public API endpoint reverse-proxing multiple fullnode instances. Additionally, we highly recommend obtaining an SSL certificate from a trusted authority (e.g. from Let’s Encrypt).

Below is a sample configuration file for the popular Nginx webserver (typically put into `/etc/nginx/conf.d/` ). For more information please consult the official Nginx [documentation](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)

```
upstream helix {
ip_hash;
Server fullnode1.ip.address:8085;
Server fullnode2.ip.address:8085;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name my.api.endpoint.com;
server_tokens off;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
## CORS
proxy_hide_header Access-Control-Allow-Origin;
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_redirect off;
proxy_set_header host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-forward-for $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://helix;
}
}
```


## Configuration

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<groupId>net.helix</groupId>
<artifactId>helix</artifactId>

<version>0.6.1</version>
<version>0.6.3</version>

<name>Helix</name>
<description>Helix Protocol</description>
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/net/helix/hlx/HLX.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public class HLX {

public static final String MAINNET_NAME = "HLX";
public static final String TESTNET_NAME = "HLX Testnet";
public static final String VERSION = "0.6.1";
public static final String VERSION = "0.6.3";

/**
* The entry point of the helix sandbox.
Expand Down Expand Up @@ -135,7 +135,7 @@ public static void main(String [] args) throws Exception {
log.error("Exception during Helix node initialisation: ", e);
throw e;
}
if (config.getNominee() != null) {
if (config.getNominee() != null || new File(config.getNomineeKeyfile()).isFile() ) {
milestonePublisher = new MilestonePublisher(config, api, helix.candidateTracker);
milestonePublisher.startScheduledExecutorService();
}
Expand All @@ -158,7 +158,7 @@ private static void shutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
log.info("Shutting down Helix node, please hold tight...");
try {
if (helix.configuration.getNominee() != null) {
if (helix.configuration.getNominee() != null || new File(helix.configuration.getNomineeKeyfile()).isFile()) {
milestonePublisher.shutdown();
}
/*if (helix.configuration.getCuratorEnabled()) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/net/helix/hlx/Helix.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureRandom;
import java.util.List;

Expand Down Expand Up @@ -212,6 +215,9 @@ public void init() throws Exception {
tangle.addMessageQueueProvider(new MessageQProviderImpl(configuration));
transactionStatsPublisher.init();
}
if(Files.notExists(Paths.get(configuration.getResourcePath()))){
new File(configuration.getResourcePath()).mkdir();
}
}

//TODO: bundleValidator should be passed to: milestoneService, spentAddressService and ledgerService.
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/net/helix/hlx/conf/APIConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public interface APIConfig extends Config {
*/
boolean isPoWDisabled();

/**
* @return {@value Descriptions#RESOURCE_PATH}
*/
String getResourcePath();

interface Descriptions {
String PORT = "The port that will be used by the API.";
String API_HOST = "The host on which the API will listen to. Set to 0.0.0.0 to accept any host.";
Expand All @@ -69,5 +74,6 @@ interface Descriptions {
String MAX_BODY_LENGTH = "The maximal number of characters the body of an API call may hold. If a request body length exceeds this number an error will be returned.";
String REMOTE = "Open the API interface to any host. Equivalent to \"--api-host 0.0.0.0\"";
String IS_POW_DISABLED = "If pow is disabled the node will not require a valid nonce.";
String RESOURCE_PATH = "Resource path";
}
}
24 changes: 18 additions & 6 deletions src/main/java/net/helix/hlx/conf/BaseHelixConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
/*
Expand Down Expand Up @@ -131,6 +133,8 @@ public abstract class BaseHelixConfig implements HelixConfig {
protected int roundDuration = Defaults.ROUND_DURATION;
protected int roundPause = Defaults.ROUND_PAUSE;
protected String nomineeKeyfile = Defaults.NOMINEE_KEYFILE;
protected String resourcePath = Defaults.RESOUCER_PATH;
protected String defaultResoucePath = Defaults.DEFAULT_RESOUCE_PATH;
protected int milestoneKeyDepth = Defaults.MILESTONE_KEY_DEPTH;
protected int nomineeSecurity = Defaults.NOMINEE_SECURITY;

Expand Down Expand Up @@ -819,7 +823,7 @@ protected void setBelowMaxDepthTransactionLimit(int maxAnalyzedTransactions) {
protected void setStartRoundDelay(int startRoundDelay) { this.startRoundDelay = startRoundDelay; }

@Override
public String getCuratorKeyfile() {return curatorKeyfile; }
public String getCuratorKeyfile() {return getResourcePath() + curatorKeyfile; }

@Override
public int getCuratorKeyDepth() {return curatorKeyDepth; }
Expand Down Expand Up @@ -867,7 +871,11 @@ public int getRoundDuration() {
protected void setRoundPause(int roundPause) { this.roundPause = roundPause; }

@Override
public String getNomineeKeyfile() {return nomineeKeyfile; }
public String getNomineeKeyfile() {return getResourcePath() + nomineeKeyfile; }

@Override
public String getResourcePath() {
return Files.isDirectory(Paths.get(resourcePath)) ? resourcePath : defaultResoucePath; }

@Override
public int getMilestoneKeyDepth() {return milestoneKeyDepth; }
Expand Down Expand Up @@ -1010,12 +1018,16 @@ public interface Defaults {
//PoW
int POW_THREADS = 8;

//Resource directory:
String RESOUCER_PATH = "./src/main/resources";
String DEFAULT_RESOUCE_PATH = "./resources";

//Curator
boolean CURATOR_ENABLED = false;
Hash CURATOR_ADDRESS = HashFactory.ADDRESS.create("9474289ae28f0ea6e3b8bedf8fc52f14d2fa9528a4eb29d7879d8709fd2f6d37");
int UPDATE_NOMINEE_DELAY = 30000;
int START_ROUND_DELAY = 2;
String CURATOR_KEYFILE = "./src/main/resources/Coordinator.key";
String CURATOR_KEYFILE = "/Coordinator.key";
int CURATOR_KEY_DEPTH = 15;
int CURATOR_SECURITY = 2;

Expand All @@ -1032,9 +1044,9 @@ public interface Defaults {
));

long GENESIS_TIME = 1568725976628L; //for local testing: System.currentTimeMillis();
int ROUND_DURATION = 5000;
int ROUND_PAUSE = 1000;
String NOMINEE_KEYFILE = "./src/main/resources/Nominee.key";
int ROUND_DURATION = 15000;
int ROUND_PAUSE = 5000;
String NOMINEE_KEYFILE = "/Nominee.key";
int MILESTONE_KEY_DEPTH = 10;
int NOMINEE_SECURITY = 2;

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/net/helix/hlx/crypto/Sha3.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public static byte[] getStandardHash(byte[] message) {
return hash;
}
digest.update(message, 0, message.length);
digest.doFinal(hash, 0);
}
digest.doFinal(hash, 0);
return hash;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/net/helix/hlx/crypto/Sha3_512.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public static byte[] getStandardHash(byte[] message) {
return hash;
}
digest.update(message, 0, message.length);
digest.doFinal(hash, 0);
}
digest.doFinal(hash, 0);
return hash;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/net/helix/hlx/model/HashPrefix.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* To get the prefix bytes @see #bytes()
*/
public final class HashPrefix implements HashId {
public static final int PREFIX_LENGTH = 28;
public static final int PREFIX_LENGTH = 32;
private final byte[] bytes;

public static HashPrefix createPrefix(HashId hashId) {
Expand Down
18 changes: 14 additions & 4 deletions src/main/java/net/helix/hlx/model/persistables/Hashes.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/**
* The Hashes model class is an implementation of the <code> Persistable </code> interface.
* It contains a set <code> LinkedHashSet </code> and delimiter <code> byte </code>.
* The <code> LinkedHashSet </code> is a hash table with linked entrys, which can be converted into a byte array.
* The <code> LinkedHashSet </code> is a hash table with linked entries, which can be converted into a byte array.
* The delimiter is used as indicator for next element of the LinkedHashSet.
*/
public class Hashes implements Persistable {
Expand All @@ -37,10 +37,20 @@ public byte[] bytes() {
* Create the set from a given byte array.
* @param bytes is a <code> byte[] </code>
*/
@Override
public void read(byte[] bytes) {
if(bytes != null) {
set = new LinkedHashSet<>(bytes.length / (1 + Hash.SIZE_IN_BYTES) + 1);
for (int i = 0; i < bytes.length; i += 1 + Hash.SIZE_IN_BYTES) {
read(bytes, 0);
}

/**
* Create the set from a given byte array.
* @param bytes is a <code> byte[] </code>
* @param offset the offset defining the start point for hash objects in the array
*/
protected void read(byte[] bytes, int offset) {
if (bytes != null) {
set = new LinkedHashSet<>((bytes.length - offset) / (1 + Hash.SIZE_IN_BYTES) + 1);
for (int i = offset; i < bytes.length; i += 1 + Hash.SIZE_IN_BYTES) {
set.add(HashFactory.TRANSACTION.create(bytes, i, Hash.SIZE_IN_BYTES));
}
}
Expand Down
35 changes: 12 additions & 23 deletions src/main/java/net/helix/hlx/model/persistables/Round.java
Original file line number Diff line number Diff line change
@@ -1,37 +1,26 @@
package net.helix.hlx.model.persistables;

import net.helix.hlx.model.Hash;
import net.helix.hlx.model.HashFactory;
import net.helix.hlx.model.IntegerIndex;
import net.helix.hlx.utils.Serializer;

import org.apache.commons.lang3.ArrayUtils;

import java.util.LinkedHashSet;

/**
* The Round model class consists of a set of milestone hashes and a corresponding index.
*/
public class Round extends Hashes {
public IntegerIndex index;
public IntegerIndex index;

@Override
public byte[] bytes() {
byte[] hashes = set.parallelStream()
.map(Hash::bytes)
.reduce((a,b) -> ArrayUtils.addAll(ArrayUtils.add(a, delimiter), b))
.orElse(new byte[0]);
return ArrayUtils.addAll(index.bytes(), hashes);
}
@Override
public byte[] bytes() {
return ArrayUtils.addAll(index.bytes(), super.bytes());
}

@Override
public void read(byte[] bytes) {
if(bytes != null) {
index = new IntegerIndex(Serializer.getInteger(bytes));
set = new LinkedHashSet<>((bytes.length - Integer.BYTES) / (1 + Hash.SIZE_IN_BYTES) + 1);
for (int i = Integer.BYTES; i < bytes.length; i += 1 + Hash.SIZE_IN_BYTES) {
set.add(HashFactory.TRANSACTION.create(bytes, i, Hash.SIZE_IN_BYTES));
}
}
}
@Override
public void read(byte[] bytes) {
if (bytes != null) {
index = new IntegerIndex(Serializer.getInteger(bytes));
read(bytes, Integer.BYTES);
}
}
}
Loading

0 comments on commit 28ba078

Please sign in to comment.