3
0
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:
Mike Hearn 2011-03-08 15:23:06 +00:00
parent 38bf9a8a80
commit 4003eee3fe
11 changed files with 533 additions and 124 deletions

View File

@ -73,9 +73,9 @@ function windowTitle()
</TR>
<TR>
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_com.google.bitcoin.core.Message">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<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&nbsp;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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
</TABLE>
&nbsp;<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>&nbsp;long</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getDifficultyTarget()">getDifficultyTarget</A></B>()</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;java.math.BigInteger</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getDifficultyTargetBI()">getDifficultyTargetBI</A></B>()</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;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>&nbsp;long</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getNonce()">getNonce</A></B>()</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;byte[]</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getPrevBlockHash()">getPrevBlockHash</A></B>()</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;long</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getTime()">getTime</A></B>()</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;long</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#getVersion()">getVersion</A></B>()</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;int</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#hashCode()">hashCode</A></B>()</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;void</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setDifficultyTarget(long)">setDifficultyTarget</A></B>(long&nbsp;compactForm)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;void</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setMerkleRoot(byte[])">setMerkleRoot</A></B>(byte[]&nbsp;value)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;void</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setNonce(long)">setNonce</A></B>(long&nbsp;nonce)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;void</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setPrevBlockHash(byte[])">setPrevBlockHash</A></B>(byte[]&nbsp;prevBlockHash)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;void</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setTime(long)">setTime</A></B>(long&nbsp;time)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;void</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/Block.html#setVersion(long)">setVersion</A></B>(long&nbsp;version)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
@ -255,25 +344,6 @@ A block is the foundation of the BitCoin system. It records a set of <A HREF="..
&nbsp;
<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[]&nbsp;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&nbsp;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[]&nbsp;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&nbsp;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&nbsp;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&nbsp;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:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_com.google.bitcoin.core.Message">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
</TR>
</TABLE>
<A NAME="skip-navbar_bottom"></A>

View File

@ -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>&nbsp;java.lang.String</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../../com/google/bitcoin/core/NetworkConnection.html#toString()">toString</A></B>()</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;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&nbsp;tag,
<A HREF="../../../../com/google/bitcoin/core/Message.html" title="class in com.google.bitcoin.core">Message</A>&nbsp;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>
&nbsp;
@ -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>

View File

@ -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&nbsp;static&nbsp;final&nbsp;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>

View File

@ -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>&nbsp;<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>&nbsp;
</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>&nbsp;<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>&nbsp;
<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>&nbsp;
<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>&nbsp;
<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>&nbsp;
<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>&nbsp;
<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>&nbsp;
<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>&nbsp;
<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>&nbsp;
<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>&nbsp;
<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>&nbsp;
<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>&nbsp;

View File

@ -204,6 +204,8 @@ transactions</H3>
<PRE>
java.util.List&lt;E&gt; <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>

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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.
}