public PromiseClientSession ReceiveTumblerEscrowedCoin(ScriptCoin escrowedCoin) { AssertState(TumblerClientSessionStates.WaitingTumblerEscrow); var escrow = EscrowScriptPubKeyParameters.GetFromCoin(escrowedCoin); if (escrow == null) { throw new PuzzleException("invalid-escrow"); } if (!escrowedCoin.IsP2SH || escrowedCoin.RedeemType != RedeemType.WitnessV0) { throw new PuzzleException("invalid-escrow"); } var expectedEscrow = GetTumblerEscrowParameters(escrow.Initiator); if (escrow != expectedEscrow) { throw new PuzzleException("invalid-escrow"); } if (escrowedCoin.Amount != Parameters.Denomination) { throw new PuzzleException("invalid-amount"); } InternalState.Status = TumblerClientSessionStates.PromisePhase; var session = new PromiseClientSession(Parameters.CreatePromiseParamaters()); session.SetChannelId(InternalState.ChannelId); session.ConfigureEscrowedCoin(escrowedCoin, InternalState.TumblerEscrowKey); InternalState.TumblerEscrowKey = null; return(session); }
public PromiseClientSession ReceiveTumblerEscrowedCoin(ScriptCoin escrowedCoin) { AssertState(TumblerClientSessionStates.WaitingTumblerEscrow); var escrow = EscrowScriptPubKeyParameters.GetFromCoin(escrowedCoin); var expectedEscrow = new EscrowScriptPubKeyParameters() { Initiator = escrow?.Initiator, Receiver = InternalState.TumblerEscrowKey.PubKey, LockTime = GetCycle().GetTumblerLockTime() }; if (escrow == null || escrow != expectedEscrow) { throw new PuzzleException("invalid-escrow"); } if (escrowedCoin.Amount != Parameters.Denomination) { throw new PuzzleException("invalid-amount"); } InternalState.Status = TumblerClientSessionStates.PromisePhase; var session = new PromiseClientSession(Parameters.CreatePromiseParamaters()); session.SetChannelId(InternalState.ChannelId); session.ConfigureEscrowedCoin(escrowedCoin, InternalState.TumblerEscrowKey); InternalState.TumblerEscrowKey = null; return(session); }
public TrustedBroadcastRequest CreateOfferRedeemTransaction(FeeRate feeRate) { Transaction tx = new Transaction(); tx.LockTime = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin).LockTime; tx.Inputs.Add(new TxIn()); tx.Inputs[0].Sequence = 0; tx.Outputs.Add(new TxOut(InternalState.OfferCoin.Amount, InternalState.RedeemDestination)); tx.Inputs[0].ScriptSig = new Script( Op.GetPushOp(TrustedBroadcastRequest.PlaceholderSignature), Op.GetPushOp(InternalState.OfferCoin.Redeem.ToBytes())); tx.Inputs[0].Witnessify(); var virtualSize = tx.HasWitness ? tx.GetVirtualSize(_Network.Consensus.Options.WitnessScaleFactor) : tx.GetSerializedSize(); tx.Outputs[0].Value -= feeRate.GetFee(virtualSize); var redeemTransaction = new TrustedBroadcastRequest { Key = InternalState.EscrowKey, PreviousScriptPubKey = InternalState.OfferCoin.ScriptPubKey, Transaction = tx }; return(redeemTransaction); }
public override uint256 GetHash() { var escrow = EscrowScriptPubKeyParameters.GetFromCoin(_Escrow); var coin = _Escrow.Clone(); coin.OverrideScriptCode(escrow.GetInitiatorScriptCode()); return(GetTransaction().GetSignatureHash(coin, SigHash.All)); }
private OfferScriptPubKeyParameters CreateOfferScriptParameters() { var escrow = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin); return(new OfferScriptPubKeyParameters { Hashes = InternalState.SolvedPuzzles.Select(p => p.SolutionKey.GetHash()).ToArray(), FulfillKey = InternalState.FulfillKey.PubKey, Expiration = escrow.LockTime, RedeemKey = escrow.Initiator }); }
public TransactionSignature SignEscape() { AssertState(SolverClientStates.Completed); var dummy = new Transaction(); dummy.Inputs.Add(new TxIn(InternalState.EscrowedCoin.Outpoint)); dummy.Outputs.Add(new TxOut()); var escrow = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin); var coin = InternalState.EscrowedCoin.Clone(); coin.OverrideScriptCode(escrow.GetInitiatorScriptCode()); return(dummy.SignInput(InternalState.EscrowKey, coin, SigHash.None | SigHash.AnyoneCanPay)); }
private PubKey AssertValidSignature(TransactionSignature clientSignature, Transaction offer) { var escrow = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin); var coin = InternalState.EscrowedCoin.Clone(); coin.OverrideScriptCode(escrow.GetInitiatorScriptCode()); var signedHash = offer.Inputs.AsIndexedInputs().First().GetSignatureHash(coin, clientSignature.SigHash); var clientKey = InternalState.GetClientEscrowPubKey(); if (!clientKey.Verify(signedHash, clientSignature.Signature)) { throw new PuzzleException("invalid-client-signature"); } return(clientKey); }
public uint256 CreateRealHash(Transaction tx, ScriptCoin _Escrow, Money feeVariation) { /* * Not sure if this is best way to do this, but had to add this for step 7 * when verifying valid Hashes, the server will have to make real hashes, but * it doesn't have access to RealHash class. So I created this function that * takes care of that */ var escrow = EscrowScriptPubKeyParameters.GetFromCoin(_Escrow); var coin = _Escrow.Clone(); coin.OverrideScriptCode(escrow.GetInitiatorScriptCode()); var Transaction = tx.Clone(); Transaction.Outputs[0].Value -= feeVariation; return(Transaction.GetSignatureHash(coin, SigHash.All)); }
private bool IsValidSignature(PuzzleSolution solution, HashBase hash, out ECDSASignature signature) { signature = null; var escrow = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin); try { var key = new XORKey(solution); signature = new ECDSASignature(key.XOR(hash.Commitment.Promise)); var ok = escrow.Initiator.Verify(hash.GetHash(), signature); if (!ok) { signature = null; } return(ok); } catch { } return(false); }
public TransactionSignature SignOffer(OfferInformation offerInformation) { if (offerInformation == null) { throw new ArgumentNullException(nameof(offerInformation)); } AssertState(SolverClientStates.WaitingOffer); var offerScript = new OfferScriptPubKeyParameters { Hashes = _PuzzleElements.OfType <RealPuzzle>().Select(p => p.Commitment.KeyHash).ToArray(), FulfillKey = offerInformation.FulfillKey, Expiration = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin).LockTime, RedeemKey = InternalState.EscrowKey.PubKey }.ToScript(); var escrowCoin = InternalState.EscrowedCoin; var txOut = new TxOut(escrowCoin.Amount - offerInformation.Fee, offerScript.WitHash.ScriptPubKey.Hash); var offerCoin = new Coin(escrowCoin.Outpoint, txOut).ToScriptCoin(offerScript); Transaction tx = new Transaction(); tx.Inputs.Add(new TxIn(escrowCoin.Outpoint)); tx.Outputs.Add(offerCoin.TxOut); var escrow = EscrowScriptPubKeyParameters.GetFromCoin(escrowCoin); escrowCoin = escrowCoin.Clone(); escrowCoin.OverrideScriptCode(escrow.GetInitiatorScriptCode()); var signature = tx.Inputs.AsIndexedInputs().First().Sign(InternalState.EscrowKey, escrowCoin, SigHash.All); InternalState.OfferCoin = offerCoin; InternalState.Status = SolverClientStates.WaitingPuzzleSolutions; return(signature); }
public PubKey GetClientEscrowPubKey() { return(EscrowScriptPubKeyParameters.GetFromCoin(EscrowedCoin).Initiator); }
public OfferInformation CheckBlindedFactors(BlindFactor[] blindFactors, FeeRate feeRate) { if (blindFactors == null) { throw new ArgumentNullException(nameof(blindFactors)); } if (blindFactors.Length != Parameters.RealPuzzleCount) { throw new ArgumentException("Expecting " + Parameters.RealPuzzleCount + " blind factors"); } AssertState(SolverServerStates.WaitingBlindFactor); Puzzle unblindedPuzzle = null; int y = 0; for (int i = 0; i < Parameters.RealPuzzleCount; i++) { var solvedPuzzle = InternalState.SolvedPuzzles[i]; var unblinded = new Puzzle(Parameters.ServerKey, solvedPuzzle.Puzzle).Unblind(blindFactors[i]); if (unblindedPuzzle == null) { unblindedPuzzle = unblinded; } else if (unblinded != unblindedPuzzle) { throw new PuzzleException("Invalid blind factor"); } y++; } InternalState.FulfillKey = new Key(); Transaction dummy = new Transaction(); dummy.AddInput(new TxIn(InternalState.EscrowedCoin.Outpoint)); dummy.Inputs[0].ScriptSig = new Script( Op.GetPushOp(TrustedBroadcastRequest.PlaceholderSignature), Op.GetPushOp(TrustedBroadcastRequest.PlaceholderSignature), Op.GetPushOp(InternalState.EscrowedCoin.Redeem.ToBytes()) ); dummy.Inputs[0].Witnessify(); dummy.AddOutput(new TxOut(InternalState.EscrowedCoin.Amount, new Key().ScriptPubKey.Hash)); var offerTransactionFee = feeRate.GetFee(dummy.GetVirtualSize()); var escrow = InternalState.EscrowedCoin; var escrowInformation = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin); var redeem = new OfferScriptPubKeyParameters { Hashes = InternalState.SolvedPuzzles.Select(p => p.SolutionKey.GetHash()).ToArray(), FulfillKey = InternalState.FulfillKey.PubKey, Expiration = escrowInformation.LockTime, RedeemKey = escrowInformation.Initiator }.ToScript(); var txOut = new TxOut(escrow.Amount - offerTransactionFee, redeem.WitHash.ScriptPubKey.Hash); InternalState.OfferCoin = new Coin(escrow.Outpoint, txOut).ToScriptCoin(redeem); InternalState.Status = SolverServerStates.WaitingFulfillment; return(new OfferInformation { FulfillKey = InternalState.FulfillKey.PubKey, Fee = offerTransactionFee }); }
private static CorrelationId GetCorrelation(SolverServerSession session) { return(EscrowScriptPubKeyParameters.GetFromCoin(session.EscrowedCoin).GetCorrelation()); }