Skip to content

Commit

Permalink
use relative time locks for penalties
Browse files Browse the repository at this point in the history
  • Loading branch information
dangershony committed Nov 14, 2023
1 parent 96e9522 commit fc4f258
Show file tree
Hide file tree
Showing 24 changed files with 83 additions and 65 deletions.
6 changes: 3 additions & 3 deletions src/Angor.Test/InvestmentOperationsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()),
Expand Down
2 changes: 1 addition & 1 deletion src/Angor.Test/ProtocolNew/AngorTestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Stage>
{
new() { AmountToRelease = (decimal)0.1, ReleaseDate = startDate.Value.AddDays(1) },
Expand Down
10 changes: 5 additions & 5 deletions src/Angor.Test/ProtocolNew/InvestmentIntegrationsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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()),
Expand All @@ -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,
Expand Down Expand Up @@ -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<Stage>
{
new() { AmountToRelease = 1, ReleaseDate = DateTime.UtcNow.AddDays(1) },
Expand Down
6 changes: 3 additions & 3 deletions src/Angor.Test/ProtocolNew/SeederTransactionActionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ public void BuildRecoverSeederFundsTransactions_AllTransactionsReturnedWithStage

var investmentTrx = Networks.Bitcoin.Testnet().Consensus.ConsensusFactory.CreateTransaction(investmentTrxHex);

_investmentScriptBuilder.Setup(_ => _.GetInvestorPenaltyTransactionScript(It.IsAny<string>(), It.IsAny<DateTime>()))
_investmentScriptBuilder.Setup(_ => _.GetInvestorPenaltyTransactionScript(It.IsAny<string>(), It.IsAny<int>()))
.Returns(new Key().ScriptPubKey);

var recoveryTransaction = _sut.BuildUpfrontRecoverFundsTransaction(new ProjectInfo { Stages = new List<Stage> { new Stage(), new Stage(), new Stage() } }, investmentTrx, DateTime.Now.AddMonths(6),
var recoveryTransaction = _sut.BuildUpfrontRecoverFundsTransaction(new ProjectInfo { Stages = new List<Stage> { new Stage(), new Stage(), new Stage() } }, investmentTrx, 180,
Encoders.Hex.EncodeData(changeAddress.PubKey.ToBytes()));

//All inputs are from the investment transaction outputs
Expand All @@ -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<Stage> { new Stage(), new Stage(), new Stage() } }, investmentTrx,
expectedDateTime, expectedAddress);
expectedDays, expectedAddress);

