public KzExtPrivKey SetMaster(KzUInt256 privkey, KzUInt256 chaincode, IEnumerable <KzKeyPath> required = null) { _privkey = new KzPrivKey(privkey); _chaincode = chaincode; _depth = 0; _child = 0; _fingerprint = 0; if (_privkey == null || !_privkey.IsValid) { goto fail; } // Verify that all the required derivation paths yield valid keys. if (required != null) { foreach (var r in required) { if (Derive(r) == null) { goto fail; } } } return(this); fail: return(null); }
KzUInt256 ComputeHash(KzMerkleTreeNode n) { // This ToArray call could be eliminated. var h = new KzUInt256(); KzHashes.HASH256(n.LeftRightHashes, h.Span); return(h); }
/// <summary> /// New nodes are always created on the left branch from their parent node (when they get one). /// They always start with a valid left hash (either Tx hash or left subtree hash. /// They always start without a valid right hash. /// </summary> public KzMerkleTreeNode(KzUInt256 newLeftHash, KzMerkleTreeNode child) { SetLeftHash(newLeftHash); if (child != null) { child.Parent = this; } }
public bool Verify(KzUInt256 hash, ReadOnlySpan <byte> sig) { if (!IsValid) { return(false); } return(secp256k1.PublicKeyVerify(hash.Span, sig, _vch.AsSpan())); }
/// <summary> /// Computes double SHA256 of data: SHA256(SHA256(data)) /// </summary> /// <param name="data">Input: bytes to be hashed.</param> /// <param name="hash">Output: SHA256 of SHA256 of data.</param> public static void HASH256(this ReadOnlySpan <byte> data, Span <byte> hash) { var h1 = new KzUInt256(); using (var sha = new SHA256Managed()) { TransformFinalBlock(sha, data, h1.Span); TransformFinalBlock(sha, h1.Span, hash); } }
/// <summary> /// Throws ArgumentException if a is null or not 32 bytes long. /// </summary> /// <param name="a"></param> /// <returns></returns> public static KzUInt256 ToKzUInt256(this byte[] a) { if (a?.Length != 32) { throw new ArgumentException(); } var i = new KzUInt256(); a.AsSpan().CopyTo(i.Span); return(i); }
public (bool ok, byte[] sig) Sign(KzUInt256 hash) { if (!fValid) { return(false, null); } var(ok, sig) = secp256k1.PrivateKeySign(hash.Span, keydata.Span); return(ok, sig); }
/// <summary> /// The complement function is KzPrivKey's SignCompact. /// </summary> /// <param name="hash"></param> /// <param name="sig"></param> /// <returns></returns> public bool RecoverCompact(KzUInt256 hash, ReadOnlySpan<byte> sig) { var (ok, vch) = secp256k1.PublicKeyRecoverCompact(hash.Span, sig); if (!ok) Invalidate(); else _vch = vch; return ok; }
public static (bool ok, KzPubKey key) FromRecoverCompact(KzUInt256 hash, ReadOnlySpan <byte> sig) { var key = new KzPubKey(); var ok = key.RecoverCompact(hash, sig); if (!ok) { key = null; } return(ok, key); }
public KzBlockHeader( Int32 version, KzUInt256 hashPrevBlock, KzUInt256 hashMerkleRoot, UInt32 time, UInt32 bits, UInt32 nonce ) { _version = version; _hashPrevBlock = hashPrevBlock; _hashMerkleRoot = hashMerkleRoot; _time = time; _bits = bits; _nonce = nonce; }
/// <summary> /// Hash used to implement BIP 32 key derivations. /// </summary> /// <param name="chainCode"></param> /// <param name="nChild"></param> /// <param name="header"></param> /// <param name="data"></param> /// <param name="output">512 bit, 64 byte hash.</param> public static void BIP32Hash(KzUInt256 chainCode, uint nChild, byte header, ReadOnlySpan <byte> data, Span <byte> output) { var len = data.Length; var buf = new byte[1 + len + 4]; // header, data, nChild var s = buf.AsSpan(); s[0] = header; data.CopyTo(s.Slice(1, len)); var num = s.Slice(1 + len, 4); num[0] = (byte)((nChild >> 24) & 0xFF); num[1] = (byte)((nChild >> 16) & 0xFF); num[2] = (byte)((nChild >> 8) & 0xFF); num[3] = (byte)((nChild >> 0) & 0xFF); HMACSHA512(chainCode.Span, s, output); }
async public Task <KzTransaction> GetTransactionsByHash(KzUInt256 txId) { var url = $"https://api.whatsonchain.com/v1/bsv/{Kz.Params.strNetworkID}/tx/hash/{txId}"; var json = await _HttpClient.GetStringAsync(url); var woctx = JsonConvert.DeserializeObject <Transaction>(json); var tx = new KzTransaction(); var ros = new ReadOnlySequence <byte>(woctx.hex.HexToBytes()); if (!tx.TryReadTransaction(ref ros)) { tx = null; } return(tx); }
public (bool ok, KzPrivKey keyChild, KzUInt256 ccChild) Derive(uint nChild, KzUInt256 cc) { if (!IsValid || !IsCompressed) { goto fail; } var vout = new byte[64]; if (nChild < HardenedBit) { // Not hardened. var pubkey = GetPubKey(); Debug.Assert(pubkey.ReadOnlySpan.Length == 33); KzHashes.BIP32Hash(cc, nChild, pubkey.ReadOnlySpan[0], pubkey.ReadOnlySpan.Slice(1), vout); } else { // Hardened. Debug.Assert(keydata.Span.Length == 32); KzHashes.BIP32Hash(cc, nChild, 0, keydata.Span, vout); } var sout = vout.AsSpan(); var ccChild = new KzUInt256(); sout.Slice(32, 32).CopyTo(ccChild.Span); var dataChild = new KzUInt256(); keydata.Span.CopyTo(dataChild.Span); var ok = secp256k1.PrivKeyTweakAdd(dataChild.Span, sout.Slice(0, 32)); if (!ok) { goto fail; } var keyChild = new KzPrivKey(dataChild); return(ok, keyChild, ccChild); fail: return(false, null, KzUInt256.Zero); }
public (bool ok, KzPubKey keyChild, KzUInt256 ccChild) Derive(uint nChild, KzUInt256 cc) { if (!IsValid || !IsCompressed || nChild >= HardenedBit) { goto fail; } var vout = new byte[64]; KzHashes.BIP32Hash(cc, nChild, ReadOnlySpan[0], ReadOnlySpan.Slice(1), vout); var sout = vout.AsSpan(); var ccChild = new KzUInt256(); sout.Slice(32, 32).CopyTo(ccChild.Span); var pkbs = new byte[64]; if (!secp256k1.PublicKeyParse(pkbs.AsSpan(), ReadOnlySpan)) { goto fail; } if (!secp256k1.PubKeyTweakAdd(pkbs.AsSpan(), sout.Slice(0, 32))) { goto fail; } var dataChild = new byte[33]; if (!secp256k1.PublicKeySerialize(dataChild.AsSpan(), pkbs, Flags.SECP256K1_EC_COMPRESSED)) { goto fail; } var keyChild = new KzPubKey(true); dataChild.AsSpan().CopyTo(keyChild.Span); return(true, keyChild, ccChild); fail: return(false, null, KzUInt256.Zero); }
public KzBlock( KzTransaction[] txs, Int32 version, KzUInt256 hashPrevBlock, KzUInt256 hashMerkleRoot, UInt32 time, UInt32 bits, UInt32 nonce ) : base( version, hashPrevBlock, hashMerkleRoot, time, bits, nonce ) { _txs = txs; }
public KzOutPoint(KzUInt256 txid, Int32 n) { _txid = txid; _n = n; }
public KzPrivKey(KzUInt256 v, bool compressed = true) { Set(v.ReadOnlySpan, compressed); }
public void SetRightHash(KzUInt256 hash) { RightHash = hash; HasRight = true; }
public void SetLeftHash(KzUInt256 hash) { LeftHash = hash; HasLeft = true; }
public KzRpcBlockRaw GetBlockHeaderRaw(KzUInt256 hash) => GetBlockHeaderRaw(hash.ToString());
public bool Equals(KzUInt256 o) => n0 == o.n0 && n1 == o.n1 && n2 == o.n2 && n3 == o.n3;
public bool Verify(KzUInt256 hash, ReadOnlySpan<byte> sig) { if (!IsValid || sig.Length == 0) return false; return secp256k1.PublicKeyVerify(hash.Span, sig, _vch.AsSpan()); }
public IKzWriter Add(KzUInt256 v) { Length += 32; return(this); }
public IKzWriter Add(KzUInt256 v) { v.Span.CopyTo(Memory.Span.Slice(Length)); Length += 32; return(this); }
/// <summary> /// Returns a new extended private key to be a master (depth 0) with the given private key and chaincode and verifies required key paths. /// </summary> /// <param name="privkey">Master private key.</param> /// <param name="chaincode">Master chaincode.</param> /// <param name="required">if not null, each key path will be verified as valid on the generated key or returns null.</param> /// <returns>Returns new key unless required key paths aren't valid for specified key in which case null is returned.</returns> public static KzExtPrivKey Master(KzUInt256 privkey, KzUInt256 chaincode, IEnumerable <KzKeyPath> required = null) => new KzExtPrivKey().SetMaster(privkey, chaincode, required);
public IKzWriter Add(KzUInt256 v) { _alg.TransformBlock(v.ReadOnlySpan); return(this); }
public KzOutPoint(KzUInt256 hashTx, Int32 n) { _HashTx = hashTx; _N = n; }