void SetData(UInt32 Length, byte opCode, byte Flags) { this.Length = Length; this.opCode = opCode; this.Flags = Flags; this.Data = new byte[6]; using (var stream = new MemoryStream(this.Data)) { stream.WriteValueU32(this.Length, false); stream.WriteValueU8(this.opCode); stream.WriteValueU8(this.Flags); this.Data = stream.ToArray(); stream.Flush(); } }
/// <summary> /// For POW coins - used to format wallet address for use in generation transaction's output /// </summary> /// <param name="address"></param> /// <example> /// nodejs: https://github.com/zone117x/node-stratum-pool/blob/dfad9e58c661174894d4ab625455bb5b7428881c/lib/util.js#L264 /// nodejs: https://codio.com/raistlinthewiz/bitcoin-coinbase-serializer-wallet-address-to-script /// </example> /// <returns></returns> public static byte[] CoinAddressToScript(string address) { byte[] decoded; try { decoded = Base58.Decode(address); } catch (AddressFormatException) { Log.Error("Base58 decode failed for address {0:l}", address); return null; } if (decoded.Length != 25) { Log.Error("invalid address length for {0:l}", address); return null; } var pubkey = decoded.Slice(1, -4); byte[] result; using (var stream = new MemoryStream()) { stream.WriteValueU8(0x76); stream.WriteValueU8(0xa9); stream.WriteValueU8(0x14); stream.WriteBytes(pubkey); stream.WriteValueU8(0x88); stream.WriteValueU8(0xac); result = stream.ToArray(); } return result; }
/// <summary> /// For POS coins - used to format wallet address pubkey to use in generation transaction's output. /// </summary> /// <param name="key"></param> /// <example> /// nodejs: https://github.com/zone117x/node-stratum-pool/blob/3586ec0d7374b2acc5a72d5ef597da26f0e39d54/lib/util.js#L243 /// nodejs: http://runnable.com/me/VCFHE0RrZnwbsQ6y /// </example> /// <returns></returns> public static byte[] PubKeyToScript(string key) { var pubKey = key.HexToByteArray(); if (pubKey.Length != 33) { Log.Error("invalid pubkey length for {0:l}", key); return null; } byte[] result; using (var stream = new MemoryStream()) { stream.WriteValueU8(0x21); stream.WriteBytes(pubKey); stream.WriteValueU8(0xac); result = stream.ToArray(); } return result; }
/// <summary> /// For POW coins - used to format wallet address for use in generation transaction's output /// </summary> /// <param name="address"></param> /// <example> /// nodejs: https://github.com/zone117x/node-stratum-pool/blob/dfad9e58c661174894d4ab625455bb5b7428881c/lib/util.js#L264 /// </example> /// <returns></returns> public static byte[] CoinAddressToScript(string address) { // TODO: implement a test for it! var decoded = Base58.Decode(address); if (decoded.Length != 25) Log.Error("invalid address length for: " + address); var pubkey = decoded.Slice(1, -4); byte[] result; using (var stream = new MemoryStream()) { stream.WriteValueU8(0x76); stream.WriteValueU8(0xa9); stream.WriteValueU8(0x14); stream.WriteBytes(pubkey); stream.WriteValueU8(0x88); stream.WriteValueU8(0xac); result = stream.ToArray(); } return result; }
/// <summary> /// Encoded an integer to save space. /// </summary> /// <remarks> /// Integer can be encoded depending on the represented value to save space. Variable length integers always precede /// an array/vector of a type of data that may vary in length. Longer numbers are encoded in little endian. /// </remarks> /// <specification>https://en.bitcoin.it/wiki/Protocol_specification#Variable_length_integer</specification> /// <example> /// nodejs: https://c9.io/raistlinthewiz/bitcoin-coinbase-varint-nodejs /// </example> /// <returns></returns> public static byte[] VarInt(UInt32 value) { if (value < 0xfd) return new[] { (byte)value }; byte[] result; using (var stream = new MemoryStream()) { if (value < 0xffff) { stream.WriteValueU8(0xfd); stream.WriteValueU16(((UInt16)value).LittleEndian()); } else if (value < 0xffffffff) { stream.WriteValueU8(0xfe); stream.WriteValueU32(value.LittleEndian()); } else { stream.WriteValueU8(0xff); stream.WriteValueU16(((UInt16)value).LittleEndian()); } result = stream.ToArray(); } return result; }
/// <summary> /// Creates a serialized string used in script signature. /// </summary> /// <remarks> /// </remarks> /// <example> /// python: http://runnable.com/U3Mya-5oZntF5Ira/bitcoin-coinbase-serialize-string-python /// nodejs: https://github.com/zone117x/node-stratum-pool/blob/dfad9e58c661174894d4ab625455bb5b7428881c/lib/util.js#L153 /// </example> /// <param name="input"></param> /// <returns></returns> public static byte[] SerializeString(string input) { if (input.Length < 253) return ArrayHelpers.Combine(new[] { (byte)input.Length }, Encoding.UTF8.GetBytes(input)); // if input string is >=253, we need need a special format. byte[] result; using (var stream = new MemoryStream()) { if (input.Length < 0x10000) { stream.WriteValueU8(253); stream.WriteValueU16(((UInt16)input.Length).LittleEndian()); // write packed length. } else if ((long)input.Length < 0x100000000) { stream.WriteValueU8(254); stream.WriteValueU32(((UInt32)input.Length).LittleEndian()); // write packed length. } else { stream.WriteValueU8(255); stream.WriteValueU16(((UInt16)input.Length).LittleEndian()); // write packed length. } stream.WriteString(input); result = stream.ToArray(); } return result; }
public Stream Serialize() { MemoryStream data = new MemoryStream(); uint dataSize = 0; // Header stuff data.WriteValueU32(0x39444350); data.WriteValueEnum<PCD9.Format>(this.Format); data.Seek(4, SeekOrigin.Current); //skip dataSize for now data.WriteValueU32(this.Unknown0C); data.WriteValueU16(this.Width); data.WriteValueU16(this.Height); data.WriteValueU8(this.BPP); data.WriteValueU8((byte)(this.Mipmaps.Count - 1)); data.WriteValueU16(this.Unknown16); // Data stuff //TODO sort to make sure the biggest is first? will the order ever change? for (int i = 0; i < this.Mipmaps.Count; i++) { // Write image data data.WriteBytes(this.Mipmaps[i].Data); // Add length to total dataSize += (uint)this.Mipmaps[i].Data.Length; } // Write dataSize data.Seek(8, SeekOrigin.Begin); data.WriteValueU32(dataSize); data.Position = 0; return data; }
public Stream Serialize() { MemoryStream data = new MemoryStream(); uint sectionCount = (uint)this.Sections.Count; Stream[] resolvers = new MemoryStream[sectionCount]; // for serialized resolvers uint unknown04_size = 0; uint unknown08_size = 0; // Write DRM Header data.WriteValueU32(this.Version, this.Endianness); data.WriteValueU32(0); // skip for now data.WriteValueU32(0); // skip for now data.WriteValueU32(0); // unknown0C data.WriteValueU32(0); // unknown10 data.WriteValueU32(sectionCount, this.Endianness); // Write DRM Section Headers for (int i = 0; i < sectionCount; i++) { DRM.Section section = this.Sections[i]; // Serialize resolvers to get length, data will be used later uint resolverLen; if (section.Resolver != null) { resolvers[i] = section.Resolver.Serialize(this.Endianness); resolverLen = (uint)resolvers[i].Length; } else { resolvers[i] = null; resolverLen = 0; } data.WriteValueU32((uint)section.Data.Length, this.Endianness); data.WriteValueU8((byte)section.Type); data.WriteValueU8(section.Unknown05); data.WriteValueU16(section.Unknown06, this.Endianness); data.WriteValueU32((uint)section.Flags | (resolverLen << 8), this.Endianness); data.WriteValueU32(section.Id, this.Endianness); data.WriteValueU32(section.Unknown10, this.Endianness); } // Write Unknown08s for (int i = 0; i < Unknown08s.Count; i++) { unknown08_size += ((uint)Unknown08s[i].Length + 1); data.WriteStringZ(Unknown08s[i]); } // Write Unknown04s for (int i = 0; i < Unknown04s.Count; i++) { unknown04_size += ((uint)Unknown04s[i].Length + 1); data.WriteStringZ(Unknown04s[i]); } // Write DRM Section Data for (int i = 0; i < sectionCount; i++) { if (resolvers[i] != null) { data.WriteFromStream(resolvers[i], resolvers[i].Length); } data.WriteFromStream(this.Sections[i].Data, this.Sections[i].Data.Length); this.Sections[i].Data.Position = 0; } // Go back and write unknowns length data.Seek(4, SeekOrigin.Begin); data.WriteValueU32(unknown04_size); data.WriteValueU32(unknown08_size); data.Position = 0; return data; }