3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-30 14:52:16 +00:00

Remove existing build pom.xml

Added genesis block construction for Dogecoin network.
Added difficulty calculations for Dogecoin network.
Completed difficulty calculation code for Dogecoin.
Added code for parsing Dogecoin blocks, and unit tests for same.
This commit is contained in:
Ross Nicoll 2015-05-30 10:04:54 +01:00
parent 245505e984
commit 5c973f6149
57 changed files with 676 additions and 894 deletions

2
.gitignore vendored
View File

@ -7,3 +7,5 @@ target
*.chain
*.spvchain
*.wallet
/nbproject/private/
/build/

View File

@ -1,48 +0,0 @@
<!--
~ Copyright 2012 Google Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<FindBugsFilter>
<Match>
<!-- Protos and inner classes are generated by the proto compiler -->
<Package name="com.dogecoin.dogecoinj.protos"/>
<Package name="org.bitcoin.protocols.payments"/>
</Match>
<!-- dogecoinj is not designed to run in an environment with malicious code loaded into the VM -->
<Match>
<Bug category="MALICIOUS_CODE"/>
</Match>
<!-- Ignore serialization bugs for now, it's not a high priority anymore -->
<Match>
<Bug code="Se"/>
</Match>
<!-- This is flagging a valid issue but the real bug is in the JDK. See issue 173. -->
<Match>
<Bug pattern="LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE"/>
</Match>
<!-- The code is correct but findbugs can't analyze it properly -->
<Match>
<Bug code="SF"/>
<Class name="com.dogecoin.dogecoinj.core.BloomFilter"/>
</Match>
<!-- fb doesn't like the odd API this class has -->
<Match>
<Class name="~.*SendRequest.*"/>
</Match>
</FindBugsFilter>

View File

