From fc4f2580f17eab881ff3546544d0c76252a7b619 Mon Sep 17 00:00:00 2001 From: dangershony Date: Tue, 14 Nov 2023 18:03:06 +0000 Subject: [PATCH] use relative time locks for penalties --- src/Angor.Test/InvestmentOperationsTest.cs | 6 +++--- src/Angor.Test/ProtocolNew/AngorTestData.cs | 2 +- .../InvestmentIntegrationsTests.cs | 10 +++++----- .../SeederTransactionActionsTest.cs | 6 +++--- .../InvestmentTransactionBuilderTest.cs | 10 +++++----- src/Angor.Test/ScriptThresholdTest.cs | 1 + src/Angor.Test/WalletOperationsTest.cs | 2 +- src/Angor/Client/NetworkConfiguration.cs | 6 +++--- .../Client/Pages/CheckTransactionCode.razor | 4 ++-- src/Angor/Client/Pages/Create.razor | 8 ++++---- src/Angor/Client/Pages/Invest.razor | 2 +- src/Angor/Client/Pages/Penalties.razor | 12 ++++++++++-- src/Angor/Client/Pages/Recover.razor | 10 ++++++---- src/Angor/Client/Pages/View.razor | 2 +- src/Angor/Shared/Models/ProjectInfo.cs | 2 +- .../Shared/Protocol/InvestmentOperations.cs | 2 +- .../Shared/{ => Protocol}/ScriptBuilder.cs | 19 ++++++++++--------- .../ProtocolNew/ISeederTransactionActions.cs | 2 +- .../ProtocolNew/InvestorTransactionActions.cs | 14 ++++++++------ .../Scripts/IInvestmentScriptbuilder.cs | 2 +- .../Scripts/InvestmentScriptBuilder.cs | 14 +++++++++----- .../ProtocolNew/SeederTransactionActions.cs | 6 +++--- .../IInvestmentTransactionBuilder.cs | 2 +- .../InvestmentTransactionBuilder.cs | 4 ++-- 24 files changed, 83 insertions(+), 65 deletions(-) rename src/Angor/Shared/{ => Protocol}/ScriptBuilder.cs (94%) diff --git a/src/Angor.Test/InvestmentOperationsTest.cs b/src/Angor.Test/InvestmentOperationsTest.cs index 7d047d2f..c3f8ef5d 100644 --- a/src/Angor.Test/InvestmentOperationsTest.cs +++ b/src/Angor.Test/InvestmentOperationsTest.cs @@ -419,7 +419,7 @@ public void SpendInvestorRecoveryTest() FounderKey = funderKey, FounderRecoveryKey = funderRecoveryKey, ProjectIdentifier = angorKey, - PenaltyDate = DateTime.UtcNow.AddDays(5), + PenaltyDays = 5, ProjectSeeders = new ProjectSeeders() }, InvestorKey = Encoders.Hex.EncodeData(investorKey.PubKey.ToBytes()), @@ -519,7 +519,7 @@ public void SpendInvestorConsolidatedRecoveryTest() FounderKey = funderKey, FounderRecoveryKey = funderRecoveryKey, ProjectIdentifier = angorKey, - PenaltyDate = DateTime.UtcNow.AddDays(5), + PenaltyDays = 5, ProjectSeeders = new ProjectSeeders { Threshold = 2, @@ -632,7 +632,7 @@ public void SpendSeederConsolidatedRecoveryTest() FounderKey = funderKey, FounderRecoveryKey = funderRecoveryKey, ProjectIdentifier = angorKey, - PenaltyDate = DateTime.UtcNow.AddDays(5), + PenaltyDays = 5, ProjectSeeders = new ProjectSeeders() }, InvestorKey = Encoders.Hex.EncodeData(seederKey.PubKey.ToBytes()), diff --git a/src/Angor.Test/ProtocolNew/AngorTestData.cs b/src/Angor.Test/ProtocolNew/AngorTestData.cs index aa1b6bf0..487ab99e 100644 --- a/src/Angor.Test/ProtocolNew/AngorTestData.cs +++ b/src/Angor.Test/ProtocolNew/AngorTestData.cs @@ -35,7 +35,7 @@ protected ProjectInfo GivenValidProjectInvestmentInfo( WalletWords? words = null projectInvestmentInfo.TargetAmount = 3; projectInvestmentInfo.StartDate = startDate.Value; projectInvestmentInfo.ExpiryDate = startDate.Value.AddDays(5); - projectInvestmentInfo.PenaltyDate = startDate.Value.AddDays(10); + projectInvestmentInfo.PenaltyDays = 10; projectInvestmentInfo.Stages = new List { new() { AmountToRelease = (decimal)0.1, ReleaseDate = startDate.Value.AddDays(1) }, diff --git a/src/Angor.Test/ProtocolNew/InvestmentIntegrationsTests.cs b/src/Angor.Test/ProtocolNew/InvestmentIntegrationsTests.cs index 7f5ea9a7..7ee3fa90 100644 --- a/src/Angor.Test/ProtocolNew/InvestmentIntegrationsTests.cs +++ b/src/Angor.Test/ProtocolNew/InvestmentIntegrationsTests.cs @@ -258,8 +258,8 @@ public void SeederTransaction_EndOfProject_Test() projectInvestmentInfo.FounderRecoveryKey = _derivationOperations.DeriveFounderRecoveryKey(words, 1); projectInvestmentInfo.ProjectIdentifier = _derivationOperations.DeriveAngorKey(projectInvestmentInfo.FounderKey, angorRootKey); - - projectInvestmentInfo.PenaltyDate = DateTime.Now.AddMonths(6); + + projectInvestmentInfo.PenaltyDays = 180; // Create the seeder 1 params var seeder11Key = new Key(); @@ -433,7 +433,7 @@ public void SpendSeederRecoveryTest() FounderKey = funderKey, FounderRecoveryKey = founderRecoveryKey, ProjectIdentifier = angorKey, - PenaltyDate = DateTime.UtcNow.AddDays(5), + PenaltyDays = 5, ProjectSeeders = new ProjectSeeders() }, InvestorKey = Encoders.Hex.EncodeData(seederKey.PubKey.ToBytes()), @@ -449,7 +449,7 @@ public void SpendSeederRecoveryTest() var recoveryTransaction = _seederTransactionActions.BuildRecoverSeederFundsTransaction(investorContext.ProjectInfo, investmentTransaction, - investorContext.ProjectInfo.PenaltyDate, Encoders.Hex.EncodeData(seederFundsRecoveryKey.PubKey.ToBytes())); + investorContext.ProjectInfo.PenaltyDays, Encoders.Hex.EncodeData(seederFundsRecoveryKey.PubKey.ToBytes())); var founderSignatures = _founderTransactionActions.SignInvestorRecoveryTransactions(investorContext.ProjectInfo, investmentTransaction.ToHex(),recoveryTransaction, @@ -493,7 +493,7 @@ public void SpendInvestorRecoveryTest() TargetAmount = 3, StartDate = DateTime.UtcNow, ExpiryDate = DateTime.UtcNow.AddDays(5), - PenaltyDate = DateTime.UtcNow.AddDays(5), + PenaltyDays = 5, Stages = new List { new() { AmountToRelease = 1, ReleaseDate = DateTime.UtcNow.AddDays(1) }, diff --git a/src/Angor.Test/ProtocolNew/SeederTransactionActionsTest.cs b/src/Angor.Test/ProtocolNew/SeederTransactionActionsTest.cs index aeb30c1b..8dc7ed34 100644 --- a/src/Angor.Test/ProtocolNew/SeederTransactionActionsTest.cs +++ b/src/Angor.Test/ProtocolNew/SeederTransactionActionsTest.cs @@ -105,14 +105,14 @@ public void BuildRecoverSeederFundsTransactions_CallsBuildUpfrontRecoverFundsTra var investmentTrxHex = "010000000102df7eb0603e53da8760b6037cca974550e85489d36d59efcedb8834bb691a71000000006a473044022047870ec27da9e51c3f4657b6ac376bb240191b93b1c597775f092a3c6e20e66602203f544e972f45e796730c02942393f9b7d02b4d6dc2301281c68029e693194549012103d418fd52b6bd5fc9330c51aa4480aa9f3bba2940bedc7ce7535ac164aebc25efffffffff06c0c62d0000000000160014b81698f9e2e78fa7fc87f8009183c8a4ab25a6c70000000000000000446a2103eb7d47c80390672435987b9a7ecaa22730cd9c4537fc8d257417fb058248ed7720fcdcd57c6c65b40bcdf9b454a96891d7375a60d516e3416af61f86d4999d44e180c3c901000000002251204f3edc853deba516c82aa9479daaddbe5c34bdde1b2a7be369d784e560271123804a5d0500000000225120d2f4094dc5c80bee991b76b089f230f086edfcef20550467026f80e79647b3f900879303000000002251208ea1c42515559fd53f811b333be518484aeecf9409aefeccb8e977b43ae1d9c99c547e6d00000000160014333a905154f56ef18b6f7aee53ed45a231da54f700000000"; var investmentTrx = Networks.Bitcoin.Testnet().Consensus.ConsensusFactory.CreateTransaction(investmentTrxHex); - var penaltyDate = DateTime.Now.AddMonths(6); + var penaltyDays = 180; var receiveAddress = Encoders.Hex.EncodeData(changeAddress.PubKey.ToBytes()); var newProject = new ProjectInfo(); - var recoveryTransactions = _sut.BuildRecoverSeederFundsTransaction(newProject, investmentTrx, penaltyDate, + var recoveryTransactions = _sut.BuildRecoverSeederFundsTransaction(newProject, investmentTrx, penaltyDays, receiveAddress); - _investmentTransactionBuilder.Verify(_ => _.BuildUpfrontRecoverFundsTransaction(newProject, investmentTrx,penaltyDate,receiveAddress), + _investmentTransactionBuilder.Verify(_ => _.BuildUpfrontRecoverFundsTransaction(newProject, investmentTrx,penaltyDays,receiveAddress), Times.Once); } } \ No newline at end of file diff --git a/src/Angor.Test/ProtocolNew/TransactionBuilders/InvestmentTransactionBuilderTest.cs b/src/Angor.Test/ProtocolNew/TransactionBuilders/InvestmentTransactionBuilderTest.cs index 6275dd36..a03d9ba9 100644 --- a/src/Angor.Test/ProtocolNew/TransactionBuilders/InvestmentTransactionBuilderTest.cs +++ b/src/Angor.Test/ProtocolNew/TransactionBuilders/InvestmentTransactionBuilderTest.cs @@ -117,10 +117,10 @@ public void BuildRecoverSeederFundsTransactions_AllTransactionsReturnedWithStage var investmentTrx = Networks.Bitcoin.Testnet().Consensus.ConsensusFactory.CreateTransaction(investmentTrxHex); - _investmentScriptBuilder.Setup(_ => _.GetInvestorPenaltyTransactionScript(It.IsAny(), It.IsAny())) + _investmentScriptBuilder.Setup(_ => _.GetInvestorPenaltyTransactionScript(It.IsAny(), It.IsAny())) .Returns(new Key().ScriptPubKey); - var recoveryTransaction = _sut.BuildUpfrontRecoverFundsTransaction(new ProjectInfo { Stages = new List { new Stage(), new Stage(), new Stage() } }, investmentTrx, DateTime.Now.AddMonths(6), + var recoveryTransaction = _sut.BuildUpfrontRecoverFundsTransaction(new ProjectInfo { Stages = new List { new Stage(), new Stage(), new Stage() } }, investmentTrx, 180, Encoders.Hex.EncodeData(changeAddress.PubKey.ToBytes())); //All inputs are from the investment transaction outputs @@ -137,14 +137,14 @@ public void BuildRecoverSeederFundsTransactions_AllTransactionsReturnedWithTheRi var investmentTrx = Networks.Bitcoin.Testnet().Consensus.ConsensusFactory.CreateTransaction(investmentTrxHex); var expectedAddress = Encoders.Hex.EncodeData(changeAddress.PubKey.ToBytes()); - var expectedDateTime = DateTime.Now.AddMonths(6); + var expectedDays = 180; var expectedScript = new Key().ScriptPubKey; - _investmentScriptBuilder.Setup(_ => _.GetInvestorPenaltyTransactionScript(expectedAddress, expectedDateTime)) + _investmentScriptBuilder.Setup(_ => _.GetInvestorPenaltyTransactionScript(expectedAddress, expectedDays)) .Returns(expectedScript); var recoveryTransaction = _sut.BuildUpfrontRecoverFundsTransaction(new ProjectInfo { Stages = new List { new Stage(), new Stage(), new Stage() } }, investmentTrx, - expectedDateTime, expectedAddress); + expectedDays, expectedAddress); //All outputs pay to the penalty script Assert.Contains(recoveryTransaction.Outputs, diff --git a/src/Angor.Test/ScriptThresholdTest.cs b/src/Angor.Test/ScriptThresholdTest.cs index 3ef8f4bc..3b613049 100644 --- a/src/Angor.Test/ScriptThresholdTest.cs +++ b/src/Angor.Test/ScriptThresholdTest.cs @@ -1,4 +1,5 @@ using Angor.Shared; +using Angor.Shared.Protocol; namespace Angor.Test { diff --git a/src/Angor.Test/WalletOperationsTest.cs b/src/Angor.Test/WalletOperationsTest.cs index 98743bd2..50acb5ef 100644 --- a/src/Angor.Test/WalletOperationsTest.cs +++ b/src/Angor.Test/WalletOperationsTest.cs @@ -150,7 +150,7 @@ public void AddInputsAndSignTransaction() projectInfo.TargetAmount = 3; projectInfo.StartDate = DateTime.UtcNow; projectInfo.ExpiryDate = DateTime.UtcNow.AddDays(5); - projectInfo.PenaltyDate= DateTime.UtcNow.AddDays(10); + projectInfo.PenaltyDays= 10; projectInfo.Stages = new List { new Stage { AmountToRelease = 1, ReleaseDate = DateTime.UtcNow.AddDays(1) }, diff --git a/src/Angor/Client/NetworkConfiguration.cs b/src/Angor/Client/NetworkConfiguration.cs index 81a22783..8bfd133c 100644 --- a/src/Angor/Client/NetworkConfiguration.cs +++ b/src/Angor/Client/NetworkConfiguration.cs @@ -59,7 +59,7 @@ public static List CreateFakeProjects() new ProjectInfo { StartDate = DateTime.UtcNow, - PenaltyDate = DateTime.UtcNow, + PenaltyDays = 100, ExpiryDate = DateTime.UtcNow, TargetAmount = 300, ProjectIdentifier = "angor" + Guid.NewGuid().ToString("N"), @@ -73,7 +73,7 @@ public static List CreateFakeProjects() new ProjectInfo { StartDate = DateTime.UtcNow, - PenaltyDate = DateTime.UtcNow, + PenaltyDays = 100, ExpiryDate = DateTime.UtcNow, TargetAmount = 200, ProjectIdentifier = "angor" + Guid.NewGuid().ToString("N"), @@ -87,7 +87,7 @@ public static List CreateFakeProjects() new ProjectInfo { StartDate = DateTime.UtcNow, - PenaltyDate = DateTime.UtcNow, + PenaltyDays = 100, ExpiryDate = DateTime.UtcNow, TargetAmount = 100, ProjectIdentifier = "angor" + Guid.NewGuid().ToString("N"), diff --git a/src/Angor/Client/Pages/CheckTransactionCode.razor b/src/Angor/Client/Pages/CheckTransactionCode.razor index 5b0f8279..60c150bc 100644 --- a/src/Angor/Client/Pages/CheckTransactionCode.razor +++ b/src/Angor/Client/Pages/CheckTransactionCode.razor @@ -159,7 +159,7 @@ else }, ExpiryDate = DateTime.Now.AddDays(1), FounderKey = Encoders.Hex.EncodeData(privateFounderKey.Neuter().PubKey.ToBytes()), - PenaltyDate = DateTime.Now.AddMinutes(1000), + PenaltyDays = 100, StartDate = DateTime.Now, TargetAmount = 10, ProjectIdentifier = derivationOperations.DeriveAngorKey(Encoders.Hex.EncodeData(privateFounderKey.Neuter().PubKey.ToBytes()),angorRootKey), @@ -172,7 +172,7 @@ else context.TransactionHex = transaction.ToHex(); - recoveryTransaction = SeederTransactionActions.BuildRecoverSeederFundsTransaction(context.ProjectInfo, transaction, context.ProjectInfo.PenaltyDate, testAddress.PubKey.ToHex()); + recoveryTransaction = SeederTransactionActions.BuildRecoverSeederFundsTransaction(context.ProjectInfo, transaction, context.ProjectInfo.PenaltyDays, testAddress.PubKey.ToHex()); var signatures = FounderTransactionActions.SignInvestorRecoveryTransactions(context.ProjectInfo, context.TransactionHex, recoveryTransaction, Encoders.Hex.EncodeData(privateFounderKey.PrivateKey.ToBytes())); diff --git a/src/Angor/Client/Pages/Create.razor b/src/Angor/Client/Pages/Create.razor index 38d7e34f..772e025f 100644 --- a/src/Angor/Client/Pages/Create.razor +++ b/src/Angor/Client/Pages/Create.razor @@ -55,8 +55,8 @@
- - + +
@@ -110,7 +110,7 @@

Start date: @project.StartDate.ToString("dd/MM/yyyy") in @((project.StartDate - DateTime.Now).Days) days

Expiry date: @project.ExpiryDate.ToString("dd/MM/yyyy") in @((project.ExpiryDate - DateTime.Now).Days) days

-

Penalty date: @project.PenaltyDate.ToString("dd/MM/yyyy") in @((project.PenaltyDate - DateTime.Now).Days) days

+

Penalty days: @project.PenaltyDays days

Miner fee: [Your fee here]

Angor fee: 1000 sats

@@ -163,7 +163,7 @@ private ProjectInfo project = new ProjectInfo { StartDate = DateTime.UtcNow, - PenaltyDate = DateTime.UtcNow.AddDays(100), + PenaltyDays = 100, ExpiryDate = DateTime.UtcNow.AddDays(50), TargetAmount = 100, TransactionId = "unknowen", diff --git a/src/Angor/Client/Pages/Invest.razor b/src/Angor/Client/Pages/Invest.razor index e1fe7128..3c6ea5b1 100644 --- a/src/Angor/Client/Pages/Invest.razor +++ b/src/Angor/Client/Pages/Invest.razor @@ -102,7 +102,7 @@

Start date: @project.StartDate.ToString("dd/MM/yyyy") in @((project.StartDate - DateTime.Now).Days) days

Expiry date: @project.ExpiryDate.ToString("dd/MM/yyyy") in @((project.ExpiryDate - DateTime.Now).Days) days

-

Penalty date: @project.PenaltyDate.ToString("dd/MM/yyyy") in @((project.PenaltyDate - DateTime.Now).Days) days

+

Penalty days: @project.PenaltyDays days

Miner fee: [Your fee here]

Angor fee: 1000 sats

diff --git a/src/Angor/Client/Pages/Penalties.razor b/src/Angor/Client/Pages/Penalties.razor index cf91614f..1a8010f3 100644 --- a/src/Angor/Client/Pages/Penalties.razor +++ b/src/Angor/Client/Pages/Penalties.razor @@ -110,8 +110,8 @@ { ProjectIdentifier = signatureInfo.ProjectIdentifier, RecoveryTransactionId = signatureInfo.RecoveryTransactionId, - DaysLeftForPenalty = (project.PenaltyDate - DateTime.Now).Days, - IsExpired = (project.PenaltyDate - DateTime.Now).Days <= 0, + //DaysLeftForPenalty = (project.PenaltyDays - DateTime.Now).Days, + //IsExpired = (project.PenaltyDays - DateTime.Now).Days <= 0, IsReleased = !string.IsNullOrEmpty(signatureInfo.RecoveryReleaseTransactionId), }); } @@ -127,12 +127,20 @@ { var operationResult = await notificationComponent.LongOperation(async () => { + var projects = storage.GetProjects(); + foreach (var penaltyProject in penaltyProjects) { var recoveryTansaction = await _IndexerService.GetTransactionInfoByIdAsync(penaltyProject.RecoveryTransactionId); var totalsats = recoveryTansaction.Outputs.Where(s => Script.FromHex(s.ScriptPubKey).IsScriptType(ScriptType.P2WSH)).Sum(s => s.Balance); penaltyProject.Amount = Money.Satoshis(totalsats).ToUnit(MoneyUnit.BTC); + + var project = projects.First(p => p.ProjectIdentifier == penaltyProject.ProjectIdentifier); + + var expieryDate = Utils.UnixTimeToDateTime(recoveryTansaction.Timestamp).AddDays(project.PenaltyDays); + penaltyProject.DaysLeftForPenalty = (expieryDate - DateTimeOffset.UtcNow).Days; + penaltyProject.IsExpired = (expieryDate - DateTimeOffset.UtcNow).Days <= 0; } return new OperationResult { Success = true }; diff --git a/src/Angor/Client/Pages/Recover.razor b/src/Angor/Client/Pages/Recover.razor index 7aa311db..94def214 100644 --- a/src/Angor/Client/Pages/Recover.razor +++ b/src/Angor/Client/Pages/Recover.razor @@ -106,7 +106,7 @@

The amount to be recovered in to a penalty = @StageInfo.Items.Where(s=> !s.IsSpent).Sum(s=> s.Amount) BTC

-

The penalty duration is @((project.PenaltyDate - DateTime.UtcNow).Days) days

+

The penalty duration is @project.PenaltyDays days


@@ -323,6 +323,8 @@ private async Task CheckSpentFund() { + var penaltyExpieryDate = Utils.UnixTimeToDateTime(StageInfo.TransactionInfo.Timestamp).AddDays(project.PenaltyDays); + foreach (var item in StageInfo.Items) { var output = StageInfo.TransactionInfo.Outputs.ElementAt(item.Outputindex); @@ -341,7 +343,7 @@ else { item.ProjectScriptType = new ProjectScriptType { ScriptType = ProjectScriptTypeEnum.InvestorWithPenalty }; - var days = (project.PenaltyDate - DateTime.Now).Days; + var days = (penaltyExpieryDate - DateTime.Now).Days; item.SpentTo = days > 0 ? $"Penalty, released in {days} days" : "Penalty can be released"; } } @@ -365,7 +367,7 @@ } case ProjectScriptTypeEnum.InvestorWithPenalty: { - var days = (project.PenaltyDate - DateTime.Now).Days; + var days = (penaltyExpieryDate - DateTime.Now).Days; item.SpentTo = days > 0 ? $"Penalty, released in {days} days" : "Penalty can be released"; break; } @@ -383,7 +385,7 @@ StageInfo.CanRecover = StageInfo.Items.Any(a => a.IsSpent == false); StageInfo.TotalSpendable = StageInfo.Items.Where(a => !a.IsSpent).Sum(a => a.Amount); - StageInfo.CanRelease = (StageInfo.Items.Any(a => a.ProjectScriptType?.ScriptType == ProjectScriptTypeEnum.InvestorWithPenalty) && DateTime.UtcNow > project.PenaltyDate); + StageInfo.CanRelease = (StageInfo.Items.Any(a => a.ProjectScriptType?.ScriptType == ProjectScriptTypeEnum.InvestorWithPenalty) && DateTime.UtcNow > penaltyExpieryDate); StageInfo.TotalInPenalty = StageInfo.Items.Where(t => t.ProjectScriptType?.ScriptType == ProjectScriptTypeEnum.InvestorWithPenalty).Sum(t => t.Amount); StageInfo.EndOfProject = project.ExpiryDate < DateTime.Now; } diff --git a/src/Angor/Client/Pages/View.razor b/src/Angor/Client/Pages/View.razor index 17270879..093b3730 100644 --- a/src/Angor/Client/Pages/View.razor +++ b/src/Angor/Client/Pages/View.razor @@ -40,7 +40,7 @@ View the transaction on the explorer.

Founder Key: @project.FounderKey

Start Date: @project.StartDate.ToString("dd/MM/yyyy")

-

Penalty Date: @project.PenaltyDate.ToString("dd/MM/yyyy")

+

Penalty Days: @project.PenaltyDays

Expiry Date: @project.ExpiryDate.ToString("dd/MM/yyyy")

Target Amount: @project.TargetAmount

Stages:
diff --git a/src/Angor/Shared/Models/ProjectInfo.cs b/src/Angor/Shared/Models/ProjectInfo.cs index f9812c6e..8b5d33c5 100644 --- a/src/Angor/Shared/Models/ProjectInfo.cs +++ b/src/Angor/Shared/Models/ProjectInfo.cs @@ -13,7 +13,7 @@ public class ProjectInfo public string NostrPubKey { get; set; } public DateTime StartDate { get; set; } - public DateTime PenaltyDate { get; set; } + public int PenaltyDays { get; set; } public DateTime ExpiryDate { get; set; } public decimal TargetAmount { get; set; } public List Stages { get; set; } = new(); diff --git a/src/Angor/Shared/Protocol/InvestmentOperations.cs b/src/Angor/Shared/Protocol/InvestmentOperations.cs index 15355a81..639621a2 100644 --- a/src/Angor/Shared/Protocol/InvestmentOperations.cs +++ b/src/Angor/Shared/Protocol/InvestmentOperations.cs @@ -246,7 +246,7 @@ public List BuildRecoverInvestorFundsTransactions(InvestorContext c var spendingScript = ScriptBuilder.GetInvestorPenaltyTransactionScript( investorReceiveAddress, - context.ProjectInfo.PenaltyDate); + context.ProjectInfo.PenaltyDays); stageTransaction.Outputs.Add(new NBitcoin.TxOut(_.TxOut.Value, new NBitcoin.Script(spendingScript.WitHash.ScriptPubKey.ToBytes()))); diff --git a/src/Angor/Shared/ScriptBuilder.cs b/src/Angor/Shared/Protocol/ScriptBuilder.cs similarity index 94% rename from src/Angor/Shared/ScriptBuilder.cs rename to src/Angor/Shared/Protocol/ScriptBuilder.cs index 3a2af59f..60718481 100644 --- a/src/Angor/Shared/ScriptBuilder.cs +++ b/src/Angor/Shared/Protocol/ScriptBuilder.cs @@ -1,10 +1,8 @@ +using Angor.Shared.Models; using Blockcore.Consensus.ScriptInfo; using Blockcore.NBitcoin; -using Blockcore.NBitcoin.Crypto; -using System.Collections.Generic; -using Angor.Shared.Models; -namespace Angor.Shared; +namespace Angor.Shared.Protocol; public class ScriptBuilder { @@ -55,16 +53,19 @@ public static (PubKey investorKey, uint256? secretHash) GetInvestmentDataFromOpR return (pubKey, secretHash); } - public static Script GetInvestorPenaltyTransactionScript(string investorKey, DateTime punishmentLockTime) + public static Script GetInvestorPenaltyTransactionScript(string investorKey, int punishmentLockDays) { - var unixTime = Utils.DateTimeToUnixTime(punishmentLockTime); - + //var unixTime = Utils.DateTimeToUnixTime(punishmentLockTime); + + //var totalSeconds = (uint)TimeSpan.FromDays(punishmentLockDays).TotalSeconds; + var sequence = new Sequence(TimeSpan.FromDays(punishmentLockDays)); + return new(new List { Op.GetPushOp(new NBitcoin.PubKey(investorKey).ToBytes()), OpcodeType.OP_CHECKSIGVERIFY, - Op.GetPushOp(unixTime), - OpcodeType.OP_CHECKLOCKTIMEVERIFY + Op.GetPushOp((uint)sequence), + OpcodeType.OP_CHECKSEQUENCEVERIFY }); } diff --git a/src/Angor/Shared/ProtocolNew/ISeederTransactionActions.cs b/src/Angor/Shared/ProtocolNew/ISeederTransactionActions.cs index 7f793639..adf6329b 100644 --- a/src/Angor/Shared/ProtocolNew/ISeederTransactionActions.cs +++ b/src/Angor/Shared/ProtocolNew/ISeederTransactionActions.cs @@ -7,7 +7,7 @@ namespace Angor.Shared.ProtocolNew; public interface ISeederTransactionActions { Transaction CreateInvestmentTransaction(ProjectInfo projectInfo, string investorKey, uint256 investorSecretHash, long totalInvestmentAmount); - Transaction BuildRecoverSeederFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, DateTime penaltyDate, string investorKey); + Transaction BuildRecoverSeederFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, int penaltyDays, string investorKey); Transaction RecoverEndOfProjectFunds(string investmentTransactionHex, ProjectInfo projectInfo, int stageIndex, string investorReceiveAddress, string investorPrivateKey, FeeEstimation feeEstimation); Transaction AddSignaturesToRecoverSeederFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, diff --git a/src/Angor/Shared/ProtocolNew/InvestorTransactionActions.cs b/src/Angor/Shared/ProtocolNew/InvestorTransactionActions.cs index e36f8b5e..2b3b02e0 100644 --- a/src/Angor/Shared/ProtocolNew/InvestorTransactionActions.cs +++ b/src/Angor/Shared/ProtocolNew/InvestorTransactionActions.cs @@ -89,7 +89,7 @@ public Transaction BuildRecoverInvestorFundsTransaction(ProjectInfo projectInfo, { var (investorKey, secretHash) = _projectScriptsBuilder.GetInvestmentDataFromOpReturnScript(investmentTransaction.Outputs.First(_ => _.ScriptPubKey.IsUnspendable).ScriptPubKey); - return _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, projectInfo.PenaltyDate, investorKey); + return _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, projectInfo.PenaltyDays, investorKey); } public Transaction BuildAndSignRecoverReleaseFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, @@ -99,12 +99,14 @@ public Transaction BuildAndSignRecoverReleaseFundsTransaction(ProjectInfo projec var spendingScript = _investmentScriptBuilder.GetInvestorPenaltyTransactionScript( investorKey, - projectInfo.PenaltyDate); + projectInfo.PenaltyDays); var network = _networkConfiguration.GetNetwork(); var transaction = network.CreateTransaction(); - transaction.LockTime = Utils.DateTimeToUnixTime(projectInfo.PenaltyDate.AddMinutes(1)); + //transaction.LockTime = Utils.DateTimeToUnixTime(projectInfo.PenaltyDays.AddMinutes(1)); + + transaction.Version = 2; // to trigger bip68 rules // add the output address transaction.Outputs.Add(new Blockcore.Consensus.TransactionInfo.TxOut(Money.Zero, Blockcore.NBitcoin.BitcoinAddress.Create(investorReceiveAddress, network))); @@ -115,7 +117,7 @@ public Transaction BuildAndSignRecoverReleaseFundsTransaction(ProjectInfo projec if (output.TxOut.ScriptPubKey == spendingScript.WitHash.ScriptPubKey) { // this is a penalty output - transaction.Inputs.Add(new Blockcore.Consensus.TransactionInfo.TxIn(output.ToOutPoint()) { Sequence = new Blockcore.NBitcoin.Sequence(transaction.LockTime.Value)}); + transaction.Inputs.Add(new Blockcore.Consensus.TransactionInfo.TxIn(output.ToOutPoint()) { Sequence = new Blockcore.NBitcoin.Sequence(TimeSpan.FromDays(projectInfo.PenaltyDays)) }); transaction.Outputs[0].Value += output.TxOut.Value; } @@ -225,7 +227,7 @@ public Transaction AddSignaturesToRecoverSeederFundsTransaction(ProjectInfo proj { var (investorKey, secretHash) = _projectScriptsBuilder.GetInvestmentDataFromOpReturnScript(investmentTransaction.Outputs.First(_ => _.ScriptPubKey.IsUnspendable).ScriptPubKey); - var recoveryTransaction = _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, projectInfo.PenaltyDate, investorKey); + var recoveryTransaction = _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, projectInfo.PenaltyDays, investorKey); var nbitcoinNetwork = NetworkMapper.Map(_networkConfiguration.GetNetwork()); var nbitcoinRecoveryTransaction = NBitcoin.Transaction.Parse(recoveryTransaction.ToHex(), nbitcoinNetwork); @@ -267,7 +269,7 @@ public bool CheckInvestorRecoverySignatures(ProjectInfo projectInfo, Transaction { var (investorKey, secretHash) = _projectScriptsBuilder.GetInvestmentDataFromOpReturnScript(investmentTransaction.Outputs.First(_ => _.ScriptPubKey.IsUnspendable).ScriptPubKey); - var recoveryTransaction = _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, projectInfo.PenaltyDate, investorKey); + var recoveryTransaction = _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, projectInfo.PenaltyDays, investorKey); var nbitcoinNetwork = NetworkMapper.Map(_networkConfiguration.GetNetwork()); var nBitcoinRecoveryTransaction = NBitcoin.Transaction.Parse(recoveryTransaction.ToHex(), nbitcoinNetwork); diff --git a/src/Angor/Shared/ProtocolNew/Scripts/IInvestmentScriptbuilder.cs b/src/Angor/Shared/ProtocolNew/Scripts/IInvestmentScriptbuilder.cs index d86ddaa5..cbfee86a 100644 --- a/src/Angor/Shared/ProtocolNew/Scripts/IInvestmentScriptbuilder.cs +++ b/src/Angor/Shared/ProtocolNew/Scripts/IInvestmentScriptbuilder.cs @@ -6,7 +6,7 @@ namespace Angor.Shared.ProtocolNew.Scripts; public interface IInvestmentScriptBuilder { - Script GetInvestorPenaltyTransactionScript(string investorKey, DateTime punishmentLockTime); + Script GetInvestorPenaltyTransactionScript(string investorKey, int punishmentLockDays); ProjectScripts BuildProjectScriptsForStage(ProjectInfo projectInfo, string investorKey, int stageIndex, uint256? hashOfSecret = null); diff --git a/src/Angor/Shared/ProtocolNew/Scripts/InvestmentScriptBuilder.cs b/src/Angor/Shared/ProtocolNew/Scripts/InvestmentScriptBuilder.cs index 9124db68..b83412a1 100644 --- a/src/Angor/Shared/ProtocolNew/Scripts/InvestmentScriptBuilder.cs +++ b/src/Angor/Shared/ProtocolNew/Scripts/InvestmentScriptBuilder.cs @@ -13,16 +13,20 @@ public InvestmentScriptBuilder(ISeederScriptTreeBuilder seederScriptTreeBuilder) _seederScriptTreeBuilder = seederScriptTreeBuilder; } - public Script GetInvestorPenaltyTransactionScript(string investorKey, DateTime punishmentLockTime) + public Script GetInvestorPenaltyTransactionScript(string investorKey, int punishmentLockDays) { - var unixTime = Utils.DateTimeToUnixTime(punishmentLockTime); - + // var unixTime = Utils.DateTimeToUnixTime(punishmentLockDays); + + var sequence = new Sequence(TimeSpan.FromDays(punishmentLockDays)); + + //var totalSeconds = (uint)TimeSpan.FromDays(punishmentLockDays).TotalSeconds; + return new(new List { Op.GetPushOp(new NBitcoin.PubKey(investorKey).ToBytes()), OpcodeType.OP_CHECKSIGVERIFY, - Op.GetPushOp(unixTime), - OpcodeType.OP_CHECKLOCKTIMEVERIFY + Op.GetPushOp((uint)sequence), + OpcodeType.OP_CHECKSEQUENCEVERIFY }); } diff --git a/src/Angor/Shared/ProtocolNew/SeederTransactionActions.cs b/src/Angor/Shared/ProtocolNew/SeederTransactionActions.cs index 72484fca..288a2f6a 100644 --- a/src/Angor/Shared/ProtocolNew/SeederTransactionActions.cs +++ b/src/Angor/Shared/ProtocolNew/SeederTransactionActions.cs @@ -48,17 +48,17 @@ public Transaction CreateInvestmentTransaction(ProjectInfo projectInfo, string i totalInvestmentAmount); } - public Transaction BuildRecoverSeederFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, DateTime penaltyDate, + public Transaction BuildRecoverSeederFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, int penaltyDays, string investorKey) { - return _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, penaltyDate, + return _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, penaltyDays, investorKey); } public Transaction AddSignaturesToRecoverSeederFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, string receiveAddress, SignatureInfo founderSignatures, string privateKey, string? secret) { - var recoveryTransaction = _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, projectInfo.PenaltyDate, receiveAddress); + var recoveryTransaction = _investmentTransactionBuilder.BuildUpfrontRecoverFundsTransaction(projectInfo, investmentTransaction, projectInfo.PenaltyDays, receiveAddress); var (investorKey, secretHash) = _projectScriptsBuilder.GetInvestmentDataFromOpReturnScript(investmentTransaction.Outputs.First(_ => _.ScriptPubKey.IsUnspendable).ScriptPubKey); diff --git a/src/Angor/Shared/ProtocolNew/TransactionBuilders/IInvestmentTransactionBuilder.cs b/src/Angor/Shared/ProtocolNew/TransactionBuilders/IInvestmentTransactionBuilder.cs index 65a6eada..56031858 100644 --- a/src/Angor/Shared/ProtocolNew/TransactionBuilders/IInvestmentTransactionBuilder.cs +++ b/src/Angor/Shared/ProtocolNew/TransactionBuilders/IInvestmentTransactionBuilder.cs @@ -9,6 +9,6 @@ public interface IInvestmentTransactionBuilder Transaction BuildInvestmentTransaction(ProjectInfo projectInfo, Script opReturnScript, IEnumerable projectScripts, long totalInvestmentAmount); - Transaction BuildUpfrontRecoverFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, DateTime penaltyDate, + Transaction BuildUpfrontRecoverFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, int penaltyDays, string investorKey); } \ No newline at end of file diff --git a/src/Angor/Shared/ProtocolNew/TransactionBuilders/InvestmentTransactionBuilder.cs b/src/Angor/Shared/ProtocolNew/TransactionBuilders/InvestmentTransactionBuilder.cs index 9d42b4b9..46397053 100644 --- a/src/Angor/Shared/ProtocolNew/TransactionBuilders/InvestmentTransactionBuilder.cs +++ b/src/Angor/Shared/ProtocolNew/TransactionBuilders/InvestmentTransactionBuilder.cs @@ -48,11 +48,11 @@ public Transaction BuildInvestmentTransaction(ProjectInfo projectInfo, Script op return investmentTransaction; } - public Transaction BuildUpfrontRecoverFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, DateTime penaltyDate, string investorKey) + public Transaction BuildUpfrontRecoverFundsTransaction(ProjectInfo projectInfo, Transaction investmentTransaction, int penaltyDays, string investorKey) { var spendingScript = _investmentScriptBuilder.GetInvestorPenaltyTransactionScript( investorKey, - penaltyDate); + penaltyDays); var transaction = _networkConfiguration.GetNetwork().CreateTransaction();