public static StealthMetadata CreateMetadata(Key ephemKey, BitField bitField = null) { for(uint nonce = 0 ; nonce < uint.MaxValue ; nonce++) { var metadata = new StealthMetadata(ephemKey, nonce); if(bitField == null || bitField.Match(metadata.BitField)) return metadata; } throw new ArgumentException("No nonce can satisfy the given bitfield, use another ephemKey"); }
public StealthPayment(int sigCount, PubKey[] spendPubKeys, Key privateKey, PubKey publicKey, StealthMetadata metadata) { Metadata = metadata; if(sigCount == 1 && spendPubKeys.Length == 1) { var template = new PayToPubkeyHashTemplate(); SpendableScript = template.GenerateScriptPubKey(spendPubKeys[0].Uncover(privateKey, publicKey).ID); } else { var template = new PayToMultiSigTemplate(); SpendableScript = template.GenerateScriptPubKey(sigCount, spendPubKeys.Select(p => p.Uncover(privateKey, publicKey)).ToArray()); } ParseSpendable(); }
public static StealthPayment[] GetPayments(Transaction transaction, PubKey[] spendKeys, BitField bitField, Key scan) { List <StealthPayment> result = new List <StealthPayment>(); for (int i = 0; i < transaction.Outputs.Count - 1; i++) { var metadata = StealthMetadata.TryParse(transaction.Outputs[i].ScriptPubKey); if (metadata != null && bitField.Match(metadata.BitField)) { var payment = new StealthPayment(transaction.Outputs[i + 1].ScriptPubKey, metadata); if (scan != null && spendKeys != null) { if (payment.StealthKeys.Length != spendKeys.Length) { continue; } var expectedStealth = spendKeys.Select(s => s.UncoverReceiver(scan, metadata.EphemKey)).ToList(); foreach (var stealth in payment.StealthKeys) { var match = expectedStealth.FirstOrDefault(expected => expected.ID == stealth.ID); if (match != null) { expectedStealth.Remove(match); } } if (expectedStealth.Count != 0) { continue; } } result.Add(payment); } } return(result.ToArray()); }
public static StealthMetadata TryParse(Script metadata) { StealthMetadata result = new StealthMetadata(); try { if(!Fill(result, metadata)) return null; } catch(Exception) { return null; } return result; }
private static bool Fill(StealthMetadata output, Script metadata) { var ops = metadata.ToOps().ToArray(); if(ops.Length != 2 || ops[0].Code != OpcodeType.OP_RETURN) return false; var data = ops[1].PushData; if(data == null || data.Length != 1 + 4 + 33) return false; MemoryStream ms = new MemoryStream(data); output.Version = ms.ReadByte(); if(output.Version != 6) return false; output.Nonce = ms.ReadBytes(4); output.EphemKey = new PubKey(ms.ReadBytes(33)); output.Script = metadata; output.Hash = Hashes.Hash256(data); var msprefix = new MemoryStream(output.Hash.ToBytes(false)); output.BitField = Utils.ToUInt32(msprefix.ReadBytes(4), true); return true; }
public StealthPayment(Script spendable, StealthMetadata metadata) { Metadata = metadata; SpendableScript = spendable; ParseSpendable(); }
public StealthPayment(int sigCount, PubKey[] spendPubKeys, Key privateKey, PubKey publicKey, StealthMetadata metadata) { Metadata = metadata; if (sigCount == 1 && spendPubKeys.Length == 1) { var template = new PayToPubkeyHashTemplate(); SpendableScript = template.GenerateScriptPubKey(spendPubKeys[0].Uncover(privateKey, publicKey).ID); } else { var template = new PayToMultiSigTemplate(); SpendableScript = template.GenerateScriptPubKey(sigCount, spendPubKeys.Select(p => p.Uncover(privateKey, publicKey)).ToArray()); } ParseSpendable(); }
public bool Match(StealthMetadata metadata) { return Match(metadata.BitField); }
public bool Match(StealthMetadata metadata) { return(Match(metadata.BitField)); }