//All outputs pay to the penalty script
Assert.Contains(recoveryTransaction.Outputs,
Expand Down
1 change: 1 addition & 0 deletions src/Angor.Test/ScriptThresholdTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Angor.Shared;
using Angor.Shared.Protocol;

namespace Angor.Test
{
Expand Down
2 changes: 1 addition & 1 deletion src/Angor.Test/WalletOperationsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Stage>
{
new Stage { AmountToRelease = 1, ReleaseDate = DateTime.UtcNow.AddDays(1) },
Expand Down
6 changes: 3 additions & 3 deletions src/Angor/Client/NetworkConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static List<ProjectInfo> CreateFakeProjects()
new ProjectInfo
{
StartDate = DateTime.UtcNow,
PenaltyDate = DateTime.UtcNow,
PenaltyDays = 100,
ExpiryDate = DateTime.UtcNow,
TargetAmount = 300,
ProjectIdentifier = "angor" + Guid.NewGuid().ToString("N"),
Expand All @@ -73,7 +73,7 @@ public static List<ProjectInfo> CreateFakeProjects()
new ProjectInfo
{
StartDate = DateTime.UtcNow,
PenaltyDate = DateTime.UtcNow,
PenaltyDays = 100,
ExpiryDate = DateTime.UtcNow,
TargetAmount = 200,
ProjectIdentifier = "angor" + Guid.NewGuid().ToString("N"),
Expand All @@ -87,7 +87,7 @@ public static List<ProjectInfo> CreateFakeProjects()
new ProjectInfo
{
StartDate = DateTime.UtcNow,
PenaltyDate = DateTime.UtcNow,
PenaltyDays = 100,
ExpiryDate = DateTime.UtcNow,
TargetAmount = 100,
ProjectIdentifier = "angor" + Guid.NewGuid().ToString("N"),
Expand Down
4 changes: 2 additions & 2 deletions src/Angor/Client/Pages/CheckTransactionCode.razor
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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()));

Expand Down
8 changes: 4 additions & 4 deletions src/Angor/Client/Pages/Create.razor
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@

<!-- Penalty Date -->
<div class="mb-3">
<label for="penaltyDate" class="form-label">Penalty Date</label>
<InputDate id="penaltyDate" @bind-Value="project.PenaltyDate" class="form-control"/>
<label for="penaltyDate" class="form-label">Penalty Days</label>
<InputNumber id="penaltyDate" @bind-Value="project.PenaltyDays" class="form-control" />
</div>

<!-- Expiry Date -->
Expand Down Expand Up @@ -110,7 +110,7 @@

<p class="mb-1"><strong>Start date:</strong> @project.StartDate.ToString("dd/MM/yyyy") in @((project.StartDate - DateTime.Now).Days) days</p>
<p class="mb-1"><strong>Expiry date:</strong> @project.ExpiryDate.ToString("dd/MM/yyyy") in @((project.ExpiryDate - DateTime.Now).Days) days</p>
<p class="mb-1"><strong>Penalty date:</strong> @project.PenaltyDate.ToString("dd/MM/yyyy") in @((project.PenaltyDate - DateTime.Now).Days) days</p>
<p class="mb-1"><strong>Penalty days:</strong> @project.PenaltyDays days</p>

<p class="mb-1"><strong>Miner fee:</strong> [Your fee here]</p>
<p class="mb-1"><strong>Angor fee:</strong> 1000 sats</p>
Expand Down Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion src/Angor/Client/Pages/Invest.razor
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@

<p class="mb-1"><strong>Start date:</strong> @project.StartDate.ToString("dd/MM/yyyy") in @((project.StartDate - DateTime.Now).Days) days</p>
<p class="mb-1"><strong>Expiry date:</strong> @project.ExpiryDate.ToString("dd/MM/yyyy") in @((project.ExpiryDate - DateTime.Now).Days) days</p>
<p class="mb-1"><strong>Penalty date:</strong> @project.PenaltyDate.ToString("dd/MM/yyyy") in @((project.PenaltyDate - DateTime.Now).Days) days</p>
<p class="mb-1"><strong>Penalty days:</strong> @project.PenaltyDays days</p>

<p class="mb-1"><strong>Miner fee:</strong> [Your fee here]</p>
<p class="mb-1"><strong>Angor fee:</strong> 1000 sats</p>
Expand Down
12 changes: 10 additions & 2 deletions src/Angor/Client/Pages/Penalties.razor
Original file line number Diff line number Diff line change
Expand Up @@ -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),
});
}
Expand All @@ -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 };
Expand Down
10 changes: 6 additions & 4 deletions src/Angor/Client/Pages/Recover.razor
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@

<p class="mb-1">The amount to be recovered in to a penalty = @StageInfo.Items.Where(s=> !s.IsSpent).Sum(s=> s.Amount) BTC</p>

<p class="mb-1">The penalty duration is @((project.PenaltyDate - DateTime.UtcNow).Days) days </p>
<p class="mb-1">The penalty duration is @project.PenaltyDays days </p>

<hr>

Expand Down Expand Up @@ -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);
Expand All @@ -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";
}
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Angor/Client/Pages/View.razor
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<a href="@projectExplorerLink" target="_blank">View the transaction on the explorer.</a>
<p class="card-text">Founder Key: @project.FounderKey</p>
<p class="card-text">Start Date: @project.StartDate.ToString("dd/MM/yyyy")</p>
<p class="card-text">Penalty Date: @project.PenaltyDate.ToString("dd/MM/yyyy")</p>
<p class="card-text">Penalty Days: @project.PenaltyDays</p>
<p class="card-text">Expiry Date: @project.ExpiryDate.ToString("dd/MM/yyyy")</p>
<p class="card-text">Target Amount: @project.TargetAmount</p>
<h5>Stages:</h5>
Expand Down
2 changes: 1 addition & 1 deletion src/Angor/Shared/Models/ProjectInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Stage> Stages { get; set; } = new();
Expand Down
2 changes: 1 addition & 1 deletion src/Angor/Shared/Protocol/InvestmentOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public List<Transaction> 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())));
Expand Down
Loading

0 comments on commit fc4f258

Please sign in to comment.