예제 #1
0
 public override StoredBlock Get(Sha256Hash hash)
 {
     using(locker.AcquireReaderLock())
     {
         StoredBlock block;
         if(store.TryGetValue(hash.ToString(),out block))
         { return block; }
         return null;
     }
 }
예제 #2
0
		public TransactionOutPoint(NetworkParameters params, long index, Transaction fromTx) {
			super(params);
			this.index = index;
			if (fromTx != null) {
				this.hash = fromTx.getHash();
				this.fromTx = fromTx;
			} else {
				// This happens when constructing the genesis block.
				hash = Sha256Hash.ZERO_HASH;
			}
			length = MESSAGE_LENGTH;
		}
예제 #3
0
        /////throws ClassNotFoundException, IOException
        //private void readObject(ObjectInputStream ois)
        //{
        //    ois.defaultReadObject();
        //    // This code is not actually necessary, as transient fields are initialized to the default value which is in
        //    // this case null. However it clears out a FindBugs warning and makes it explicit what we're doing.
        //    hash = null;
        //}
        private void parseHeader()
        {
            if(headerParsed)
            { return; }

            Cursor=Offset;
            Version=ReadUint32();
            PreviousBlockHash=ReadHash();
            MerkleRoot=ReadHash();
            TimeSeconds=ReadUint32();
            difficultyTarget=ReadUint32();
            nonce=ReadUint32();

            hash=new Sha256Hash(DoubleDigestSha256Helper.DoubleDigest(Bytes,Offset,Cursor).ReverseBytes());

            headerParsed=true;
            headerBytesValid=ParseRetain;
        }
예제 #4
0
        /// <summary>
        /// Adds a transaction to this block, with or without checking the sanity of doing so.
        /// <exception cref="VerificationException"></exception>
        /// </summary>
        /// <param name="transaction"></param>
        /// <param name="runSanityChecks"></param>
        public void addTransaction(Transaction transaction,bool runSanityChecks)
        {
            if(Transactions==null)
            { Transactions=new List<Transaction>(); }

            transaction.SetParent(this);

            if(runSanityChecks)
            {
                if(Transactions.Count==0 && !transaction.IsCoinBase)
                { throw new VerificationException("Attempted to add a non-coinbase transaction as the first transaction: "+t); }

                if(Transactions.Count>0 && transaction.IsCoinBase)
                { throw new VerificationException("Attempted to add a coinbase transaction when there already is one: "+t); }
            }

            Transactions.Add(transaction);
            AdjustLength(Transactions.Count,transaction.Length);

            // Force a recalculation next time the values are needed.
            MerkleRoot=null;
            hash=null;
        }