@ -1,462 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2012 Google Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.altcoinj</groupId>
<artifactId>altcoinj-parent</artifactId>
<version>0.13-SNAPSHOT</version>
</parent>
<artifactId>altcoinj-core</artifactId>
<name>altcoinj</name>
<description>Extension library to bitcoinj to add altcoin support</description>
<packaging>jar</packaging>
<url>https://altcoinj.github.io</url>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<!-- Dummy block to make Maven Central happy: authors list is in AUTHORS -->
<developers>
<developer>
<name>The altcoinj team</name>
<email>ross@dogecoin.com</email>
</developer>
</developers>
<profiles>
<profile>
<id>update-protobuf</id>
<activation>
<property>
<name>updateProtobuf</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>compile-protoc</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<path id="proto.path">
<fileset dir="src">
<include name="**/*.proto"/>
</fileset>
</path>
<pathconvert pathsep=" " property="proto.files" refid="proto.path"/>
<exec executable="protoc" failonerror="true">
<arg value="--java_out=${project.basedir}/src/main/java"/>
<arg value="-I${project.basedir}/src"/>
<arg line="${proto.files}"/>
</exec>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<!-- Ensure compilation is done under Java 6 for backwards compatibility -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<!-- Generate source and javadoc jars: Maven Central requires this -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<detectLinks/>
<links>
<link>http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/</link>
</links>
<detectJavaApiLink/>
<quiet>true</quiet>
</configuration>
</plugin>
<!-- Verify the dependency chain: see https://github.com/gary-rowe/BitcoinjEnforcerRules for
more information on this.
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce</id>
<phase>verify</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<DependencyConvergence/>
<digestRule implementation="uk.co.froot.maven.enforcer.DigestRule">
<!-- Create a snapshot to build the list of URNs below -->
<buildSnapshot>true</buildSnapshot>
<!-- List of required hashes -->
<!-- Format is URN of groupId:artifactId:version:type:classifier:scope:hash -->
<!-- classifier is "null" if not present -->
<urns>
<urn>cglib:cglib-nodep:2.2:jar:null:test:59afed7ab65e7ec6585d5bc60556c3cbd203532b</urn>
<urn>com.fasterxml.jackson.core:jackson-annotations:2.4.0:jar:null:test:d6a66c7a5f01cf500377bd669507a08cfeba882a</urn>
<urn>com.fasterxml.jackson.core:jackson-core:2.4.2:jar:null:test:ceb72830d95c512b4b300a38f29febc85bdf6e4b</urn>
<urn>com.fasterxml.jackson.core:jackson-databind:2.4.2:jar:null:test:8e31266a272ad25ac4c089734d93e8d811652c1f</urn>
<urn>com.google.code.findbugs:jsr305:2.0.1:jar:null:compile:516c03b21d50a644d538de0f0369c620989cd8f0</urn>
<urn>com.google.guava:guava:16.0.1:jar:null:compile:5fa98cd1a63c99a44dd8d3b77e4762b066a5d0c5</urn>
<urn>com.google.protobuf:protobuf-java:2.5.0:jar:null:compile:a10732c76bfacdbd633a7eb0f7968b1059a65dfa</urn>
<urn>com.h2database:h2:1.3.167:jar:null:compile:d3867d586f087e53eb12fc65e5693d8ee9a5da17</urn>
<urn>com.lambdaworks:scrypt:1.4.0:jar:null:compile:906506b74f30c8c20bccd9ed4a11112d8941fe87</urn>
<urn>com.madgag.spongycastle:core:1.51.0.0:jar:null:compile:0f642963312ea0e615ad65f28adc5a5b3a2a0862</urn>
<urn>junit:junit:4.11:jar:null:test:4e031bb61df09069aeb2bffb4019e7a5034a4ee0</urn>
<urn>mysql:mysql-connector-java:5.1.33:jar:null:compile:8af455a9a3267e6664cafc87ace71a4e4ef02837</urn>
<urn>net.jcip:jcip-annotations:1.0:jar:null:compile:afba4942caaeaf46aab0b976afd57cc7c181467e</urn>
<urn>org.apache.maven.plugins:maven-clean-plugin:2.6.1:maven-plugin:null:runtime:bfdf7d6c2f8fc8759457e9d54f458ba56ac7b30f</urn>
<urn>org.apache.maven.plugins:maven-compiler-plugin:3.2:maven-plugin:null:runtime:aec10f274ac07fafab8906cb1aa69669d753b2c2</urn>
<urn>org.apache.maven.plugins:maven-dependency-plugin:2.10:maven-plugin:null:runtime:af87ceeb71c6499147c5d27f74c9317bf707538e</urn>
<urn>org.apache.maven.plugins:maven-deploy-plugin:2.8.2:maven-plugin:null:runtime:3c2d83ecd387e9843142ae92a0439792c1500319</urn>
<urn>org.apache.maven.plugins:maven-enforcer-plugin:1.0:maven-plugin:null:runtime:ad032b7593576e9fe9305c73865633e163895b29</urn>
<urn>org.apache.maven.plugins:maven-install-plugin:2.5.2:maven-plugin:null:runtime:8a67631619fc3c1d1f036e59362ddce71e1e496f</urn>
<urn>org.apache.maven.plugins:maven-jar-plugin:2.6:maven-plugin:null:runtime:618f08d0fcdd3929af846ef1b65503b5904f93e3</urn>
<urn>org.apache.maven.plugins:maven-javadoc-plugin:2.10.2:maven-plugin:null:runtime:5f391697fa85cecc7e5bac7ce5a6f9d056a58ba3</urn>
<urn>org.apache.maven.plugins:maven-resources-plugin:2.7:maven-plugin:null:runtime:94af11389943a480ecec7db01b4ded1b9cdf57c5</urn>
<urn>org.apache.maven.plugins:maven-shade-plugin:2.3:maven-plugin:null:runtime:d136adc7abccc9c12adcad6ae7a9bc51b2b7184b</urn>
<urn>org.apache.maven.plugins:maven-site-plugin:3.4:maven-plugin:null:runtime:659cd5f1dd8bff554cf52603339494cbf7f283c5</urn>
<urn>org.apache.maven.plugins:maven-source-plugin:2.4:maven-plugin:null:runtime:46f0d7f7823d729ba300d3f8929900c7e9cb5ac0</urn>
<urn>org.apache.maven.plugins:maven-surefire-plugin:2.18.1:maven-plugin:null:runtime:402fd3066fd6d85ea4a1a3e7cd82a7e35037e6e8</urn>
<urn>org.easymock:easymock:3.0:jar:null:test:f28a4c31c330f95c9acbf1108cea19952b5c496f</urn>
<urn>org.eluder.coveralls:coveralls-maven-plugin:3.1.0:maven-plugin:null:runtime:ca9d2915e2b1e99f15c9f54ad653eda893d42a69</urn>
<urn>org.hamcrest:hamcrest-core:1.3:jar:null:test:42a25dc3219429f0e5d060061f71acb49bf010a0</urn>
<urn>org.jacoco:jacoco-maven-plugin:0.7.4.201502262128:maven-plugin:null:runtime:ee12ed04db135c74d0ae99e9c4e4754ee1582edb</urn>
<urn>org.objenesis:objenesis:1.2:jar:null:test:bfcb0539a071a4c5a30690388903ac48c0667f2a</urn>
<urn>org.slf4j:slf4j-api:1.7.6:jar:null:compile:562424e36df3d2327e8e9301a76027fca17d54ea</urn>
<urn>org.slf4j:slf4j-jdk14:1.7.6:jar:null:test:1a3301a32ea7d90c3d33e9d60edbfdc9589fc748</urn>
<urn>org.sonatype.plugins:nexus-staging-maven-plugin:1.6.5:maven-plugin:null:runtime:455ca2aa8cd14a06608f1538bd6a1efd09561563</urn>
<urn>postgresql:postgresql:9.1-901.jdbc4:jar:null:compile:153f2f92a786f12fc111d0111f709012df87c808</urn>
<!-- A check for the rules themselves -->
<urn>uk.co.froot.maven.enforcer:digest-enforcer-rules:0.0.1:jar:null:runtime:16a9e04f3fe4bb143c42782d07d5faf65b32106f</urn>
</urns>
</digestRule>
</rules>
</configuration>
</execution>
</executions>
<!-- Ensure we download the enforcer rules -->
<dependencies>
<dependency>
<groupId>uk.co.froot.maven.enforcer</groupId>
<artifactId>digest-enforcer-rules</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<!-- Create the bundled JAR, it's easier for some people -->
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>false</minimizeJar>
<filters>
<filter>
<!-- exclude signatures, the bundling process breaks them for some reason -->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>bundled</shadedClassifierName>
</configuration>
</execution>
</executions>
</plugin>
<!-- Code coverage plugin, generates coverage report to target/site/jacoco/
To skip coverage generation add -Djacoco.skip=true
-->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.4.201502262128</version>
<configuration>
<excludes>
<exclude>**/Protos*.class</exclude> <!-- Exclude generated protobuf classes -->
<exclude>org/bitcoinj/jni/*</exclude> <!-- Exclude JNI classes -->
<exclude>org/bitcoin/*</exclude> <!-- Exclude native classes -->
</excludes>
</configuration>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/coverage-reports/jacoco.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
</configuration>
</execution>
<execution>
<id>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Unit tests plugin, to skip runing test add -Dmaven.test.skip -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>${surefireArgLine}</argLine> <!-- This is required for code coverage to work. -->
<runOrder>alphabetical</runOrder>
</configuration>
</plugin>
<!-- Coveralls is a online code coverage tool, you can track code coverage here: https://coveralls.io/r/altcoinj/altcoinj -->
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- Create a bundled executable test jar that runs the regtester/pulltester.
The comparison tool is kind of messy and badly needs a seriously refactoring.
It depends on classes which are only in the test tree so we must do some
Maven kung fu here to create a bundle of it, as I couldn't make Maven Shade
do bundling on the test jar for some reason. Maven kind of sucks ...
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unzip-lib</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<artifactItems>
<artifactItem>
<outputDirectory>target/test-classes/</outputDirectory>
<groupId>org.altcoinj</groupId>
<artifactId>altcoinj-core</artifactId>
<version>${project.version}</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>unzip-deps</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<outputDirectory>target/test-classes/</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
<!-- altcoinj consumers are expected to provide their own SLF4J adapters
such as logback, slf4j-log4j12, slf4j-jcl and so on
see http://www.slf4j.org/faq.html -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.167</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.madgag.spongycastle</groupId>
<artifactId>core</artifactId>
<version>1.51.0.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0.1</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.lambdaworks</groupId>
<artifactId>scrypt</artifactId>
<version>1.4.0</version>
</dependency>
<!-- Note this is an optional dependency: Postgres blockstore -->
<!-- To Test remove optional -->
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901.jdbc4</version>
<optional>true</optional>
</dependency>
<!-- Note this is an optional dependency: MySQL blockstore -->
<!-- To Test remove optional -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.33</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.fusesource.leveldbjni</groupId>
<artifactId>leveldbjni-all</artifactId>
<version>1.8</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>orchid</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.13-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -1,106 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.altcoinj.params;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Utils;
import org.bitcoinj.utils.MonetaryFormat;
import static com.google.common.base.Preconditions.checkState;
/**
* Parameters for the main Dogecoin production network on which people trade goods and services.
*/
public class AbstractDogecoinParams extends NetworkParameters {
/** Standard format for the DOGE denomination. */
public static final MonetaryFormat DOGE;
/** Standard format for the mDOGE denomination. */
public static final MonetaryFormat MDOGE;
/** Standard format for the Koinu denomination. */
public static final MonetaryFormat KOINU;
public static final int DOGE_TARGET_TIMESPAN = 4 * 60 * 60; // 4 hours per difficulty cycle, on average.
public static final int DOGE_TARGET_TIMESPAN_NEW = 60; // 60s per difficulty cycle, on average. Kicks in after block 145k.
public static final int DOGE_TARGET_SPACING = 1 * 60; // 1 minute per block.
public static final int DOGE_INTERVAL = DOGE_TARGET_TIMESPAN / DOGE_TARGET_SPACING;
public static final int DOGE_INTERVAL_NEW = DOGE_TARGET_TIMESPAN_NEW / DOGE_TARGET_SPACING;
/** Currency code for base 1 Dogecoin. */
public static final String CODE_DOGE = "DOGE";
/** Currency code for base 1/1,000 Dogecoin. */
public static final String CODE_MDOGE = "mDOGE";
/** Currency code for base 1/100,000,000 Dogecoin. */
public static final String CODE_KOINU = "Koinu";
private static final Map<Integer, String> CURRENCY_CODES = new HashMap<Integer, String>();
static {
CURRENCY_CODES.put(0, CODE_DOGE);
CURRENCY_CODES.put(3, CODE_MDOGE);
CURRENCY_CODES.put(8, CODE_KOINU);
DOGE = MonetaryFormat.BTC.replaceCodes(CURRENCY_CODES);
MDOGE = DOGE.shift(3).minDecimals(2).optionalDecimals(2);
KOINU = DOGE.shift(6).minDecimals(0).optionalDecimals(2);
}
/** The string returned by getId() for the main, production network where people trade things. */
public static final String ID_DOGE_MAINNET = "org.dogecoin.production";
/** The string returned by getId() for the testnet. */
public static final String ID_DOGE_TESTNET = "org.dogecoin.test";
protected final int newInterval;
protected final int newTargetTimespan;
protected final int diffChangeTarget;
public AbstractDogecoinParams(final int setDiffChangeTarget) {
super();
interval = DOGE_INTERVAL;
newInterval = DOGE_INTERVAL_NEW;
targetTimespan = DOGE_TARGET_TIMESPAN;
newTargetTimespan = DOGE_TARGET_TIMESPAN_NEW;
maxTarget = Utils.decodeCompactBits(0x1e0fffffL);
diffChangeTarget = setDiffChangeTarget;
packetMagic = 0xc0c0c0c0;
bip32HeaderPub = 0x0488C42E; //The 4 byte header that serializes in base58 to "xpub". (?)
bip32HeaderPriv = 0x0488E1F4; //The 4 byte header that serializes in base58 to "xprv" (?)
}
/** How many blocks pass between difficulty adjustment periods. After new diff algo. */
public int getNewInterval() {
return newInterval;
}
/**
* How much time in seconds is supposed to pass between "interval" blocks. If the actual elapsed time is
* significantly different from this value, the network difficulty formula will produce a different value.
* Dogecoin after block 145k uses 60 seconds.
*/
public int getNewTargetTimespan() {
return newTargetTimespan;
}
public MonetaryFormat getMonetaryFormat() {
return DOGE;
}
}

