Пример #1
0
        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");
            }
        }
Пример #2
0
        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()));
        }
Пример #3
0
        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);
        }
Пример #4
0
        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()));
        }
Пример #5
0
        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);
        }
Пример #6
0
        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());
        }
Пример #7
0
 public static byte[] EncodeHex(string _hex) => EncodeBytes(HexPlus.HexStringToByteArray(_hex));
Пример #8
0
 public byte[] ToData()
 {
     return(HexPlus.HexStringToByteArray(this.address));
 }
Пример #9
0
 public byte[] ToBytes() => HexPlus.HexStringToByteArray(base.Text.Substring(2));
Пример #10
0
        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("-", ""));
        }
Пример #11
0
        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);
        }
Пример #12
0
 public static string Encode(string _hexString)
 {
     return(Encode(HexPlus.HexStringToByteArray(_hexString)));
 }
Пример #13
0
        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()));
        }