public static string Publics2PublicScript(string[] _publics, int _required) { try { List <byte> _bytes = new List <byte>(); _bytes.Add((byte)(80 + _required)); foreach (string _public in _publics) { byte[] _keyBytes = HexPlus.HexStringToByteArray(_public); _bytes.AddRange(((BigInteger)_keyBytes.Length).ToByteArray()); _bytes.AddRange(_keyBytes); } _bytes.Add((byte)(80 + _publics.Length)); _bytes.Add(0xae); return(HexPlus.ByteArrayToHexString(_bytes.ToArray())); } catch { throw new Exception("Public keys convert to PublicScript error"); } }
public static string Private2Wif(string _private, bool _mainnet, bool _compressed) { List <byte> _resultArray = new List <byte>(); _resultArray.Add((byte)(_mainnet ? 0x80 : 0xef)); _resultArray.AddRange(HexPlus.HexStringToByteArray(_private)); if (_compressed) { _resultArray.Add(0x01); } _resultArray.AddRange(SHA.EncodeSHA256(SHA.EncodeSHA256(_resultArray.ToArray())).Take(4).ToArray()); return(Base58.Encode(_resultArray.ToArray())); }
public static Address GetMultisignAddress(string[] _privates = null, int _required = 1, bool _mainnet = true) { if (_privates == null) { _privates = new string[1]; } if (_privates.Length < _required) { throw new ArgumentException("Key count lower then require count"); } for (int i = 0; i < _privates.Length; i++) { _privates[i] = string.IsNullOrWhiteSpace(_privates[i]) ? RandomPlus.RandomHex(64) : _privates[i]; } string _publicScript = Privates2PublicScript(_privates, _required); byte[] _signArray = HexPlus.HexStringToByteArray(_publicScript); RIPEMD160Managed _ripemd = new RIPEMD160Managed(); byte[] _ripemdHashed = _ripemd.ComputeHash(SHA.EncodeSHA256(_signArray)); byte[] _addedVersion = new byte[_ripemdHashed.Length + 1]; _addedVersion[0] = (byte)(_mainnet ? (byte)5 : (byte)196); Array.Copy(_ripemdHashed, 0, _addedVersion, 1, _ripemdHashed.Length); byte[] _shaHashed = SHA.EncodeSHA256(SHA.EncodeSHA256(_addedVersion)); Array.Resize(ref _shaHashed, 4); byte[] _result = new byte[_addedVersion.Length + _shaHashed.Length]; Array.Copy(_addedVersion, 0, _result, 0, _addedVersion.Length); Array.Copy(_shaHashed, 0, _result, _addedVersion.Length, _shaHashed.Length); for (int i = 0; i < _privates.Length; i++) { _privates[i] = Private2Wif(_privates[i], _mainnet, true); } Address _address = new Address { Text = Base58.Encode(_result), Public = _publicScript, Privates = _privates }; return(_address); }
public static string Public2PKSH(string _public, bool _multiSig = false) { List <byte> _hashed = HexPlus.HexStringToByteArray(_public).ToList(); _hashed.Insert(0, 0x14);//PKSH A9 -> do a RipeMD160 on the top stack item 14->push hex 14(decimal 20) bytes on stack _hashed.Insert(0, 0xa9); if (_multiSig) { _hashed.Add(0x87); } else { _hashed.Insert(0, 0x76); _hashed.Add(0x88); _hashed.Add(0xac); } _hashed.InsertRange(0, BigInteger.Parse(_hashed.Count.ToString()).ToByteArray()); return(HexPlus.ByteArrayToHexString(_hashed.ToArray())); }
public static Address GenerateAddress(string _privateKey = "", bool _mainNet = true) { _privateKey = _privateKey == "" ? RandomPlus.RandomHex(64) : _privateKey; BigInteger _privateInt = BigInteger.Parse("0" + _privateKey, System.Globalization.NumberStyles.HexNumber); byte[] _publicKey = Secp256k1.PrivateKeyToPublicKey(_privateInt); SHA256Managed _sha256 = new SHA256Managed(); RIPEMD160Managed _ripemd = new RIPEMD160Managed(); byte[] _ripemdHashed = _ripemd.ComputeHash(_sha256.ComputeHash(_publicKey)); byte[] _addedVersion = new byte[_ripemdHashed.Length + 1]; _addedVersion[0] = (byte)(_mainNet ? 0x00 : 0x6f); Array.Copy(_ripemdHashed, 0, _addedVersion, 1, _ripemdHashed.Length); byte[] _shaHashed = _sha256.ComputeHash(_sha256.ComputeHash(_addedVersion)); Array.Resize(ref _shaHashed, 4); byte[] _result = new byte[_addedVersion.Length + _shaHashed.Length]; Array.Copy(_addedVersion, 0, _result, 0, _addedVersion.Length); Array.Copy(_shaHashed, 0, _result, _addedVersion.Length, _shaHashed.Length); string _key1 = string.Join("", (_mainNet ? "80" : "ef"), _privateKey); string _key2 = HexPlus.ByteArrayToHexString(SHA.EncodeSHA256(SHA.EncodeSHA256(HexPlus.HexStringToByteArray(_key1))).Take(4).ToArray()); Address _address = new Address(); _address.Text = Base58.Encode(_result); _address.PublicKey = HexPlus.ByteArrayToHexString(_publicKey); _address.PrivateKey = Base58.Encode(_key1 + _key2); _address.Text = (_mainNet ? (_address.Text.StartsWith("1") ? "" : "1") : "") + _address.Text; return(_address); }
public string ToSignedHex(string _private) { byte[] _basicRaw = RLP.EncodeList(new byte[][] { RLP.EncodeUInt(this.Nonce), RLP.EncodeBigInteger(this.GasPrice.ToGWei()), RLP.EncodeUInt(this.GasLimit), RLP.EncodeHex(this.Address), RLP.EncodeBigInteger(this.Value.Integer), RLP.EncodeString(this.DataHex), RLP.EncodeInt((int)this.ChainId), RLP.EncodeString(""), RLP.EncodeString("") }); byte[] _basicHashedRaw = new Keccak256().Compute(_basicRaw); BigInteger _limit = BigInteger.Pow(BigInteger.Parse("2"), 256), _r = BigInteger.Zero, _e = BigInteger.Zero, _s = BigInteger.Zero, _k = BigInteger.Zero, _recid = BigInteger.Zero; while (true) { _k = BigInteger.Zero; if (_k == BigInteger.Zero) { byte[] kBytes = new byte[33]; rngCsp.GetBytes(kBytes); kBytes[32] = 0; _k = new BigInteger(kBytes); } if (_k.IsZero || _k >= Secp256k1.N) { continue; } var _gk = Secp256k1.G.Multiply(_k); _r = _gk.X % Secp256k1.N; _recid = _gk.Y & 1; if (_r == BigInteger.Zero) { throw new Exception("Sign failed because R is Zero."); } if (_r >= _limit || _r.Sign == 0) { Thread.Sleep(100); continue; } _e = Lion.BigNumberPlus.HexToBigInt(BitConverter.ToString(_basicHashedRaw).Replace("-", "")); _s = ((_e + (_r * Lion.BigNumberPlus.HexToBigInt(_private))) * BigInteger.ModPow(_k, Secp256k1.N - 2, Secp256k1.N)) % Secp256k1.N; if (_s == BigInteger.Zero) { throw new Exception("Sign failed because S is Zero."); } if (_s > Secp256k1.HalfN) { _recid = _recid ^ 1; } if (_s.CompareTo(Secp256k1.HalfN) > 0) { _s = Secp256k1.N - _s; } if (_s >= _limit || _s.Sign == 0 || _r.ToString("X").StartsWith("0") || _s.ToString("X").StartsWith("0")) { Thread.Sleep(100); continue; } break; } BigInteger _v = BigInteger.Parse(((int)this.ChainId).ToString()) * 2 + _recid + 35; byte[] _signed = RLP.EncodeList(new byte[][] { RLP.EncodeUInt(this.Nonce), RLP.EncodeBigInteger(this.GasPrice.ToGWei()), RLP.EncodeUInt(this.GasLimit), RLP.EncodeHex(this.Address), RLP.EncodeBigInteger(this.Value.Integer), RLP.EncodeString(this.DataHex), RLP.EncodeBigInteger(_v), RLP.EncodeBytes(HexPlus.HexStringToByteArray(_r.ToString("X"))), RLP.EncodeBytes(HexPlus.HexStringToByteArray(_s.ToString("X"))) }); return(HexPlus.ByteArrayToHexString(_signed).ToLower()); }
public static byte[] EncodeHex(string _hex) => EncodeBytes(HexPlus.HexStringToByteArray(_hex));
public byte[] ToData() { return(HexPlus.HexStringToByteArray(this.address)); }
public byte[] ToBytes() => HexPlus.HexStringToByteArray(base.Text.Substring(2));
public static string Public2P2SH(string _public) { List <byte> _hash160 = new RIPEMD160Managed().ComputeHash(SHA.EncodeSHA256(HexPlus.HexStringToByteArray(_public))).ToList(); _hash160.InsertRange(0, ((BigInteger)_hash160.Count).ToByteArray()); _hash160.Insert(0, 0x00); _hash160.Insert(0, 0x16); _hash160.Insert(0, 0x17); return(BitConverter.ToString(_hash160.ToArray()).ToLower().Replace("-", "")); }
public static Address GetLegacyAddress(string _private = "", bool _mainnet = true) { _private = _private == "" ? RandomPlus.RandomHex(64) : _private; BigInteger _privateInt = BigInteger.Parse("0" + _private, NumberStyles.HexNumber); byte[] _public = Secp256k1.PrivateKeyToPublicKey(_privateInt, false); RIPEMD160Managed _ripemd = new RIPEMD160Managed(); byte[] _ripemdHashed = _ripemd.ComputeHash(SHA.EncodeSHA256(_public)); byte[] _addedVersion = new byte[_ripemdHashed.Length + 1]; _addedVersion[0] = (byte)(_mainnet ? 0x00 : 0x6f); Array.Copy(_ripemdHashed, 0, _addedVersion, 1, _ripemdHashed.Length); byte[] _shaHashed = SHA.EncodeSHA256(SHA.EncodeSHA256(_addedVersion)); Array.Resize(ref _shaHashed, 4); byte[] _result = new byte[_addedVersion.Length + _shaHashed.Length]; Array.Copy(_addedVersion, 0, _result, 0, _addedVersion.Length); Array.Copy(_shaHashed, 0, _result, _addedVersion.Length, _shaHashed.Length); string _key1 = string.Join("", (_mainnet ? "80" : "ef"), _private); string _key2 = HexPlus.ByteArrayToHexString(SHA.EncodeSHA256(SHA.EncodeSHA256(HexPlus.HexStringToByteArray(_key1))).Take(4).ToArray()); Address _address = new Address { Text = Base58.Encode(_result), Public = HexPlus.ByteArrayToHexString(_public), Private = Base58.Encode(_key1 + _key2) }; return(_address); }
public static string Encode(string _hexString) { return(Encode(HexPlus.HexStringToByteArray(_hexString))); }
public string ToSignedHex(decimal _maxFee = 0.0001M) { if (this.Vouts.Count <= 0) { throw new Exception("Vout is empty."); } if (this.Vins.Count <= 0) { throw new Exception("Vin is empty."); } decimal _voutAmount = this.Vouts.Sum(t => t.Amount); decimal _vinAmount = this.Vins.Sum(t => t.Amount); if (_vinAmount <= 0M) { throw new Exception("Vin amount is zero."); } if (_voutAmount <= 0M) { throw new Exception("Vout amount is zero."); } if (_vinAmount >= _voutAmount) { throw new Exception("Vout amount less than Vin amount."); } if (_voutAmount - _vinAmount > _maxFee) { throw new Exception("Fee is too much."); } byte[] _voutCount = BigInteger.Parse(this.Vouts.Count.ToString()).ToByteArray(true, false); //base script: version/input count List <byte> _voutHead = new List <byte>(); _voutHead.AddAndPadRight(5, 0x0, 0x02); //version; _voutHead.Add(0x01); _voutHead.AddRange(_voutCount); //start from output,not contains sign,not contains hash type List <byte> _vinUnsigned = new List <byte>(); foreach (TransactionVin _vin in this.Vins) { _vinUnsigned.AddAndPadRight(8, 0x0, BigInteger.Parse((100000000M * _vin.Amount).ToString("0")).ToByteArray()); _vinUnsigned.AddRange(HexPlus.HexStringToByteArray(Address.Address2PKSH(_vin.Address))); } //base script sig = base+input+output+hashtype //pay script sig = ecdsa(base script sig) byte[] _seq = new byte[] { 0xff, 0xff, 0xff, 0xff }; byte[] _seqHash = SHA.EncodeSHA256(SHA.EncodeSHA256(_seq)); byte[] _vinHash = SHA.EncodeSHA256(SHA.EncodeSHA256(_vinUnsigned.ToArray())); List <byte> _preVouts = new List <byte>(); List <byte> _seqs = new List <byte>(); byte[] vinCount = BigInteger.Parse(this.Vins.Count.ToString()).ToByteArray(true, false); foreach (TransactionVout _vout in this.Vouts) { _preVouts.AddRange(_vout.Scripts); _seqs.AddRange(_seq); } byte[] _preVoutHash = SHA.EncodeSHA256(SHA.EncodeSHA256(_preVouts.ToArray())); byte[] _seqHashs = SHA.EncodeSHA256(SHA.EncodeSHA256(_seqs.ToArray())); foreach (TransactionVout _vout in this.Vouts) { List <byte> _voutUnsigned = new List <byte>(); _voutUnsigned.AddAndPadRight(4, 0x0, 0x02); if (_vout.IsWitness) { //witness transaction join HASH_ALL(hash_outputs/hash_seqs/hash_inputs) to transaction scripts _voutUnsigned.AddRange(_preVoutHash); _voutUnsigned.AddRange(_seqHashs); _voutUnsigned.AddRange(_vout.Scripts); _voutUnsigned.AddRange(HexPlus.HexStringToByteArray(_vout.ScriptPKSH)); _voutUnsigned.AddAndPadRight(8, 0x0, BigInteger.Parse((100000000M * _vout.Amount).ToString("0")).ToByteArray()); _voutUnsigned.AddRange(new byte[] { 0xff, 0xff, 0xff, 0xff }); _voutUnsigned.AddRange(_vinHash); } else { //legacy transaction HASH_ALL(transaction scripts) _voutUnsigned.AddRange(_voutCount); foreach (TransactionVout _childVout in this.Vouts) { _voutUnsigned.AddRange(_childVout.Scripts); //each inputs script in scripts,not current input skip PKSH,replace with 0x00 if (_childVout.TxId != _vout.TxId || _childVout.TxIndex != _vout.TxIndex) { _voutUnsigned.Add(0x00); } else { _voutUnsigned.AddRange(HexPlus.HexStringToByteArray(_childVout.ScriptPKSH)); } _voutUnsigned.AddRange(new byte[] { 0xff, 0xff, 0xff, 0xff }); } _voutUnsigned.AddRange(vinCount); _voutUnsigned.AddRange(_vinUnsigned); } _voutUnsigned.AddAndPadRight(4, 0x0, 0x00); _voutUnsigned.AddAndPadRight(4, 0x0, 0x01); //hash type=HASH_ALL; string _scriptSig = BitConverter.ToString(SHA.EncodeSHA256(SHA.EncodeSHA256(_voutUnsigned.ToArray()))).Replace("-", "").ToLower(); _vout.ScriptSign = HexPlus.HexStringToByteArray(Signature.SignHex(_scriptSig, _vout.Private.Wif)); } _vinUnsigned.InsertRange(0, vinCount); //transaction seq //pay bytes List <byte> _signedRaw = new List <byte>(); _signedRaw.AddRange(_voutHead); foreach (TransactionVout _vout in this.Vouts) { _signedRaw.AddRange(_vout.Scripts); //script per input if (!_vout.IsWitness) { byte[] _publicKeys = HexPlus.HexStringToByteArray(_vout.Private.Public); BigInteger _sigLength = _vout.ScriptSign.Length + (BigInteger)_publicKeys.Length; _signedRaw.AddRange(_sigLength.ToByteArray(true, false)); _signedRaw.AddRange(_vout.ScriptSign.ToArray()); _signedRaw.AddRange(_publicKeys); } else { _signedRaw.AddRange(HexPlus.HexStringToByteArray(_vout.ScriptP2SH)); } _signedRaw.AddRange(_seq); } _signedRaw.AddRange(_vinUnsigned); foreach (TransactionVout _vout in this.Vouts) { if (!_vout.IsWitness) { _signedRaw.Add(0x00); } else { BigInteger _sigLength = BigInteger.Parse(_vout.Private.Public, NumberStyles.HexNumber).ToByteArray().Length + _vout.ScriptSign.Length + 1; _signedRaw.Add(0x02); _signedRaw.AddRange(_vout.ScriptSign.ToArray()); _signedRaw.AddRange(HexPlus.HexStringToByteArray(_vout.Private.Public)); } } _signedRaw.AddAndPadRight(4, 0x0, 0x00); return(HexPlus.ByteArrayToHexString(_signedRaw.ToArray())); }