mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-14 11:15:51 +00:00
Add getters/setters and a solve method to the Block object. Use this in a new proof of work unit test.
Introduce a unit test NetworkParameters that has very easy difficulty. Correct some assertTrue(false) type checks to use fail() instead. Make ALLOWED_TIME_DRIFT non-public until I have a good explanation in the javadocs of what it's for. Simplify Block.equals
This commit is contained in:
parent
38bf9a8a80
commit
4003eee3fe
@ -73,9 +73,9 @@ function windowTitle()
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
|
||||
SUMMARY: NESTED | <A HREF="#field_summary">FIELD</A> | <A HREF="#constructor_summary">CONSTR</A> | <A HREF="#method_summary">METHOD</A></FONT></TD>
|
||||
SUMMARY: NESTED | <A HREF="#fields_inherited_from_class_com.google.bitcoin.core.Message">FIELD</A> | <A HREF="#constructor_summary">CONSTR</A> | <A HREF="#method_summary">METHOD</A></FONT></TD>
|
||||
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
|
||||
DETAIL: <A HREF="#field_detail">FIELD</A> | <A HREF="#constructor_detail">CONSTR</A> | <A HREF="#method_detail">METHOD</A></FONT></TD>
|
||||
DETAIL: FIELD | <A HREF="#constructor_detail">CONSTR</A> | <A HREF="#method_detail">METHOD</A></FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<A NAME="skip-navbar_top"></A>
|
||||
@ -124,14 +124,6 @@ A block is the foundation of the BitCoin system. It records a set of <A HREF="..
|
||||
<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
|
||||
<B>Field Summary</B></FONT></TH>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE>static long</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#ALLOWED_TIME_DRIFT">ALLOWED_TIME_DRIFT</A></B></CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<A NAME="fields_inherited_from_class_com.google.bitcoin.core.Message"><!-- --></A>
|
||||
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
|
||||
@ -186,6 +178,22 @@ A block is the foundation of the BitCoin system. It records a set of <A HREF="..
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> long</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getDifficultyTarget()">getDifficultyTarget</A></B>()</CODE>
|
||||
|
||||
<BR>
|
||||
Returns the difficulty of the proof of work that this block should meet encoded in compact form.</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> java.math.BigInteger</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getDifficultyTargetBI()">getDifficultyTargetBI</A></B>()</CODE>
|
||||
|
||||
<BR>
|
||||
Returns the difficulty target as a 256 bit value that can be compared to a SHA-256 hash.</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> byte[]</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getHash()">getHash</A></B>()</CODE>
|
||||
|
||||
@ -211,9 +219,90 @@ A block is the foundation of the BitCoin system. It records a set of <A HREF="..
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> long</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getNonce()">getNonce</A></B>()</CODE>
|
||||
|
||||
<BR>
|
||||
Returns the nonce, an arbitrary value that exists only to make the hash of the block header fall below the
|
||||
difficulty target.</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> byte[]</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getPrevBlockHash()">getPrevBlockHash</A></B>()</CODE>
|
||||
|
||||
<BR>
|
||||
Returns the hash of the previous block in the chain, as defined by the block header.</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> long</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getTime()">getTime</A></B>()</CODE>
|
||||
|
||||
<BR>
|
||||
Returns the time at which the block was solved and broadcast, according to the clock of the solving node.</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> long</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getVersion()">getVersion</A></B>()</CODE>
|
||||
|
||||
<BR>
|
||||
Returns the version of the block data structure as defined by the BitCoin protocol.</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> int</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#hashCode()">hashCode</A></B>()</CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> void</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setDifficultyTarget(long)">setDifficultyTarget</A></B>(long compactForm)</CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> void</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setMerkleRoot(byte[])">setMerkleRoot</A></B>(byte[] value)</CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> void</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setNonce(long)">setNonce</A></B>(long nonce)</CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> void</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setPrevBlockHash(byte[])">setPrevBlockHash</A></B>(byte[] prevBlockHash)</CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> void</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setTime(long)">setTime</A></B>(long time)</CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> void</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setVersion(long)">setVersion</A></B>(long version)</CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
@ -255,25 +344,6 @@ A block is the foundation of the BitCoin system. It records a set of <A HREF="..
|
||||
|
||||
<P>
|
||||
|
||||
<!-- ============ FIELD DETAIL =========== -->
|
||||
|
||||
<A NAME="field_detail"><!-- --></A>
|
||||
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
|
||||
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
|
||||
<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
|
||||
<B>Field Detail</B></FONT></TH>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<A NAME="ALLOWED_TIME_DRIFT"><!-- --></A><H3>
|
||||
ALLOWED_TIME_DRIFT</H3>
|
||||
<PRE>
|
||||
public static final long <B>ALLOWED_TIME_DRIFT</B></PRE>
|
||||
<DL>
|
||||
<DL>
|
||||
<DT><B>See Also:</B><DD><A HREF="../../../../constant-values.html#com.google.bitcoin.core.Block.ALLOWED_TIME_DRIFT">Constant Field Values</A></DL>
|
||||
</DL>
|
||||
|
||||
<!-- ========= CONSTRUCTOR DETAIL ======== -->
|
||||
|
||||
<A NAME="constructor_detail"><!-- --></A>
|
||||
@ -414,6 +484,17 @@ public byte[] <B>getMerkleRoot</B>()</PRE>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="setMerkleRoot(byte[])"><!-- --></A><H3>
|
||||
setMerkleRoot</H3>
|
||||
<PRE>
|
||||
public void <B>setMerkleRoot</B>(byte[] value)</PRE>
|
||||
<DL>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="addTransaction(com.google.bitcoin.core.Transaction)"><!-- --></A><H3>
|
||||
addTransaction</H3>
|
||||
<PRE>
|
||||
@ -425,6 +506,142 @@ public void <B>addTransaction</B>(<A HREF="../../../../com/google/bitcoin/core/T
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="getVersion()"><!-- --></A><H3>
|
||||
getVersion</H3>
|
||||
<PRE>
|
||||
public long <B>getVersion</B>()</PRE>
|
||||
<DL>
|
||||
<DD>Returns the version of the block data structure as defined by the BitCoin protocol.
|
||||
<P>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="setVersion(long)"><!-- --></A><H3>
|
||||
setVersion</H3>
|
||||
<PRE>
|
||||
public void <B>setVersion</B>(long version)</PRE>
|
||||
<DL>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="getPrevBlockHash()"><!-- --></A><H3>
|
||||
getPrevBlockHash</H3>
|
||||
<PRE>
|
||||
public byte[] <B>getPrevBlockHash</B>()</PRE>
|
||||
<DL>
|
||||
<DD>Returns the hash of the previous block in the chain, as defined by the block header.
|
||||
<P>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="setPrevBlockHash(byte[])"><!-- --></A><H3>
|
||||
setPrevBlockHash</H3>
|
||||
<PRE>
|
||||
public void <B>setPrevBlockHash</B>(byte[] prevBlockHash)</PRE>
|
||||
<DL>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="getTime()"><!-- --></A><H3>
|
||||
getTime</H3>
|
||||
<PRE>
|
||||
public long <B>getTime</B>()</PRE>
|
||||
<DL>
|
||||
<DD>Returns the time at which the block was solved and broadcast, according to the clock of the solving node.
|
||||
<P>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="setTime(long)"><!-- --></A><H3>
|
||||
setTime</H3>
|
||||
<PRE>
|
||||
public void <B>setTime</B>(long time)</PRE>
|
||||
<DL>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="getDifficultyTarget()"><!-- --></A><H3>
|
||||
getDifficultyTarget</H3>
|
||||
<PRE>
|
||||
public long <B>getDifficultyTarget</B>()</PRE>
|
||||
<DL>
|
||||
<DD>Returns the difficulty of the proof of work that this block should meet encoded in compact form. The
|
||||
<A HREF="../../../../com/google/bitcoin/core/BlockChain.html" title="class in com.google.bitcoin.core"><CODE>BlockChain</CODE></A> verifies that this is not too easy by looking at the length of the chain when the block is
|
||||
added. To find the actual value the hash should be compared against, use getDifficultyTargetBI.
|
||||
<P>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="getDifficultyTargetBI()"><!-- --></A><H3>
|
||||
getDifficultyTargetBI</H3>
|
||||
<PRE>
|
||||
public java.math.BigInteger <B>getDifficultyTargetBI</B>()</PRE>
|
||||
<DL>
|
||||
<DD>Returns the difficulty target as a 256 bit value that can be compared to a SHA-256 hash.
|
||||
<P>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="setDifficultyTarget(long)"><!-- --></A><H3>
|
||||
setDifficultyTarget</H3>
|
||||
<PRE>
|
||||
public void <B>setDifficultyTarget</B>(long compactForm)</PRE>
|
||||
<DL>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="getNonce()"><!-- --></A><H3>
|
||||
getNonce</H3>
|
||||
<PRE>
|
||||
public long <B>getNonce</B>()</PRE>
|
||||
<DL>
|
||||
<DD>Returns the nonce, an arbitrary value that exists only to make the hash of the block header fall below the
|
||||
difficulty target.
|
||||
<P>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="setNonce(long)"><!-- --></A><H3>
|
||||
setNonce</H3>
|
||||
<PRE>
|
||||
public void <B>setNonce</B>(long nonce)</PRE>
|
||||
<DL>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<HR>
|
||||
|
||||
@ -476,9 +693,9 @@ public void <B>addTransaction</B>(<A HREF="../../../../com/google/bitcoin/core/T
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
|
||||
SUMMARY: NESTED | <A HREF="#field_summary">FIELD</A> | <A HREF="#constructor_summary">CONSTR</A> | <A HREF="#method_summary">METHOD</A></FONT></TD>
|
||||
SUMMARY: NESTED | <A HREF="#fields_inherited_from_class_com.google.bitcoin.core.Message">FIELD</A> | <A HREF="#constructor_summary">CONSTR</A> | <A HREF="#method_summary">METHOD</A></FONT></TD>
|
||||
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
|
||||
DETAIL: <A HREF="#field_detail">FIELD</A> | <A HREF="#constructor_detail">CONSTR</A> | <A HREF="#method_detail">METHOD</A></FONT></TD>
|
||||
DETAIL: FIELD | <A HREF="#constructor_detail">CONSTR</A> | <A HREF="#method_detail">METHOD</A></FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<A NAME="skip-navbar_bottom"></A>
|
||||
|
@ -162,6 +162,14 @@ A NetworkConnection handles talking to a remote BitCoin peer at a low level. It
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> java.lang.String</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/NetworkConnection.html#toString()">toString</A></B>()</CODE>
|
||||
|
||||
<BR>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
|
||||
<CODE> void</CODE></FONT></TD>
|
||||
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/NetworkConnection.html#writeMessage(java.lang.String, com.google.bitcoin.core.Message)">writeMessage</A></B>(java.lang.String tag,
|
||||
<A HREF="../../../../com/google/bitcoin/core/Message.html" title="class in com.google.bitcoin.core">Message</A> message)</CODE>
|
||||
@ -176,7 +184,7 @@ A NetworkConnection handles talking to a remote BitCoin peer at a low level. It
|
||||
<TH ALIGN="left"><B>Methods inherited from class java.lang.Object</B></TH>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
|
||||
<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait</CODE></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
@ -253,19 +261,35 @@ public void <B>shutdown</B>()
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="toString()"><!-- --></A><H3>
|
||||
toString</H3>
|
||||
<PRE>
|
||||
public java.lang.String <B>toString</B>()</PRE>
|
||||
<DL>
|
||||
<DD><DL>
|
||||
<DT><B>Overrides:</B><DD><CODE>toString</CODE> in class <CODE>java.lang.Object</CODE></DL>
|
||||
</DD>
|
||||
<DD><DL>
|
||||
</DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
||||
<A NAME="readMessage()"><!-- --></A><H3>
|
||||
readMessage</H3>
|
||||
<PRE>
|
||||
public <A HREF="../../../../com/google/bitcoin/core/Message.html" title="class in com.google.bitcoin.core">Message</A> <B>readMessage</B>()
|
||||
throws <A HREF="../../../../com/google/bitcoin/core/ProtocolException.html" title="class in com.google.bitcoin.core">ProtocolException</A></PRE>
|
||||
throws java.io.IOException,
|
||||
<A HREF="../../../../com/google/bitcoin/core/ProtocolException.html" title="class in com.google.bitcoin.core">ProtocolException</A></PRE>
|
||||
<DL>
|
||||
<DD>Reads a network message from the wire, blocking until the message is fully received.
|
||||
<P>
|
||||
<DD><DL>
|
||||
|
||||
<DT><B>Returns:</B><DD>An instance of a Message subclass.
|
||||
<DT><B>Returns:</B><DD>An instance of a Message subclass
|
||||
<DT><B>Throws:</B>
|
||||
<DD><CODE><A HREF="../../../../com/google/bitcoin/core/ProtocolException.html" title="class in com.google.bitcoin.core">ProtocolException</A></CODE> - if the message is badly formatted, failed checksum or there was a protocol failure.</DL>
|
||||
<DD><CODE><A HREF="../../../../com/google/bitcoin/core/ProtocolException.html" title="class in com.google.bitcoin.core">ProtocolException</A></CODE> - if the message is badly formatted, failed checksum or there was a TCP failure.
|
||||
<DD><CODE>java.io.IOException</CODE></DL>
|
||||
</DD>
|
||||
</DL>
|
||||
<HR>
|
||||
|
@ -95,24 +95,6 @@ com.google.*</FONT></TH>
|
||||
|
||||
<P>
|
||||
|
||||
<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
|
||||
<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
|
||||
<TH ALIGN="left" COLSPAN="3">com.google.bitcoin.core.<A HREF="com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A></TH>
|
||||
</TR>
|
||||
<TR BGCOLOR="white" CLASS="TableRowColor">
|
||||
<A NAME="com.google.bitcoin.core.Block.ALLOWED_TIME_DRIFT"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
|
||||
<CODE>public static final long</CODE></FONT></TD>
|
||||
<TD ALIGN="left"><CODE><A HREF="com/google/bitcoin/core/Block.html#ALLOWED_TIME_DRIFT">ALLOWED_TIME_DRIFT</A></CODE></TD>
|
||||
<TD ALIGN="right"><CODE>7200L</CODE></TD>
|
||||
</TR>
|
||||
</FONT></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<P>
|
||||
|
||||
<P>
|
||||
|
||||
<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
|
||||
<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
|
||||
<TH ALIGN="left" COLSPAN="3">com.google.bitcoin.core.<A HREF="com/google/bitcoin/core/Message.html" title="class in com.google.bitcoin.core">Message</A></TH>
|
||||
|
@ -112,9 +112,6 @@ Variable in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Net
|
||||
<DT><A HREF="./com/google/bitcoin/core/AddressMessage.html" title="class in com.google.bitcoin.core"><B>AddressMessage</B></A> - Class in <A HREF="./com/google/bitcoin/core/package-summary.html">com.google.bitcoin.core</A><DD> <DT><A HREF="./com/google/bitcoin/core/Block.html#addTransaction(com.google.bitcoin.core.Transaction)"><B>addTransaction(Transaction)</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>Adds a transaction to this block.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#ALLOWED_TIME_DRIFT"><B>ALLOWED_TIME_DRIFT</B></A> -
|
||||
Static variable in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>
|
||||
</DL>
|
||||
<HR>
|
||||
<A NAME="_B_"><!-- --></A><H2>
|
||||
@ -272,6 +269,12 @@ Constructor for class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core
|
||||
<DT><A HREF="./com/google/bitcoin/core/GetDataMessage.html" title="class in com.google.bitcoin.core"><B>GetDataMessage</B></A> - Class in <A HREF="./com/google/bitcoin/core/package-summary.html">com.google.bitcoin.core</A><DD> <DT><A HREF="./com/google/bitcoin/core/GetDataMessage.html#GetDataMessage(com.google.bitcoin.core.NetworkParameters, byte[])"><B>GetDataMessage(NetworkParameters, byte[])</B></A> -
|
||||
Constructor for class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/GetDataMessage.html" title="class in com.google.bitcoin.core">GetDataMessage</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#getDifficultyTarget()"><B>getDifficultyTarget()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>Returns the difficulty of the proof of work that this block should meet encoded in compact form.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#getDifficultyTargetBI()"><B>getDifficultyTargetBI()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>Returns the difficulty target as a 256 bit value that can be compared to a SHA-256 hash.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Script.html#getFromAddress()"><B>getFromAddress()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Script.html" title="class in com.google.bitcoin.core">Script</A>
|
||||
<DD>Convenience wrapper around getPubKey.
|
||||
@ -300,6 +303,13 @@ Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Trans
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#getMerkleRoot()"><B>getMerkleRoot()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>Returns the merkle root in big endian form, calculating it from transactions if necessary.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#getNonce()"><B>getNonce()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>Returns the nonce, an arbitrary value that exists only to make the hash of the block header fall below the
|
||||
difficulty target.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#getPrevBlockHash()"><B>getPrevBlockHash()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>Returns the hash of the previous block in the chain, as defined by the block header.
|
||||
<DT><A HREF="./com/google/bitcoin/core/ECKey.html#getPubKey()"><B>getPubKey()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/ECKey.html" title="class in com.google.bitcoin.core">ECKey</A>
|
||||
<DD>Gets the raw public key value.
|
||||
@ -325,6 +335,9 @@ Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Trans
|
||||
<DT><A HREF="./com/google/bitcoin/core/VarInt.html#getSizeInBytes()"><B>getSizeInBytes()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/VarInt.html" title="class in com.google.bitcoin.core">VarInt</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#getTime()"><B>getTime()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>Returns the time at which the block was solved and broadcast, according to the clock of the solving node.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Script.html#getToAddress()"><B>getToAddress()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Script.html" title="class in com.google.bitcoin.core">Script</A>
|
||||
<DD>Gets the destination address from this script, if it's in the required form (see getPubKey).
|
||||
@ -340,6 +353,9 @@ Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Trans
|
||||
<DT><A HREF="./com/google/bitcoin/core/Transaction.html#getValueSentToMe(com.google.bitcoin.core.Wallet)"><B>getValueSentToMe(Wallet)</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Transaction.html" title="class in com.google.bitcoin.core">Transaction</A>
|
||||
<DD>Returns the sum of the outputs that are sending coins to a key in our wallet.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#getVersion()"><B>getVersion()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>Returns the version of the block data structure as defined by the BitCoin protocol.
|
||||
</DL>
|
||||
<HR>
|
||||
<A NAME="_H_"><!-- --></A><H2>
|
||||
@ -594,9 +610,27 @@ Constructor for exception com.google.bitcoin.core.<A HREF="./com/google/bitcoin/
|
||||
<DT><A HREF="./com/google/bitcoin/core/Wallet.html#sendCoins(com.google.bitcoin.core.Peer, com.google.bitcoin.core.Address, java.math.BigInteger)"><B>sendCoins(Peer, Address, BigInteger)</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Wallet.html" title="class in com.google.bitcoin.core">Wallet</A>
|
||||
<DD>Sends coins to the given address, via the given <A HREF="./com/google/bitcoin/core/Peer.html" title="class in com.google.bitcoin.core"><CODE>Peer</CODE></A>.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#setDifficultyTarget(long)"><B>setDifficultyTarget(long)</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#setMerkleRoot(byte[])"><B>setMerkleRoot(byte[])</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#setNonce(long)"><B>setNonce(long)</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#setPrevBlockHash(byte[])"><B>setPrevBlockHash(byte[])</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#setTime(long)"><B>setTime(long)</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/Script.html#setTracing(boolean)"><B>setTracing(boolean)</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Script.html" title="class in com.google.bitcoin.core">Script</A>
|
||||
<DD>If true, running a program will log its instructions.
|
||||
<DT><A HREF="./com/google/bitcoin/core/Block.html#setVersion(long)"><B>setVersion(long)</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Block.html" title="class in com.google.bitcoin.core">Block</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/Utils.html#sha256hash160(byte[])"><B>sha256hash160(byte[])</B></A> -
|
||||
Static method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/Utils.html" title="class in com.google.bitcoin.core">Utils</A>
|
||||
<DD>Calculates RIPEMD160(SHA256(input)).
|
||||
@ -650,6 +684,9 @@ Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/GetBl
|
||||
<DT><A HREF="./com/google/bitcoin/core/InventoryItem.html#toString()"><B>toString()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/InventoryItem.html" title="class in com.google.bitcoin.core">InventoryItem</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/NetworkConnection.html#toString()"><B>toString()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/NetworkConnection.html" title="class in com.google.bitcoin.core">NetworkConnection</A>
|
||||
<DD>
|
||||
<DT><A HREF="./com/google/bitcoin/core/PeerAddress.html#toString()"><B>toString()</B></A> -
|
||||
Method in class com.google.bitcoin.core.<A HREF="./com/google/bitcoin/core/PeerAddress.html" title="class in com.google.bitcoin.core">PeerAddress</A>
|
||||
<DD>
|
||||
|
@ -204,6 +204,8 @@ transactions</H3>
|
||||
<PRE>
|
||||
java.util.List<E> <B>transactions</B></PRE>
|
||||
<DL>
|
||||
<DD>If null, it means this object holds only the headers.
|
||||
<P>
|
||||
<DL>
|
||||
</DL>
|
||||
</DL>
|
||||
@ -213,6 +215,8 @@ hash</H3>
|
||||
<PRE>
|
||||
byte[] <B>hash</B></PRE>
|
||||
<DL>
|
||||
<DD>Stores the hash of the block. If null, getHash() will recalculate it.
|
||||
<P>
|
||||
<DL>
|
||||
</DL>
|
||||
</DL>
|
||||
|
@ -33,18 +33,22 @@ import static com.google.bitcoin.core.Utils.*;
|
||||
* you grab it from a downloaded {@link BlockChain}.
|
||||
*/
|
||||
public class Block extends Message {
|
||||
public static final long ALLOWED_TIME_DRIFT = 2 * 60 * 60; // Same value as official client.
|
||||
static final long ALLOWED_TIME_DRIFT = 2 * 60 * 60; // Same value as official client.
|
||||
|
||||
long version;
|
||||
byte[] prevBlockHash;
|
||||
byte[] merkleRoot;
|
||||
long time;
|
||||
long difficultyTarget; // "nBits"
|
||||
long nonce;
|
||||
/** A value for difficultyTarget (nBits) that allows half of all possible hash solutions. Used in unit testing. */
|
||||
static final long EASIEST_DIFFICULTY_TARGET = 0x207fFFFFL;
|
||||
|
||||
// If null, it means this object holds only the headers.
|
||||
private long version;
|
||||
private byte[] prevBlockHash;
|
||||
private byte[] merkleRoot;
|
||||
private long time;
|
||||
private long difficultyTarget; // "nBits"
|
||||
private long nonce;
|
||||
|
||||
/** If null, it means this object holds only the headers. */
|
||||
List<Transaction> transactions;
|
||||
byte[] hash;
|
||||
/** Stores the hash of the block. If null, getHash() will recalculate it. */
|
||||
private byte[] hash;
|
||||
|
||||
// If set, points towards the previous block in the chain. Note that a block may have multiple other blocks
|
||||
// pointing back to it because despite being called a "chain", the block chain is in fact a tree. There can be
|
||||
@ -106,7 +110,9 @@ public class Block extends Message {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns hash in little endian form */
|
||||
/**
|
||||
* Calculates the block hash by serializing the block and hashing the resulting bytes.
|
||||
*/
|
||||
private byte[] calculateHash() {
|
||||
try {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
@ -155,8 +161,29 @@ public class Block extends Message {
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
private void checkProofOfWork() throws VerificationException {
|
||||
|
||||
/**
|
||||
* Finds a value of nonce that makes the blocks hash lower than the difficulty target. This is called mining,
|
||||
* but solve() is far too slow to do real mining with. It exists only for unit testing purposes and is not a part
|
||||
* of the public API.
|
||||
*
|
||||
* This can loop forever if a solution cannot be found solely by incrementing nonce. It doesn't change extraNonce.
|
||||
*/
|
||||
void solve() {
|
||||
while (true) {
|
||||
try {
|
||||
// Is our proof of work valid yet?
|
||||
if (checkProofOfWork(false)) return;
|
||||
// No, so increment the nonce and try again.
|
||||
setNonce(getNonce() + 1);
|
||||
} catch (VerificationException e) {
|
||||
throw new RuntimeException(e); // Cannot happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if the hash of the block is OK (lower than difficulty target). */
|
||||
private boolean checkProofOfWork(boolean throwException) throws VerificationException {
|
||||
// This part is key - it is what proves the block was as difficult to make as it claims
|
||||
// to be. Note however that in the context of this function, the block can claim to be
|
||||
// as difficult as it wants to be .... if somebody was able to take control of our network
|
||||
@ -170,11 +197,16 @@ public class Block extends Message {
|
||||
if (target.compareTo(BigInteger.valueOf(0)) <= 0 || target.compareTo(params.proofOfWorkLimit) > 0)
|
||||
throw new VerificationException("Difficulty target is bad");
|
||||
|
||||
byte[] hashBytes = (hash == null ? calculateHash() : hash);
|
||||
BigInteger h = new BigInteger(1, hashBytes);
|
||||
if (h.compareTo(target) > 0)
|
||||
throw new VerificationException("Hash is higher than target: " + bytesToHexString(hashBytes) + " vs " +
|
||||
target.toString(16));
|
||||
BigInteger h = new BigInteger(1, getHash());
|
||||
if (h.compareTo(target) > 0) {
|
||||
// Proof of work check failed!
|
||||
if (throwException)
|
||||
throw new VerificationException("Hash is higher than target: " + getHashAsString() + " vs " +
|
||||
target.toString(16));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void checkTimestamp() throws VerificationException {
|
||||
@ -260,7 +292,7 @@ public class Block extends Message {
|
||||
//
|
||||
// Firstly we need to ensure this block does in fact represent real work done. If the
|
||||
// difficulty is high enough, it's probably been done by the network.
|
||||
checkProofOfWork();
|
||||
checkProofOfWork(true);
|
||||
checkTimestamp();
|
||||
// Now we need to check that the body of the block actually matches the headers. The
|
||||
// network won't generate an invalid block, but if we didn't validate this then an
|
||||
@ -281,14 +313,12 @@ public class Block extends Message {
|
||||
if (hash != null && other.hash != null)
|
||||
return Arrays.equals(hash, other.hash);
|
||||
// Otherwise we have to do it the slow way.
|
||||
byte[] me = bitcoinSerialize();
|
||||
byte[] them = other.bitcoinSerialize();
|
||||
return Arrays.equals(me, them);
|
||||
return Arrays.equals(getHash(), other.getHash());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(hash);
|
||||
return Arrays.hashCode(getHash());
|
||||
}
|
||||
|
||||
/** Returns the merkle root in big endian form, calculating it from transactions if necessary. */
|
||||
@ -298,6 +328,11 @@ public class Block extends Message {
|
||||
return merkleRoot;
|
||||
}
|
||||
|
||||
public void setMerkleRoot(byte[] value) {
|
||||
merkleRoot = value;
|
||||
hash = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a transaction to this block.
|
||||
*/
|
||||
@ -310,4 +345,82 @@ public class Block extends Message {
|
||||
merkleRoot = null;
|
||||
hash = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the block data structure as defined by the BitCoin protocol.
|
||||
*/
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
this.hash = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash of the previous block in the chain, as defined by the block header.
|
||||
*/
|
||||
public byte[] getPrevBlockHash() {
|
||||
return prevBlockHash;
|
||||
}
|
||||
|
||||
public void setPrevBlockHash(byte[] prevBlockHash) {
|
||||
this.prevBlockHash = prevBlockHash;
|
||||
this.hash = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time at which the block was solved and broadcast, according to the clock of the solving node.
|
||||
*/
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
this.hash = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difficulty of the proof of work that this block should meet encoded in compact form. The
|
||||
* {@link BlockChain} verifies that this is not too easy by looking at the length of the chain when the block is
|
||||
* added. To find the actual value the hash should be compared against, use getDifficultyTargetBI.
|
||||
*/
|
||||
public long getDifficultyTarget() {
|
||||
return difficultyTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difficulty target as a 256 bit value that can be compared to a SHA-256 hash.
|
||||
*/
|
||||
public BigInteger getDifficultyTargetBI() {
|
||||
return Utils.decodeCompactBits(getDifficultyTarget());
|
||||
}
|
||||
|
||||
public void setDifficultyTarget(long compactForm) {
|
||||
this.difficultyTarget = compactForm;
|
||||
this.hash = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nonce, an arbitrary value that exists only to make the hash of the block header fall below the
|
||||
* difficulty target.
|
||||
*/
|
||||
public long getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
public void setNonce(long nonce) {
|
||||
this.nonce = nonce;
|
||||
this.hash = null;
|
||||
}
|
||||
|
||||
/** Adds a fake coinbase transaction for unit tests. */
|
||||
void addFakeTransaction() {
|
||||
transactions = new ArrayList<Transaction>();
|
||||
Transaction coinbase = new Transaction(params);
|
||||
coinbase.setFakeHashForTesting(Utils.doubleDigest("test tx".getBytes()));
|
||||
transactions.add(coinbase);
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class BlockChain {
|
||||
LOG("Re-received block that is currently on top of the chain.");
|
||||
return true;
|
||||
}
|
||||
if (!Arrays.equals(block.prevBlockHash, prev.getHash())) {
|
||||
if (!Arrays.equals(block.getPrevBlockHash(), prev.getHash())) {
|
||||
// The block does not fit onto the top of the chain. It can either be:
|
||||
// - Entirely unconnected. This can happen when a new block is solved and broadcast whilst we are in
|
||||
// the process of downloading the block chain.
|
||||
@ -140,7 +140,7 @@ public class BlockChain {
|
||||
blocksConnectedThisRound = 0;
|
||||
for (int i = 0; i < unconnectedBlocks.size(); i++) {
|
||||
Block block = unconnectedBlocks.get(i);
|
||||
if (Arrays.equals(block.prevBlockHash, blockChain.getLast().getHash())) {
|
||||
if (Arrays.equals(block.getPrevBlockHash(), blockChain.getLast().getHash())) {
|
||||
// False here ensures we don't recurse infinitely downwards when connecting huge chains.
|
||||
add(block, false);
|
||||
unconnectedBlocks.remove(i);
|
||||
@ -163,21 +163,22 @@ public class BlockChain {
|
||||
// Is this supposed to be a difficulty transition point?
|
||||
if (blockChain.size() % INTERVAL != 0) {
|
||||
// No ... so check the difficulty didn't actually change.
|
||||
if (top.difficultyTarget != prev.difficultyTarget)
|
||||
if (top.getDifficultyTarget() != prev.getDifficultyTarget())
|
||||
throw new VerificationException("Unexpected change in difficulty at height " + blockChain.size() +
|
||||
": " + Long.toHexString(top.difficultyTarget) + " vs " + Long.toHexString(prev.difficultyTarget));
|
||||
": " + Long.toHexString(top.getDifficultyTarget()) + " vs " +
|
||||
Long.toHexString(prev.getDifficultyTarget()));
|
||||
return;
|
||||
}
|
||||
|
||||
Block blockIntervalAgo = blockChain.get(blockChain.size() - INTERVAL);
|
||||
int timespan = (int) (prev.time - blockIntervalAgo.time);
|
||||
int timespan = (int) (prev.getTime() - blockIntervalAgo.getTime());
|
||||
// Limit the adjustment step.
|
||||
if (timespan < TARGET_TIMESPAN / 4)
|
||||
timespan = TARGET_TIMESPAN / 4;
|
||||
if (timespan > TARGET_TIMESPAN * 4)
|
||||
timespan = TARGET_TIMESPAN * 4;
|
||||
|
||||
BigInteger newDifficulty = Utils.decodeCompactBits(blockIntervalAgo.difficultyTarget);
|
||||
BigInteger newDifficulty = Utils.decodeCompactBits(blockIntervalAgo.getDifficultyTarget());
|
||||
newDifficulty = newDifficulty.multiply(BigInteger.valueOf(timespan));
|
||||
newDifficulty = newDifficulty.divide(BigInteger.valueOf(TARGET_TIMESPAN));
|
||||
|
||||
@ -185,8 +186,8 @@ public class BlockChain {
|
||||
newDifficulty = params.proofOfWorkLimit;
|
||||
}
|
||||
|
||||
int accuracyBytes = (int) (top.difficultyTarget >>> 24) - 3;
|
||||
BigInteger receivedDifficulty = Utils.decodeCompactBits(top.difficultyTarget);
|
||||
int accuracyBytes = (int) (top.getDifficultyTarget() >>> 24) - 3;
|
||||
BigInteger receivedDifficulty = top.getDifficultyTargetBI();
|
||||
|
||||
// The calculated difficulty is to a higher precision than received, so reduce here.
|
||||
BigInteger mask = BigInteger.valueOf(0xFFFFFFL).shiftLeft(accuracyBytes * 8);
|
||||
|
@ -78,9 +78,9 @@ public class NetworkParameters implements Serializable {
|
||||
n.port = 18333;
|
||||
n.addressHeader = 111;
|
||||
n.genesisBlock = createGenesis(n);
|
||||
n.genesisBlock.time = 1296688602L;
|
||||
n.genesisBlock.difficultyTarget = 0x1d07fff8L;
|
||||
n.genesisBlock.nonce = 384568319;
|
||||
n.genesisBlock.setTime(1296688602L);
|
||||
n.genesisBlock.setDifficultyTarget(0x1d07fff8L);
|
||||
n.genesisBlock.setNonce(384568319);
|
||||
String genesisHash = n.genesisBlock.getHashAsString();
|
||||
assert genesisHash.equals("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008");
|
||||
return n;
|
||||
@ -94,11 +94,19 @@ public class NetworkParameters implements Serializable {
|
||||
n.packetMagic = 0xf9beb4d9L;
|
||||
n.addressHeader = 0;
|
||||
n.genesisBlock = createGenesis(n);
|
||||
n.genesisBlock.difficultyTarget = 0x1d00ffffL;
|
||||
n.genesisBlock.time = 1231006505;
|
||||
n.genesisBlock.nonce = 2083236893;
|
||||
n.genesisBlock.setDifficultyTarget(0x1d00ffffL);
|
||||
n.genesisBlock.setTime(1231006505L);
|
||||
n.genesisBlock.setNonce(2083236893);
|
||||
String genesisHash = n.genesisBlock.getHashAsString();
|
||||
assert genesisHash.equals("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||
assert genesisHash.equals("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f") : genesisHash;
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Returns a testnet params modified to allow any difficulty target. */
|
||||
static NetworkParameters unitTests() {
|
||||
NetworkParameters n = NetworkParameters.testNet();
|
||||
n.proofOfWorkLimit = new BigInteger("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16);
|
||||
n.genesisBlock.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,6 @@ public class Peer {
|
||||
LOG("Shutting down peer thread");
|
||||
} else {
|
||||
// We caught an unexpected exception.
|
||||
System.err.println(e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import java.math.BigInteger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
// Tests still to write:
|
||||
// - Rest of checkDifficultyTransitions: verify we don't accept invalid transitions.
|
||||
@ -50,18 +51,13 @@ public class BlockChainTest {
|
||||
Block b2 = getBlock2();
|
||||
|
||||
// Let's try adding an invalid block.
|
||||
long n = b2.nonce;
|
||||
long n = b2.getNonce();
|
||||
try {
|
||||
// TODO: Encapsulate these fields behind setters that recalc the hash automatically.
|
||||
b2.nonce = 12345;
|
||||
b2.hash = null;
|
||||
b2.setNonce(12345);
|
||||
chain.add(b2);
|
||||
// We should not get here.
|
||||
assertTrue(false);
|
||||
fail();
|
||||
} catch (VerificationException e) {
|
||||
// Pass.
|
||||
b2.nonce = n;
|
||||
b2.hash = null;
|
||||
b2.setNonce(n);
|
||||
}
|
||||
assertTrue(chain.add(b2));
|
||||
}
|
||||
@ -74,20 +70,20 @@ public class BlockChainTest {
|
||||
NetworkParameters params2 = NetworkParameters.testNet();
|
||||
Block bad = new Block(params2);
|
||||
// Merkle root can be anything here, doesn't matter.
|
||||
bad.merkleRoot = Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
bad.setMerkleRoot(Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
|
||||
// Nonce was just some number that made the hash < difficulty limit set below, it can be anything.
|
||||
bad.nonce = 140548933;
|
||||
bad.time = 1279242649;
|
||||
bad.prevBlockHash = b2.getHash();
|
||||
bad.setNonce(140548933);
|
||||
bad.setTime(1279242649);
|
||||
bad.setPrevBlockHash(b2.getHash());
|
||||
// We're going to make this block so easy 50% of solutions will pass, and check it gets rejected for having a
|
||||
// bad difficulty target. Unfortunately the encoding mechanism means we cannot make one that accepts all
|
||||
// solutions.
|
||||
bad.difficultyTarget = 0x207fFFFFL;
|
||||
bad.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
|
||||
try {
|
||||
chain.add(bad);
|
||||
// The difficulty target above should be rejected on the grounds of being easier than the networks
|
||||
// allowable difficulty.
|
||||
assertTrue(false);
|
||||
fail();
|
||||
} catch (VerificationException e) {
|
||||
assertTrue(e.getMessage(), e.getMessage().indexOf("Difficulty target is bad") >= 0);
|
||||
}
|
||||
@ -98,7 +94,7 @@ public class BlockChainTest {
|
||||
try {
|
||||
chain.add(bad);
|
||||
// We should not get here as the difficulty target should not be changing at this point.
|
||||
assertTrue(false);
|
||||
fail();
|
||||
} catch (VerificationException e) {
|
||||
assertTrue(e.getMessage(), e.getMessage().indexOf("Unexpected change in difficulty") >= 0);
|
||||
}
|
||||
@ -108,11 +104,10 @@ public class BlockChainTest {
|
||||
|
||||
private Block getBlock2() throws Exception {
|
||||
Block b2 = new Block(params);
|
||||
b2.merkleRoot = Hex.decode("addc858a17e21e68350f968ccd384d6439b64aafa6c193c8b9dd66320470838b");
|
||||
b2.nonce = 2642058077L;
|
||||
b2.time = 1296734343;
|
||||
b2.prevBlockHash =
|
||||
Hex.decode("000000033cc282bc1fa9dcae7a533263fd7fe66490f550d80076433340831604");
|
||||
b2.setMerkleRoot(Hex.decode("addc858a17e21e68350f968ccd384d6439b64aafa6c193c8b9dd66320470838b"));
|
||||
b2.setNonce(2642058077L);
|
||||
b2.setTime(1296734343L);
|
||||
b2.setPrevBlockHash(Hex.decode("000000033cc282bc1fa9dcae7a533263fd7fe66490f550d80076433340831604"));
|
||||
assertEquals("000000037b21cac5d30fc6fda2581cf7b2612908aed2abbcc429c45b0557a15f", b2.getHashAsString());
|
||||
b2.verify();
|
||||
return b2;
|
||||
@ -120,10 +115,10 @@ public class BlockChainTest {
|
||||
|
||||
private Block getBlock1() throws Exception {
|
||||
Block b1 = new Block(params);
|
||||
b1.merkleRoot = Hex.decode("0e8e58ecdacaa7b3c6304a35ae4ffff964816d2b80b62b58558866ce4e648c10");
|
||||
b1.nonce = 236038445;
|
||||
b1.time = 1296734340;
|
||||
b1.prevBlockHash = Hex.decode("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008");
|
||||
b1.setMerkleRoot(Hex.decode("0e8e58ecdacaa7b3c6304a35ae4ffff964816d2b80b62b58558866ce4e648c10"));
|
||||
b1.setNonce(236038445);
|
||||
b1.setTime(1296734340);
|
||||
b1.setPrevBlockHash(Hex.decode("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008"));
|
||||
assertEquals("000000033cc282bc1fa9dcae7a533263fd7fe66490f550d80076433340831604", b1.getHashAsString());
|
||||
b1.verify();
|
||||
return b1;
|
||||
|
@ -25,13 +25,10 @@ import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class BlockTest {
|
||||
static final NetworkParameters params = NetworkParameters.testNet();
|
||||
|
||||
static final byte[] blockBytes;
|
||||
|
||||
static {
|
||||
@ -44,6 +41,38 @@ public class BlockTest {
|
||||
public void testBlockVerification() throws Exception {
|
||||
Block block = new Block(params, blockBytes);
|
||||
block.verify();
|
||||
assertEquals("00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935", block.getHashAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProofOfWork() throws Exception {
|
||||
// This params accepts any difficulty target.
|
||||
NetworkParameters params = NetworkParameters.unitTests();
|
||||
Block block = new Block(params, blockBytes);
|
||||
block.setNonce(12346);
|
||||
try {
|
||||
block.verify();
|
||||
fail();
|
||||
} catch (VerificationException e) {
|
||||
// Expected.
|
||||
}
|
||||
// Blocks contain their own difficulty target. The BlockChain verification mechanism is what stops real blocks
|
||||
// from containing artificially weak difficulties.
|
||||
block.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
|
||||
// Now it should pass.
|
||||
block.verify();
|
||||
// Break the nonce again at the lower difficulty level so we can try solving for it.
|
||||
block.setNonce(1);
|
||||
try {
|
||||
block.verify();
|
||||
fail();
|
||||
} catch (VerificationException e) {
|
||||
// Expected to fail as the nonce is no longer correct.
|
||||
}
|
||||
// Should find an acceptable nonce.
|
||||
block.solve();
|
||||
block.verify();
|
||||
assertEquals(block.getNonce(), 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -56,7 +85,7 @@ public class BlockTest {
|
||||
block.transactions.set(1, tx1);
|
||||
try {
|
||||
block.verify();
|
||||
assertTrue("Verified when should not.", false);
|
||||
fail();
|
||||
} catch (VerificationException e) {
|
||||
// We should get here.
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user