public override StoredBlock Get(Sha256Hash hash) { using(locker.AcquireReaderLock()) { StoredBlock block; if(store.TryGetValue(hash.ToString(),out block)) { return block; } return null; } }
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; }
/////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; }
/// <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; }
/** * 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. } } }
protected void unCache() { super.unCache(); hash = null; }
public void addBlockAppearance(Sha256Hash blockHash) { if(appearsInHashes==null) { appearsInHashes=new HashSet<Sha256Hash>(); } appearsInHashes.Add(blockHash); }
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 }
/// <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; }
public TransactionOutPoint(NetworkParameters params, long index, Sha256Hash hash) { super(params); this.index = index; this.hash = hash; length = MESSAGE_LENGTH; }