260
pom.xml
View File

@ -1,220 +1,42 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.altcoinj</groupId>
<artifactId>altcoinj-parent</artifactId>
<version>0.13-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>core</module>
</modules>
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
</parent>
<scm>
<connection>scm:git:https://github.com/rnicoll/altcoinj</connection>
<developerConnection>scm:git:https://github.com/rnicoll/altcoinj</developerConnection>
<url>scm:git:https://github.com/rnicoll/altcoinj</url>
</scm>
<name>altcoinj Parent</name>
<description>Provides the common configuration for the AltcoinJ modules</description>
<url>https://github.com/rnicoll/altcoinj/</url>
<licenses>
<license>
<name>Apache 2</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
<distribution>repo</distribution>
<comments>A business-friendly OSS license</comments>
</license>
</licenses>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/rnicoll/altcoinj/issues</url>
</issueManagement>
<!-- Common build plugin configuration -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
</plugin>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.3</version>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.6</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.6</version>
</dependency>
<!-- altcoinj consumers are expected to provide their own SLF4J adapters
such as logback, slf4j-log4j12, slf4j-jcl and so on
see http://www.slf4j.org/faq.html -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.6</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Third-party dependencies -->
<easymock.version>3.0</easymock.version>
<junit.version>4.8.2</junit.version>
<generated.sourceDirectory>gen</generated.sourceDirectory>
</properties>
<profiles>
<profile>
<id>doclint-java8-disable</id>
<activation>
<jdk>[1.8,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.altcoinj</groupId>
<artifactId>altcoinj</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.13-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.lambdaworks</groupId>
<artifactId>scrypt</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
</project>

View File

@ -15,13 +15,11 @@
* limitations under the License.
*/
package org.bitcoinj.core;
package org.altcoinj.core;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.ByteArrayOutputStream;
@ -29,11 +27,15 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.security.GeneralSecurityException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.altcoinj.core.ScryptHash;
import static org.altcoinj.core.Utils.scryptDigest;
import static org.bitcoinj.core.Coin.FIFTY_COINS;
import static org.bitcoinj.core.Utils.doubleDigest;
import static org.bitcoinj.core.Utils.doubleDigestTwoBuffers;
@ -55,11 +57,13 @@ public class AltcoinBlock extends org.bitcoinj.core.Block {
private boolean auxpowParsed = false;
private boolean auxpowBytesValid = false;
/** AuxPoW header element, if applicable. */
@Nullable private AuxPoW auxpow;
/** AuxPoW header element, if applicable. */
@Nullable private AuxPoW auxpow;
private ScryptHash scryptHash;
/** Special case constructor, used for the genesis node, cloneAsHeader and unit tests. */
AltcoinBlock(NetworkParameters params) {
public AltcoinBlock(NetworkParameters params) {
super(params);
}
@ -123,18 +127,54 @@ public class AltcoinBlock extends org.bitcoinj.core.Block {
super(params, version, prevBlockHash, merkleRoot, time, difficultyTarget, nonce, transactions);
}
@Override
private ScryptHash calculateScryptHash() {
try {
ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(HEADER_SIZE);
writeHeader(bos);
return new ScryptHash(Utils.reverseBytes(scryptDigest(bos.toByteArray())));
} catch (IOException e) {
throw new RuntimeException(e); // Cannot happen.
} catch (GeneralSecurityException e) {
throw new RuntimeException(e); // Cannot happen.
}
}
public AuxPoW getAuxPoW() {
// TODO: maybeParseAuxPoW();
return this.auxpow;
}
/**
* Returns the Scrypt hash of the block (which for a valid, solved block should be
* below the target). Big endian.
*/
public ScryptHash getScryptHash() {
if (scryptHash == null)
scryptHash = calculateScryptHash();
return scryptHash;
}
/**
* Returns the Scrypt hash of the block.
*/
public String getScryptHashAsString() {
return getScryptHash().toString();
}
protected void parseAuxPoW() throws ProtocolException {
if (this.auxpowParsed)
return;
if (this.params.isAuxPoWBlockVersion(this.version)) {
// The following is used in dogecoinj, but I don't think we necessarily need it
// payload.length >= 160) { // We have at least 2 headers in an Aux block. Workaround for StoredBlocks
this.auxpow = new AuxPoW(params, payload, cursor, this, parseLazy, parseRetain);
} else {
this.auxpow = null;
}
this.auxpow = null;
if (this.params instanceof AuxPoWNetworkParameters) {
final AuxPoWNetworkParameters altcoinParams = (AuxPoWNetworkParameters)this.params;
if (altcoinParams.isAuxPoWBlockVersion(this.getVersion())) {
// The following is used in dogecoinj, but I don't think we necessarily need it
// payload.length >= 160) { // We have at least 2 headers in an Aux block. Workaround for StoredBlocks
this.auxpow = new AuxPoW(params, payload, cursor, this, parseLazy, parseRetain);
optimalEncodingMessageSize += auxpow.getOptimalEncodingMessageSize();
}
}
this.auxpowParsed = true;
this.auxpowBytesValid = parseRetain;
@ -148,6 +188,15 @@ public class AltcoinBlock extends org.bitcoinj.core.Block {
length = cursor - offset;
}
@Override
protected void parseTransactions() {
if (null != this.auxpow) {
parseTransactions(HEADER_SIZE + auxpow.getMessageSize());
} else {
parseTransactions(HEADER_SIZE);
}
}
@Override
protected void parseLite() throws ProtocolException {
// Ignore the header since it has fixed length. If length is not provided we will have to
@ -156,8 +205,8 @@ public class AltcoinBlock extends org.bitcoinj.core.Block {
Preconditions.checkState(parseLazy,
"Performing lite parse of block transaction as block was initialised from byte array " +
"without providing length. This should never need to happen.");
parseAuxPoW();
parseTransactions();
// TODO: Handle AuxPoW header space
length = cursor - offset;
} else {
transactionBytesValid = !transactionsParsed || parseRetain && length > HEADER_SIZE;

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
package org.bitcoinj.core;
package org.altcoinj.core;
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.script.Script;
@ -126,8 +126,8 @@ public class AuxPoW extends ChildMessage implements Serializable {
return;
cursor = offset;
transaction = new Transaction(params, payload, cursor, this, parseLazy, parseRetain, Message.UNKNOWN_LENGTH);
cursor += transaction.getOptimalEncodingMessageSize();
transaction = new Transaction(params, payload, cursor, this, parseLazy, parseRetain, Message.UNKNOWN_LENGTH);
cursor += transaction.getOptimalEncodingMessageSize();
optimalEncodingMessageSize = transaction.getOptimalEncodingMessageSize();
hashBlock = readHash();

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.bitcoinj.core;
package org.altcoinj.core;
import static org.bitcoinj.core.Utils.doubleDigestTwoBuffers;
import static org.bitcoinj.core.Utils.reverseBytes;
@ -88,14 +88,14 @@ public class MerkleBranch extends ChildMessage implements Serializable {
super(params);
setParent(parent);
this.branchHashes = hashes;
this.branchSideMask = branchSideMask;
this.branchHashes = hashes;
this.branchSideMask = branchSideMask;
}
@Override
protected void parseLite() throws ProtocolException {
length = calcLength(payload, offset);
cursor = offset + length;
length = calcLength(payload, offset);
cursor = offset + length;
}
protected static int calcLength(byte[] buf, int offset) {
@ -113,10 +113,10 @@ public class MerkleBranch extends ChildMessage implements Serializable {
final int hashCount = (int) readVarInt();
optimalEncodingMessageSize += VarInt.sizeOf(hashCount);
branchHashes = new ArrayList<Sha256Hash>(hashCount);
for (int hashIdx = 0; hashIdx < hashCount; hashIdx++) {
branchHashes.add(readHash());
}
branchHashes = new ArrayList<Sha256Hash>(hashCount);
for (int hashIdx = 0; hashIdx < hashCount; hashIdx++) {
branchHashes.add(readHash());
}
optimalEncodingMessageSize += 32 * hashCount;
branchSideMask = readUint32();
optimalEncodingMessageSize += 4;
@ -125,9 +125,9 @@ public class MerkleBranch extends ChildMessage implements Serializable {
@Override
protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
stream.write(new VarInt(branchHashes.size()).encode());
for (Sha256Hash hash: branchHashes) {
stream.write(Utils.reverseBytes(hash.getBytes()));
}
for (Sha256Hash hash: branchHashes) {
stream.write(Utils.reverseBytes(hash.getBytes()));
}
Utils.uint32ToByteStreamLE(branchSideMask, stream);
}

View File

@ -0,0 +1,34 @@
/**
* Copyright 2015 Ross Nicoll
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.altcoinj.core;
import org.bitcoinj.core.Sha256Hash;
/**
* Scrypt hash. Currently extends Sha256Hash (so no real type safety is provided),
* but in time the two classes should have a common superclass rather than one
* extending the other directly.
*/
public class ScryptHash extends Sha256Hash {
public ScryptHash(byte[] rawHashBytes) {
super(rawHashBytes);
}
public ScryptHash(String hexString) {
super(hexString);
}
}

View File

@ -0,0 +1,33 @@
/**
* Copyright 2011 Google Inc.
* Copyright 2014 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.altcoinj.core;
import com.lambdaworks.crypto.SCrypt;
import java.security.GeneralSecurityException;
/**
*
*/
public class Utils {
/**
* Calculates the Scrypt hash of the given byte range.
* The resulting hash is in small endian form.
*/
public static byte[] scryptDigest(byte[] input) throws GeneralSecurityException {
return SCrypt.scrypt(input, input, 1024, 1, 1, 32);
}
}

View File

@ -0,0 +1,288 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.altcoinj.params;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import org.bitcoinj.core.AltcoinBlock;
import org.bitcoinj.core.AuxPoWNetworkParameters;
import org.bitcoinj.core.Block;
import org.bitcoinj.core.Coin;
import static org.bitcoinj.core.Coin.COIN;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Utils;
import org.bitcoinj.core.VerificationException;
import org.bitcoinj.script.Script;
import org.bitcoinj.script.ScriptOpCodes;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.utils.MonetaryFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkState;
/**
* Parameters for the main Dogecoin production network on which people trade goods and services.
*/
public class AbstractDogecoinParams extends NetworkParameters {
/** Standard format for the DOGE denomination. */
public static final MonetaryFormat DOGE;
/** Standard format for the mDOGE denomination. */
public static final MonetaryFormat MDOGE;
/** Standard format for the Koinu denomination. */
public static final MonetaryFormat KOINU;
public static final int DIGISHIELD_BLOCK_HEIGHT = 145000; // Block height to use Digishield from
public static final int DOGE_TARGET_TIMESPAN = 4 * 60 * 60; // 4 hours per difficulty cycle, on average.
public static final int DOGE_TARGET_TIMESPAN_NEW = 60; // 60s per difficulty cycle, on average. Kicks in after block 145k.
public static final int DOGE_TARGET_SPACING = 1 * 60; // 1 minute per block.
public static final int DOGE_INTERVAL = DOGE_TARGET_TIMESPAN / DOGE_TARGET_SPACING;
public static final int DOGE_INTERVAL_NEW = DOGE_TARGET_TIMESPAN_NEW / DOGE_TARGET_SPACING;
/** Currency code for base 1 Dogecoin. */
public static final String CODE_DOGE = "DOGE";
/** Currency code for base 1/1,000 Dogecoin. */
public static final String CODE_MDOGE = "mDOGE";
/** Currency code for base 1/100,000,000 Dogecoin. */
public static final String CODE_KOINU = "Koinu";
public static final int BLOCK_VERSION_DEFAULT = 0x00000002;
public static final int BLOCK_VERSION_AUXPOW = 0x00620002;
public static final int BLOCK_VERSION_FLAG_AUXPOW = 0x00000100;
static {
DOGE = MonetaryFormat.BTC.noCode()
.code(0, CODE_DOGE)
.code(3, CODE_MDOGE)
.code(7, CODE_KOINU);
MDOGE = DOGE.shift(3).minDecimals(2).optionalDecimals(2);
KOINU = DOGE.shift(7).minDecimals(0).optionalDecimals(2);
}
/** The string returned by getId() for the main, production network where people trade things. */
public static final String ID_DOGE_MAINNET = "org.dogecoin.production";
/** The string returned by getId() for the testnet. */
public static final String ID_DOGE_TESTNET = "org.dogecoin.test";
protected final int newInterval;
protected final int newTargetTimespan;
protected final int diffChangeTarget;
protected Logger log = LoggerFactory.getLogger(AbstractDogecoinParams.class);
public AbstractDogecoinParams(final int setDiffChangeTarget) {
super();
genesisBlock = createGenesis(this);
interval = DOGE_INTERVAL;
newInterval = DOGE_INTERVAL_NEW;
targetTimespan = DOGE_TARGET_TIMESPAN;
newTargetTimespan = DOGE_TARGET_TIMESPAN_NEW;
maxTarget = Utils.decodeCompactBits(0x1e0fffffL);
diffChangeTarget = setDiffChangeTarget;
packetMagic = 0xc0c0c0c0;
bip32HeaderPub = 0x0488C42E; //The 4 byte header that serializes in base58 to "xpub". (?)
bip32HeaderPriv = 0x0488E1F4; //The 4 byte header that serializes in base58 to "xprv" (?)
}
private static AltcoinBlock createGenesis(NetworkParameters params) {
AltcoinBlock genesisBlock = new AltcoinBlock(params);
Transaction t = new Transaction(params);
try {
byte[] bytes = Utils.HEX.decode
("04ffff001d0104084e696e746f6e646f");
t.addInput(new TransactionInput(params, t, bytes));
ByteArrayOutputStream scriptPubKeyBytes = new ByteArrayOutputStream();
Script.writeBytes(scriptPubKeyBytes, Utils.HEX.decode
("040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9"));
scriptPubKeyBytes.write(ScriptOpCodes.OP_CHECKSIG);
t.addOutput(new TransactionOutput(params, t, COIN.multiply(88), scriptPubKeyBytes.toByteArray()));
} catch (Exception e) {
// Cannot happen.
throw new RuntimeException(e);
}
genesisBlock.addTransaction(t);
return genesisBlock;
}
/** How many blocks pass between difficulty adjustment periods. After new diff algo. */
public int getNewInterval() {
return newInterval;
}
/**
* How much time in seconds is supposed to pass between "interval" blocks. If the actual elapsed time is
* significantly different from this value, the network difficulty formula will produce a different value.
* Dogecoin after block 145k uses 60 seconds.
*/
public int getNewTargetTimespan() {
return newTargetTimespan;
}
public MonetaryFormat getMonetaryFormat() {
return DOGE;
}
@Override
public Coin getMaxMoney() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Coin getMinNonDustOutput() {
return Coin.COIN;
}
@Override
public String getUriScheme() {
return "dogecoin";
}
@Override
public boolean hasMaxMoney() {
return false;
}
@Override
public void checkDifficultyTransitions(StoredBlock storedPrev, Block nextBlock, BlockStore blockStore)
throws VerificationException, BlockStoreException {
final Block prev = storedPrev.getHeader();
final int previousHeight = storedPrev.getHeight();
final boolean digishieldAlgorithm = previousHeight + 1 >= this.getDigishieldBlockHeight();
final int retargetInterval = digishieldAlgorithm
? this.getInterval()
: this.getNewInterval();
// Is this supposed to be a difficulty transition point?
if ((storedPrev.getHeight() + 1) % retargetInterval != 0) {
// No ... so check the difficulty didn't actually change.
if (nextBlock.getDifficultyTarget() != prev.getDifficultyTarget())
throw new VerificationException("Unexpected change in difficulty at height " + storedPrev.getHeight() +
": " + Long.toHexString(nextBlock.getDifficultyTarget()) + " vs " +
Long.toHexString(prev.getDifficultyTarget()));
return;
}
// We need to find a block far back in the chain. It's OK that this is expensive because it only occurs every
// two weeks after the initial block chain download.
StoredBlock cursor = blockStore.get(prev.getHash());
int goBack = retargetInterval - 1;
if (cursor.getHeight()+1 != retargetInterval)
goBack = retargetInterval;
for (int i = 0; i < goBack; i++) {
if (cursor == null) {
// This should never happen. If it does, it means we are following an incorrect or busted chain.
throw new VerificationException(
"Difficulty transition point but we did not find a way back to the genesis block.");
}
cursor = blockStore.get(cursor.getHeader().getPrevBlockHash());
}
//We used checkpoints...
if (cursor == null) {
log.debug("Difficulty transition: Hit checkpoint!");
return;
}
Block blockIntervalAgo = cursor.getHeader();
long receivedTargetCompact = nextBlock.getDifficultyTarget();
long newTargetCompact = this.getNewDifficultyTarget(previousHeight, prev.getTimeSeconds(),
receivedTargetCompact, blockIntervalAgo.getTimeSeconds());
if (newTargetCompact != receivedTargetCompact)
throw new VerificationException("Network provided difficulty bits do not match what was calculated: " +
newTargetCompact + " vs " + receivedTargetCompact);
}
/**
*
* @param previousHeight Height of the block immediately previous to the one we're calculating difficulty of.
* @param previousBlockTime Time of the block immediately previous to the one we're calculating difficulty of.
* @param lastDifficultyTarget Compact difficulty target of the last retarget block.
* @param lastRetargetTime Time of the last difficulty retarget.
* @return New difficulty target as compact bytes.
*/
protected long getNewDifficultyTarget(int previousHeight, long previousBlockTime,
final long lastDifficultyTarget, final long lastRetargetTime) {
final int height = previousHeight + 1;
final boolean digishieldAlgorithm = height >= this.getDigishieldBlockHeight();
final int retargetTimespan = digishieldAlgorithm
? this.getNewTargetTimespan()
: this.getTargetTimespan();
int actualTime = (int) (previousBlockTime - lastRetargetTime);
final int minTimespan;
final int maxTimespan;
// Limit the adjustment step.
if (digishieldAlgorithm)
{
// Round towards zero to match the C++ implementation.
if (actualTime < retargetTimespan) {
actualTime = (int)Math.ceil(retargetTimespan + (actualTime - retargetTimespan) / 8.0);
} else {
actualTime = (int)Math.floor(retargetTimespan + (actualTime - retargetTimespan) / 8.0);
}
minTimespan = retargetTimespan - (retargetTimespan / 4);
maxTimespan = retargetTimespan + (retargetTimespan / 2);
}
else if (height > 10000)
{
minTimespan = retargetTimespan / 4;
maxTimespan = retargetTimespan * 4;
}
else if (height > 5000)
{
minTimespan = retargetTimespan / 8;
maxTimespan = retargetTimespan * 4;
}
else
{
minTimespan = retargetTimespan / 16;
maxTimespan = retargetTimespan * 4;
}
actualTime = Math.min(maxTimespan, Math.max(minTimespan, actualTime));
BigInteger newTarget = Utils.decodeCompactBits(lastDifficultyTarget);
newTarget = newTarget.multiply(BigInteger.valueOf(actualTime));
newTarget = newTarget.divide(BigInteger.valueOf(retargetTimespan));
if (newTarget.compareTo(this.getMaxTarget()) > 0) {
log.info("Difficulty hit proof of work limit: {}", newTarget.toString(16));
newTarget = this.getMaxTarget();
}
int accuracyBytes = (int) (lastDifficultyTarget >>> 24) - 3;
// The calculated difficulty is to a higher precision than received, so reduce here.
BigInteger mask = BigInteger.valueOf(0xFFFFFFL).shiftLeft(accuracyBytes * 8);
newTarget = newTarget.and(mask);
return Utils.encodeCompactBits(newTarget);
}
/**
* Get the block height from which the Digishield difficulty calculation
* algorithm is used.
*/
public int getDigishieldBlockHeight() {
return DIGISHIELD_BLOCK_HEIGHT;
}
}

View File

@ -16,12 +16,8 @@
package org.altcoinj.params;
import java.util.Map;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Utils;
import org.bitcoinj.utils.MonetaryFormat;
import org.altcoinj.core.ScryptHash;
import org.bitcoinj.core.AltcoinBlock;
import static com.google.common.base.Preconditions.checkState;
@ -48,6 +44,8 @@ public class DogecoinMainNetParams extends AbstractDogecoinParams {
subsidyDecreaseBlockCount = 100000;
spendableCoinbaseDepth = 100;
// Note this is an SHA256 hash, not a Scrypt hash. Scrypt hashes are only
// used in difficulty calculations.
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691"),
genesisHash);
@ -56,25 +54,25 @@ public class DogecoinMainNetParams extends AbstractDogecoinParams {
// transactions are handled. Duplicated transactions could occur in the case where a coinbase had the same
// extraNonce and the same outputs but appeared at different heights, and greatly complicated re-org handling.
// Having these here simplifies block connection logic considerably.
checkpoints.put( 0, new Sha256Hash("1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691"));
checkpoints.put( 42279, new Sha256Hash("8444c3ef39a46222e87584ef956ad2c9ef401578bd8b51e8e4b9a86ec3134d3a"));
checkpoints.put( 42400, new Sha256Hash("557bb7c17ed9e6d4a6f9361cfddf7c1fc0bdc394af7019167442b41f507252b4"));
checkpoints.put(104679, new Sha256Hash("35eb87ae90d44b98898fec8c39577b76cb1eb08e1261cfc10706c8ce9a1d01cf"));
checkpoints.put(128370, new Sha256Hash("3f9265c94cab7dc3bd6a2ad2fb26c8845cb41cff437e0a75ae006997b4974be6"));
checkpoints.put(145000, new Sha256Hash("cc47cae70d7c5c92828d3214a266331dde59087d4a39071fa76ddfff9b7bde72"));
checkpoints.put(165393, new Sha256Hash("7154efb4009e18c1c6a6a79fc6015f48502bcd0a1edd9c20e44cd7cbbe2eeef1"));
checkpoints.put(186774, new Sha256Hash("3c712c49b34a5f34d4b963750d6ba02b73e8a938d2ee415dcda141d89f5cb23a"));
checkpoints.put(199992, new Sha256Hash("3408ff829b7104eebaf61fd2ba2203ef2a43af38b95b353e992ef48f00ebb190"));
checkpoints.put(225000, new Sha256Hash("be148d9c5eab4a33392a6367198796784479720d06bfdd07bd547fe934eea15a"));
checkpoints.put(250000, new Sha256Hash("0e4bcfe8d970979f7e30e2809ab51908d435677998cf759169407824d4f36460"));
checkpoints.put(270639, new Sha256Hash("c587a36dd4f60725b9dd01d99694799bef111fc584d659f6756ab06d2a90d911"));
checkpoints.put(299742, new Sha256Hash("1cc89c0c8a58046bf0222fe131c099852bd9af25a80e07922918ef5fb39d6742"));
checkpoints.put(323141, new Sha256Hash("60c9f919f9b271add6ef5671e9538bad296d79f7fdc6487ba702bf2ba131d31d"));
checkpoints.put(339202, new Sha256Hash("8c29048df5ae9df38a67ea9470fdd404d281a3a5c6f33080cd5bf14aa496ab03"));
checkpoints.put(350000, new Sha256Hash("2bdcba23a47049e69c4fec4c425462e30f3d21d25223bde0ed36be4ea59a7075"));
checkpoints.put(370005, new Sha256Hash("7be5af2c5bdcb79047dcd691ef613b82d4f1c20835677daed936de37a4782e15"));
checkpoints.put(371337, new Sha256Hash("60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053"));
checkpoints.put(400002, new Sha256Hash("a5021d69a83f39aef10f3f24f932068d6ff322c654d20562def3fac5703ce3aa"));
checkpoints.put( 0, new ScryptHash("1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691"));
checkpoints.put( 42279, new ScryptHash("8444c3ef39a46222e87584ef956ad2c9ef401578bd8b51e8e4b9a86ec3134d3a"));
checkpoints.put( 42400, new ScryptHash("557bb7c17ed9e6d4a6f9361cfddf7c1fc0bdc394af7019167442b41f507252b4"));
checkpoints.put(104679, new ScryptHash("35eb87ae90d44b98898fec8c39577b76cb1eb08e1261cfc10706c8ce9a1d01cf"));
checkpoints.put(128370, new ScryptHash("3f9265c94cab7dc3bd6a2ad2fb26c8845cb41cff437e0a75ae006997b4974be6"));
checkpoints.put(145000, new ScryptHash("cc47cae70d7c5c92828d3214a266331dde59087d4a39071fa76ddfff9b7bde72"));
checkpoints.put(165393, new ScryptHash("7154efb4009e18c1c6a6a79fc6015f48502bcd0a1edd9c20e44cd7cbbe2eeef1"));
checkpoints.put(186774, new ScryptHash("3c712c49b34a5f34d4b963750d6ba02b73e8a938d2ee415dcda141d89f5cb23a"));
checkpoints.put(199992, new ScryptHash("3408ff829b7104eebaf61fd2ba2203ef2a43af38b95b353e992ef48f00ebb190"));
checkpoints.put(225000, new ScryptHash("be148d9c5eab4a33392a6367198796784479720d06bfdd07bd547fe934eea15a"));
checkpoints.put(250000, new ScryptHash("0e4bcfe8d970979f7e30e2809ab51908d435677998cf759169407824d4f36460"));
checkpoints.put(270639, new ScryptHash("c587a36dd4f60725b9dd01d99694799bef111fc584d659f6756ab06d2a90d911"));
checkpoints.put(299742, new ScryptHash("1cc89c0c8a58046bf0222fe131c099852bd9af25a80e07922918ef5fb39d6742"));
checkpoints.put(323141, new ScryptHash("60c9f919f9b271add6ef5671e9538bad296d79f7fdc6487ba702bf2ba131d31d"));
checkpoints.put(339202, new ScryptHash("8c29048df5ae9df38a67ea9470fdd404d281a3a5c6f33080cd5bf14aa496ab03"));
checkpoints.put(350000, new ScryptHash("2bdcba23a47049e69c4fec4c425462e30f3d21d25223bde0ed36be4ea59a7075"));
checkpoints.put(370005, new ScryptHash("7be5af2c5bdcb79047dcd691ef613b82d4f1c20835677daed936de37a4782e15"));
checkpoints.put(371337, new ScryptHash("60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053"));
checkpoints.put(400002, new ScryptHash("a5021d69a83f39aef10f3f24f932068d6ff322c654d20562def3fac5703ce3aa"));
dnsSeeds = new String[] {
"seed.dogecoin.com",
@ -94,6 +92,12 @@ public class DogecoinMainNetParams extends AbstractDogecoinParams {
@Override
public String getPaymentProtocolId() {
// TODO: CHANGE THIS
return PAYMENT_PROTOCOL_ID_MAINNET;
return ID_DOGE_MAINNET;
}
@Override
public boolean isAuxPoWBlockVersion(long version) {
return version >= BLOCK_VERSION_AUXPOW
&& (version & BLOCK_VERSION_FLAG_AUXPOW) > 0;
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2015 J. Ross Nicoll
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.altcoinj.params;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
*
* @author jrn
*/
public class AbstractDogecoinParamsTest {
private static final AbstractDogecoinParams params = DogecoinMainNetParams.get();
@Test
public void shouldCalculateBitcoinLikeDifficulty() {
int previousHeight = 239;
long previousBlockTime = 1386475638; // Block 239
long lastRetargetDifficulty = 0x1e0ffff0;
long lastRetargetTime = 1386474927; // Block 1
long newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
assertEquals(newDifficulty, 0x1e00ffff);
previousHeight = 479;
previousBlockTime = 1386475840;
lastRetargetDifficulty = 0x1e0fffff;
lastRetargetTime = 1386475638; // Block 239
newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
assertEquals(newDifficulty, 0x1e00ffff);
previousHeight = 9599;
previousBlockTime = 1386954113;
lastRetargetDifficulty = 0x1c1a1206;
lastRetargetTime = 1386942008; // Block 9359
newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
assertEquals(newDifficulty, 0x1c15ea59);
}
@Test
public void shouldCalculateDigishieldDifficulty() {
int previousHeight = 145000;
long previousBlockTime = 1395094679;
long lastRetargetDifficulty = 0x1b499dfd;
long lastRetargetTime = 1395094427;
long newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
assertEquals(newDifficulty, 0x1b671062);
}
@Test
public void shouldCalculateDigishieldDifficultyRounding() {
// Test case for correct rounding of modulated time
int previousHeight = 145001;
long previousBlockTime = 1395094727;
long lastRetargetDifficulty = 0x1b671062;
long lastRetargetTime = 1395094679;
long newDifficulty = params.getNewDifficultyTarget(previousHeight, previousBlockTime, lastRetargetDifficulty, lastRetargetTime);
assertEquals(newDifficulty, 0x1b6558a4);
}
}

View File

@ -0,0 +1,92 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.bitcoinj.core;
import java.io.IOException;
import org.altcoinj.params.DogecoinMainNetParams;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
/**
*
* @author jrn
*/
public class DogecoinBlockTest {
private final NetworkParameters params = DogecoinMainNetParams.get();
@Before
public void setUp() throws Exception {
Context context = new Context(params);
}
@Test
public void shouldParseBlock1() throws IOException {
byte[] payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block1.bin"));
final AltcoinBlock block = new AltcoinBlock(params, payload);
assertEquals("82bc68038f6034c0596b6e313729793a887fded6e92a31fbdf70863f89d9bea2", block.getHashAsString());
assertEquals(1, block.getTransactions().size());
}
/**
* Test the first hardfork block.
* @throws IOException
*/
@Test
public void shouldParseBlock250000() throws IOException {
byte[] payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block250000.bin"));
final AltcoinBlock block = new AltcoinBlock(params, payload);
assertEquals(2469341065L, block.getNonce());
final AuxPoW auxpow = block.getAuxPoW();
assertNull(auxpow);
assertEquals(6, block.getTransactions().size());
assertEquals("0e4bcfe8d970979f7e30e2809ab51908d435677998cf759169407824d4f36460", block.getHashAsString());
}
/**
* Confirm parsing of the first merged-mine block.
*
* @throws IOException
*/
@Test
public void shouldParseBlock371337() throws IOException {
byte[] payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block371337.bin"));
final AltcoinBlock block = new AltcoinBlock(params, payload);
assertEquals("60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053", block.getHashAsString());
assertEquals(0, block.getNonce());
final AuxPoW auxpow = block.getAuxPoW();
assertNotNull(auxpow);
final Transaction auxpowCoinbase = auxpow.getCoinbase();
assertEquals("e5422732b20e9e7ecc243427abbe296e9528d308bb111aae8d30c3465e442de8", auxpowCoinbase.getHashAsString());
final Block parentBlock = auxpow.getParentBlockHeader();
assertEquals("45df41e40aba5b2a03d08bd1202a1c02ef3954d8aa22ea6c5ae62fd00f290ea9", parentBlock.getHashAsString());
assertNull(parentBlock.getTransactions());
final MerkleBranch blockchainMerkleBranch = auxpow.getBlockchainBranch();
Sha256Hash[] expected = new Sha256Hash[] {
new Sha256Hash("b541c848bc001d07d2bdf8643abab61d2c6ae50d5b2495815339a4b30703a46f"),
new Sha256Hash("78d6abe48cee514cf3496f4042039acb7e27616dcfc5de926ff0d6c7e5987be7"),
new Sha256Hash("a0469413ce64d67c43902d54ee3a380eff12ded22ca11cbd3842e15d48298103")
};
assertArrayEquals(expected, blockchainMerkleBranch.getHashes().toArray(new Sha256Hash[blockchainMerkleBranch.getSize()]));
final MerkleBranch coinbaseMerkleBranch = auxpow.getCoinbaseBranch();
expected = new Sha256Hash[] {
new Sha256Hash("cd3947cd5a0c26fde01b05a3aa3d7a38717be6ae11d27239365024db36a679a9"),
new Sha256Hash("48f9e8fef3411944e27f49ec804462c9e124dca0954c71c8560e8a9dd218a452"),
new Sha256Hash("d11293660392e7c51f69477a6130237c72ecee2d0c1d3dc815841734c370331a")
};
assertArrayEquals(expected, coinbaseMerkleBranch.getHashes().toArray(new Sha256Hash[coinbaseMerkleBranch.getSize()]));
System.out.println(block.toString());
assertEquals(6, block.getTransactions().size());
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
020162000d6f03470d329026cd1fc720c0609cd378ca8691a117bd1aa46f01fb09b1a8468a15bf6f0b0e83f2e5036684169eafb9406468d4f075c999fb5b2a78fbb827ee41fb11548441361b0000000001000000010000000000000000000000000000000000000000000000000000000000000000ffffffff380345bf09fabe6d6d980ba42120410de0554d42a5b5ee58167bcd86bf7591f429005f24da45fb51cf0800000000000000cdb1f1ff0e000000ffffffff01800c0c2a010000001976a914aa3750aa18b8a0f3f0590731e1fab934856680cf88ac00000000b3e64e02fff596209c498f1b18f798d62f216f11c8462bf3922319000000000003a979a636db2450363972d211aee67b71387a3daaa3051be0fd260c5acd4739cd52a418d29d8a0e56c8714c95a0dc24e1c9624480ec497fe2441941f3fee8f9481a3370c334178415c83d1d0c2deeec727c2330617a47691fc5e79203669312d100000000036fa40307b3a439538195245b0de56a2c1db6ba3a64f8bdd2071d00bc48c841b5e77b98e5c7d6f06f92dec5cf6d61277ecb9a0342406f49f34c51ee8ce4abd678038129485de14238bd1ca12cd2de12ff0e383aee542d90437cd664ce139446a00000000002000000d2ec7dfeb7e8f43fe77aba3368df95ac2088034420402730ee0492a2084217083411b3fc91033bfdeea339bc11b9efc986e161c703e07a9045338c165673f09940fb11548b54021b58cc9ae50601000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0d0389aa050101062f503253482fffffffff010066f33caf050000232102b73438165461b826b30a46078f211aa005d1e7e430b1e0ed461678a5fe516c73ac000000000100000001ef2e86aa5f027e13d7fc1f0bd4a1fc677d698e42850680634ccd1834668ff320010000006b483045022100fcf5dc43afa85978a71e76a9f4c11cd6bf2a7d5677212f9001ad085d420a5d3a022068982e1e53e94fc6007cf8b60ff3919bcaf7f0b70fefb79112cb840777d8c7cf0121022b050b740dd02c1b4e1e7cdbffe6d836d987c9db4c4db734b58526f08942193bffffffff02004e7253000000001976a91435cb1f77e88e96fb3094d84e8d3b7789a092636d88ac00d4b7e8b00700001976a9146ca1f634daa4efc7871abab945c7cefd282b481f88ac0000000001000000010a6c24bbc92fd0ec32bb5b0a051c44eba0c1325f0b24d9523c109f8bb1281f49000000006a4730440220608577619fb3a0b826f09df5663ffbf121c8e0164f43b73d9affe2f9e4576bd0022040782c9a7df0a20afe1a7e3578bf27e1331c862253af21ced4fde5ef1b44b787012103e4f91ad831a87cc532249944bc7138a355f7d0aac25dc4737a8701181ce680a5ffffffff010019813f0d0000001976a91481db1aa49ebc6a71cad96949eb28e22af85eb0bd88ac0000000001000000017b82db0f644ecff378217d9b8dc0de8817eaf85ceefacab23bf344e2e495dca5010000006b483045022100f07ced6bfdbd6cdeb8b2c8fc92b9803f5798754b5b6c454c8f084198bea303f402205616f84d7ec882af9c34a3fd2457ca3fb81ec5a463a963a6e684edee427d4525012102c056b10494520dbd7b37e2e6bb8f72f98d73a609a926901221bfb114fa1d5a80ffffffff02f0501a22000000001976a914ca63ded8b23d0252158a3bdc816747ef89fb438988ac80b65ea1350700001976a914fb26a7c16ace531a8e7bbd925e46c67c3150c1c888ac000000000100000001c9bdba900e1579ebf4e44415fe8b9abec57a763f8c70a30604bea7fbe7c55d42000000006a47304402204ccbeeace0630e72102fdaf0836e41f8f6dcdde6a178f0fbc2d96a4d17a1df8f02207e4a91203a2abd87fdddee96510482ef96535741b6c17a1acae93c977ad248e5012103e0747583a342b76a5de9c21db138b9640d49b4f3b67a306d3b3f217416d49b55ffffffff020058850c020000001976a9144417c63a91208a02a5f46a0f7a2b806adc7d19a788ac0042dc06030000001976a9147b61c5adef0d559e5acf2901c2989294624b651988ac0000000001000000017c1423b198dfc3da37ae9a5fc11a3720e4343b3049d3b289b8285eb04595c04b000000006b483045022100b0c1cb9608bf644d7a8916bf61f36ced95bd045e97612804ca774f60e05e7bde022017c12255eecc474c8d8b05d0910013b2df8703af68212cf0962b6b8ee0e101ee01210341e154088c23b8ea943bca94c1d4f65361668a242b168522f00199365414b46affffffff01019891ad000000001976a91481db1aa49ebc6a71cad96949eb28e22af85eb0bd88ac00000000