예제 #5
0
		/**
		 * This is required for signatures which use a sigHashType which cannot be represented using SigHash and anyoneCanPay
		 * See transaction c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73, which has sigHashType 0
		 * throws ScriptException
		 */
		private Sha256Hash hashTransactionForSignature(int inputIndex,byte[] connectedScript,byte sigHashType)
		{
			lock(this)
			{
				// TODO: This whole separate method should be un-necessary if we fix how we deserialize sighash flags.
				// The SIGHASH flags are used in the design of contracts, please see this page for a further understanding of
				// the purposes of the code in this method:
				//
				//   https://en.bitcoin.it/wiki/Contracts
			
				try
				{
					// Store all the input scripts and clear them in preparation for signing. If we're signing a fresh
					// transaction that step isn't very helpful, but it doesn't add much cost relative to the actual
					// EC math so we'll do it anyway.
					//
					// Also store the input sequence numbers in case we are clearing them with SigHash.NONE/SINGLE
				
					byte[][] inputScripts = new byte[inputs.size()][];
					long[] inputSequenceNumbers = new long[inputs.size()];
					for (int i = 0; i < inputs.size(); i++)
					{
						inputScripts[i] = inputs[i].getScriptBytes();
						inputSequenceNumbers[i] = inputs[i].getSequenceNumber();
						inputs[i].setScriptBytes(TransactionInput.EMPTY_ARRAY);
					}
				
					// This step has no purpose beyond being synchronized with the reference clients bugs. OP_CODESEPARATOR
					// is a legacy holdover from a previous, broken design of executing scripts that shipped in Bitcoin 0.1.
					// It was seriously flawed and would have let anyone take anyone elses money. Later versions switched to
					// the design we use today where scripts are executed independently but share a stack. This left the
					// OP_CODESEPARATOR instruction having no purpose as it was only meant to be used internally, not actually
					// ever put into scripts. Deleting OP_CODESEPARATOR is a step that should never be required but if we don't
					// do it, we could split off the main chain.
				
					connectedScript = Script.removeAllInstancesOfOp(connectedScript, Script.OP_CODESEPARATOR);
				
					// Set the input to the script of its output. Satoshi does this but the step has no obvious purpose as
					// the signature covers the hash of the prevout transaction which obviously includes the output script
					// already. Perhaps it felt safer to him in some way, or is another leftover from how the code was written.
				
					TransactionInput input = inputs.get(inputIndex);
					input.setScriptBytes(connectedScript);
					ArrayList<TransactionOutput> outputs = this.outputs;
					if((sigHashType & 0x1f) == (SigHash.NONE.ordinal() + 1))
					{
						// SIGHASH_NONE means no outputs are signed at all - the signature is effectively for a "blank cheque".
						this.outputs = new ArrayList<TransactionOutput>(0);
					
						// The signature isn't broken by new versions of the transaction issued by other parties.
					
						for(int i=0;i<inputs.size();i++)
						{
							if (i != inputIndex)
							{ inputs[i].setSequenceNumber(0); }
						}
					}
					else if((sigHashType & 0x1f) == (SigHash.SINGLE.ordinal() + 1))
					{
						// SIGHASH_SINGLE means only sign the output at the same index as the input (ie, my output).
					
						if (inputIndex >= this.outputs.size())
						{
							// The input index is beyond the number of outputs, it's a buggy signature made by a broken
							// Bitcoin implementation. The reference client also contains a bug in handling this case:
							// any transaction output that is signed in this case will result in both the signed output
							// and any future outputs to this public key being steal-able by anyone who has
							// the resulting signature and the public key (both of which are part of the signed tx input).
							// Put the transaction back to how we found it.
							// TODO: Only allow this to happen if we are checking a signature, not signing a transactions
						
							for(int i=0;i<inputs.size();i++)
							{
								inputs[i].setScriptBytes(inputScripts[i]);
								inputs[i].setSequenceNumber(inputSequenceNumbers[i]);
							}
						
							this.outputs = outputs;
						
							// Satoshis bug is that SignatureHash was supposed to return a hash and on this codepath it
							// actually returns the constant "1" to indicate an error, which is never checked for. Oops.
							return new Sha256Hash("0100000000000000000000000000000000000000000000000000000000000000");
						}
					
						// In SIGHASH_SINGLE the outputs after the matching input index are deleted, and the outputs before
						// that position are "nulled out". Unintuitively, the value in a "null" transaction is set to -1.
					
						this.outputs = new ArrayList<TransactionOutput>(this.outputs.subList(0, inputIndex + 1));
						for (int i = 0; i < inputIndex; i++)
						{ this.outputs.set(i, new TransactionOutput(params, this, BigInteger.valueOf(-1), new byte[] {})); }
					
						// The signature isn't broken by new versions of the transaction issued by other parties.
						for(int i=0;i<inputs.size();i++)
						{
							if (i != inputIndex)
							{ inputs[i].setSequenceNumber(0); }
						}
					}
				
					ArrayList<TransactionInput> inputs = this.inputs;
				
					if((sigHashType & 0x80) == 0x80)
					{
						// SIGHASH_ANYONECANPAY means the signature in the input is not broken by changes/additions/removals
						// of other inputs. For example, this is useful for building assurance contracts.
					
						this.inputs = new ArrayList<TransactionInput>();
						this.inputs.add(input);
					}
				
					ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(length == UNKNOWN_LENGTH ? 256 : length + 4);
					bitcoinSerialize(bos);
				
					// We also have to write a hash type (sigHashType is actually an unsigned char)
					uint32ToByteStreamLE(0x000000ff & sigHashType, bos);
				
					// Note that this is NOT reversed to ensure it will be signed correctly. If it were to be printed out
					// however then we would expect that it is IS reversed.
					Sha256Hash hash = new Sha256Hash(doubleDigest(bos.toByteArray()));
					bos.close();
				
					// Put the transaction back to how we found it.
					this.inputs = inputs;
					for (int i = 0; i < inputs.size(); i++)
					{
						inputs[i].setScriptBytes(inputScripts[i]);
						inputs[i].setSequenceNumber(inputSequenceNumbers[i]);
					}
				
					this.outputs = outputs;
					return hash;
				}
				catch(IOException e)
				{
					throw new RuntimeException(e);  // Cannot happen.
				}
			}
		}
예제 #6
0
		protected void unCache() {
			super.unCache();
			hash = null;
		}
예제 #7
0
		public void addBlockAppearance(Sha256Hash blockHash)
		{
			if(appearsInHashes==null)
			{ appearsInHashes=new HashSet<Sha256Hash>(); }
			appearsInHashes.Add(blockHash);
		}
예제 #8
0
		public Transaction(NetworkParameters parameters,int version,Sha256Hash hash):base(parameters)
		{
			this.version=version & ((1L<<32)-1); // this field is unsigned - remove any sign extension
			inputs=new List<TransactionInput>();
			outputs=new List<TransactionOutput>();
			this.hash=hash;

			// We don't initialize appearsIn deliberately as it's only useful for transactions stored in the wallet.
			Length=8; //8 for std fields
		}
예제 #9
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="height"></param>
 /// <param name="hash"></param>
 /// <returns>True if the block height is either not a checkpoint, or is a checkpoint and the hash matches.</returns>
 public bool PassesCheckpoint(int height,Sha256Hash hash)
 {
     if(hash!=null)
     {
         Sha256Hash checkpointHash;
         if(Checkpoints.TryGetValue(height,out checkpointHash))
         { return checkpointHash.Equals(hash); }
     }
     return true;
 }
예제 #10
0
		public TransactionOutPoint(NetworkParameters params, long index, Sha256Hash hash) {
			super(params);
			this.index = index;
			this.hash = hash;
			length = MESSAGE_LENGTH;
		}