/// <summary> /// Returns a human readable debug string. /// </summary> public override string ToString() { if (IsCoinBase) { return("TxIn: COINBASE"); } return("TxIn from tx " + Outpoint + " (pubkey: " + Utils.BytesToHexString(ScriptSig.PubKey) + ") script:" + ScriptSig); }
public override string ToString() { var b = new StringBuilder(); b.Append("pub:").Append(Utils.BytesToHexString(_pub)); b.Append(" priv:").Append(Utils.BytesToHexString(_priv.ToByteArray())); return(b.ToString()); }
/// <summary> /// Returns the program opcodes as a string, for example "[1234] DUP HAHS160" /// </summary> public override string ToString() { var buf = new StringBuilder(); foreach (var chunk in _chunks) { if (chunk.Length == 1) { string opName; var opcode = chunk[0]; switch (opcode) { case OpDup: opName = "DUP"; break; case OpHash160: opName = "HASH160"; break; case OpCheckSig: opName = "CHECKSIG"; break; case OpEqualVerify: opName = "EQUALVERIFY"; break; default: opName = "?(" + opcode + ")"; break; } buf.Append(opName); buf.Append(" "); } else { // Data chunk buf.Append("["); buf.Append(chunk.Length); buf.Append("]"); buf.Append(Utils.BytesToHexString(chunk)); buf.Append(" "); } } return(buf.ToString()); }
/// <summary> /// Writes message to to the output stream. /// </summary> /// <exception cref="IOException"/> public void Serialize(Message message, Stream @out) { string name; if (!_names.TryGetValue(message.GetType(), out name)) { throw new Exception("BitcoinSerializer doesn't currently know how to serialize " + message.GetType()); } var header = new byte[4 + _commandLen + 4 + (_usesChecksumming ? 4 : 0)]; Utils.Uint32ToByteArrayBe(_params.PacketMagic, header, 0); // The header array is initialized to zero so we don't have to worry about // NULL terminating the string here. for (var i = 0; i < name.Length && i < _commandLen; i++) { header[4 + i] = (byte)name[i]; } var payload = message.BitcoinSerialize(); Utils.Uint32ToByteArrayLe((uint)payload.Length, header, 4 + _commandLen); if (_usesChecksumming) { var hash = Utils.DoubleDigest(payload); Array.Copy(hash, 0, header, 4 + _commandLen + 4, 4); } @out.Write(header); @out.Write(payload); if (_log.IsDebugEnabled) { _log.DebugFormat("Sending {0} message: {1}", name, Utils.BytesToHexString(header) + Utils.BytesToHexString(payload)); } }
/// <exception cref="ProtocolException"/> internal Message(NetworkParameters @params, byte[] msg, int offset, uint protocolVersion = NetworkParameters.ProtocolVersion) { ProtocolVersion = protocolVersion; Params = @params; Bytes = msg; Cursor = Offset = offset; Parse(); #if SELF_CHECK // Useful to ensure serialize/deserialize are consistent with each other. if (GetType() != typeof(VersionMessage)) { var msgbytes = new byte[Cursor - offset]; Array.Copy(msg, offset, msgbytes, 0, Cursor - offset); var reserialized = BitcoinSerialize(); if (!reserialized.SequenceEqual(msgbytes)) { throw new Exception("Serialization is wrong: " + Environment.NewLine + Utils.BytesToHexString(reserialized) + " vs " + Environment.NewLine + Utils.BytesToHexString(msgbytes)); } } #endif Bytes = null; }
public override string ToString() { return(Utils.BytesToHexString(_bytes)); }
/// <summary> /// Once a transaction has some inputs and outputs added, the signatures in the inputs can be calculated. The /// signature is over the transaction itself, to prove the redeemer actually created that transaction, /// so we have to do this step last. /// </summary> /// <remarks> /// This method is similar to SignatureHash in script.cpp /// </remarks> /// <param name="hashType">This should always be set to SigHash.ALL currently. Other types are unused. </param> /// <param name="wallet">A wallet is required to fetch the keys needed for signing.</param> /// <exception cref="ScriptException"/> public void SignInputs(SigHash hashType, Wallet wallet) { Debug.Assert(_inputs.Count > 0); Debug.Assert(_outputs.Count > 0); // I don't currently have an easy way to test other modes work, as the official client does not use them. Debug.Assert(hashType == SigHash.All); // The transaction is signed with the input scripts empty except for the input we are signing. In the case // where addInput has been used to set up a new transaction, they are already all empty. The input being signed // has to have the connected OUTPUT program in it when the hash is calculated! // // Note that each input may be claiming an output sent to a different key. So we have to look at the outputs // to figure out which key to sign with. var signatures = new byte[_inputs.Count][]; var signingKeys = new EcKey[_inputs.Count]; for (var i = 0; i < _inputs.Count; i++) { var input = _inputs[i]; Debug.Assert(input.ScriptBytes.Length == 0, "Attempting to sign a non-fresh transaction"); // Set the input to the script of its output. input.ScriptBytes = input.Outpoint.ConnectedPubKeyScript; // Find the signing key we'll need to use. var connectedPubKeyHash = input.Outpoint.ConnectedPubKeyHash; var key = wallet.FindKeyFromPubHash(connectedPubKeyHash); // This assert should never fire. If it does, it means the wallet is inconsistent. Debug.Assert(key != null, "Transaction exists in wallet that we cannot redeem: " + Utils.BytesToHexString(connectedPubKeyHash)); // Keep the key around for the script creation step below. signingKeys[i] = key; // The anyoneCanPay feature isn't used at the moment. const bool anyoneCanPay = false; var hash = HashTransactionForSignature(hashType, anyoneCanPay); // Set the script to empty again for the next input. input.ScriptBytes = TransactionInput.EmptyArray; // Now sign for the output so we can redeem it. We use the keypair to sign the hash, // and then put the resulting signature in the script along with the public key (below). using (var bos = new MemoryStream()) { bos.Write(key.Sign(hash)); bos.Write((byte)(((int)hashType + 1) | (anyoneCanPay ? 0x80 : 0))); signatures[i] = bos.ToArray(); } } // Now we have calculated each signature, go through and create the scripts. Reminder: the script consists of // a signature (over a hash of the transaction) and the complete public key needed to sign for the connected // output. for (var i = 0; i < _inputs.Count; i++) { var input = _inputs[i]; Debug.Assert(input.ScriptBytes.Length == 0); var key = signingKeys[i]; input.ScriptBytes = Script.CreateInputScript(signatures[i], key.PubKey); } // Every input is now complete. }
public override string ToString() { return("Unknown message [" + _name + "]: " + (Bytes == null ? "" : Utils.BytesToHexString(Bytes))); }
/// <summary> /// Reads a message from the given InputStream and returns it. /// </summary> /// <exception cref="ProtocolException"/> /// <exception cref="IOException"/> public Message Deserialize(Stream @in) { // A BitCoin protocol message has the following format. // // - 4 byte magic number: 0xfabfb5da for the testnet or // 0xf9beb4d9 for production // - 12 byte command in ASCII // - 4 byte payload size // - 4 byte checksum // - Payload data // // The checksum is the first 4 bytes of a SHA256 hash of the message payload. It isn't // present for all messages, notably, the first one on a connection. // // Satoshi's implementation ignores garbage before the magic header bytes. We have to do the same because // sometimes it sends us stuff that isn't part of any message. SeekPastMagicBytes(@in); // Now read in the header. var header = new byte[_commandLen + 4 + (_usesChecksumming ? 4 : 0)]; var readCursor = 0; while (readCursor < header.Length) { var bytesRead = @in.Read(header, readCursor, header.Length - readCursor); if (bytesRead == -1) { // There's no more data to read. throw new IOException("Socket is disconnected"); } readCursor += bytesRead; } var cursor = 0; // The command is a NULL terminated string, unless the command fills all twelve bytes // in which case the termination is implicit. var mark = cursor; for (; header[cursor] != 0 && cursor - mark < _commandLen; cursor++) { } var commandBytes = new byte[cursor - mark]; Array.Copy(header, mark, commandBytes, 0, commandBytes.Length); for (var i = 0; i < commandBytes.Length; i++) { // Emulate ASCII by replacing extended characters with question marks. if (commandBytes[i] >= 0x80) { commandBytes[i] = 0x3F; } } var command = Encoding.UTF8.GetString(commandBytes, 0, commandBytes.Length); cursor = mark + _commandLen; var size = Utils.ReadUint32(header, cursor); cursor += 4; if (size > Message.MaxSize) { throw new ProtocolException("Message size too large: " + size); } // Old clients don't send the checksum. var checksum = new byte[4]; if (_usesChecksumming) { // Note that the size read above includes the checksum bytes. Array.Copy(header, cursor, checksum, 0, 4); } // Now try to read the whole message. readCursor = 0; var payloadBytes = new byte[size]; while (readCursor < payloadBytes.Length - 1) { var bytesRead = @in.Read(payloadBytes, readCursor, (int)(size - readCursor)); if (bytesRead == -1) { throw new IOException("Socket is disconnected"); } readCursor += bytesRead; } // Verify the checksum. if (_usesChecksumming) { var hash = Utils.DoubleDigest(payloadBytes); if (checksum[0] != hash[0] || checksum[1] != hash[1] || checksum[2] != hash[2] || checksum[3] != hash[3]) { throw new ProtocolException("Checksum failed to verify, actual " + Utils.BytesToHexString(hash) + " vs " + Utils.BytesToHexString(checksum)); } } if (_log.IsDebugEnabled) { _log.DebugFormat("Received {0} byte '{1}' message: {2}", size, command, Utils.BytesToHexString(payloadBytes) ); } try { return(MakeMessage(command, payloadBytes)); } catch (Exception e) { throw new ProtocolException("Error deserializing message " + Utils.BytesToHexString(payloadBytes) + Environment.NewLine + e.Message, e); } }