From d032b77abe8610a3ea85ed2a51c0601c2921d3e3 Mon Sep 17 00:00:00 2001 From: benbierens Date: Fri, 22 Nov 2024 16:09:18 +0100 Subject: [PATCH] wip: withdraw funds --- .../CodexContractsAccess.cs | 22 +++++ .../CodexPlugin/MarketplaceTypes.cs | 2 - .../MarketTests/ContractSuccessfulTest.cs | 91 ++++++++++--------- .../MarketplaceAutoBootstrapDistTest.cs | 52 +++++++++-- 4 files changed, 115 insertions(+), 52 deletions(-) diff --git a/ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs b/ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs index 58fbb29..8e2c04a 100644 --- a/ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs +++ b/ProjectPlugins/CodexContractsPlugin/CodexContractsAccess.cs @@ -2,6 +2,7 @@ using GethPlugin; using Logging; using Nethereum.ABI; +using Nethereum.Hex.HexConvertors.Extensions; using Nethereum.Util; using NethereumWorkflow; using Newtonsoft.Json; @@ -24,6 +25,7 @@ namespace CodexContractsPlugin ICodexContractsEvents GetEvents(BlockInterval blockInterval); EthAddress? GetSlotHost(Request storageRequest, decimal slotIndex); RequestState GetRequestState(Request request); + void WithdrawFunds(string purchaseId, EthAddress address); } [JsonConverter(typeof(StringEnumConverter))] @@ -114,6 +116,26 @@ namespace CodexContractsPlugin return gethNode.Call(Deployment.MarketplaceAddress, func); } + public void WithdrawFunds(string purchaseId, EthAddress address) + { + try + { + log.Log("withdrawing funds...."); + var func = new WithdrawFundsFunction + { + RequestId = purchaseId.HexToByteArray(), + FromAddress = address.Address + }; + var response = gethNode.Call(Deployment.MarketplaceAddress, func); + + log.Log("got response: " + response); + } + catch (Exception ex) + { + log.Log("Got exception: " + ex); + } + } + private ContractInteractions StartInteraction() { return new ContractInteractions(log, gethNode); diff --git a/ProjectPlugins/CodexPlugin/MarketplaceTypes.cs b/ProjectPlugins/CodexPlugin/MarketplaceTypes.cs index fcbfe63..c92220b 100644 --- a/ProjectPlugins/CodexPlugin/MarketplaceTypes.cs +++ b/ProjectPlugins/CodexPlugin/MarketplaceTypes.cs @@ -1,7 +1,5 @@ using CodexContractsPlugin; -using CodexOpenApi; using Logging; -using System.Data; using Utils; namespace CodexPlugin diff --git a/Tests/CodexReleaseTests/MarketTests/ContractSuccessfulTest.cs b/Tests/CodexReleaseTests/MarketTests/ContractSuccessfulTest.cs index bddfbcd..71ad111 100644 --- a/Tests/CodexReleaseTests/MarketTests/ContractSuccessfulTest.cs +++ b/Tests/CodexReleaseTests/MarketTests/ContractSuccessfulTest.cs @@ -9,30 +9,46 @@ namespace CodexReleaseTests.MarketTests [TestFixture] public class ContractSuccessfulTest : MarketplaceAutoBootstrapDistTest { - private const int NumberOfHosts = 4; private const int FilesizeMb = 10; private const int PricePerSlotPerSecondTSTWei = 10; + protected override int NumberOfHosts => 4; + protected override int NumberOfClients => 1; + protected override ByteSize HostAvailabilitySize => (5 * FilesizeMb).MB(); + protected override TimeSpan HostAvailabilityMaxDuration => GetHostAvailabilityDuration(); + [Test] public void ContractSuccessful() { var hosts = StartHosts(); - var client = StartCodex(s => s.WithName("client")); + var client = StartClients().Single(); - var contract = CreateStorageRequest(client); + var request = CreateStorageRequest(client); - contract.WaitForStorageContractSubmitted(); - AssertContractIsOnChain(contract); + request.WaitForStorageContractSubmitted(); + AssertContractIsOnChain(request); - contract.WaitForStorageContractStarted(); - var slotFills = AssertContractSlotsAreFilledByHosts(contract, hosts); + request.WaitForStorageContractStarted(); + var slotFills = AssertContractSlotsAreFilledByHosts(request, hosts); - contract.WaitForStorageContractFinished(); - AssertClientHasPaidForContract(client, contract); - AssertHostsWerePaidForContract(contract, hosts, slotFills); + request.WaitForStorageContractFinished(); + //EveryoneWithdrawsFunds(hosts, client); + + GetContracts().WithdrawFunds(request.PurchaseId, client.EthAddress); + foreach (var host in hosts) + GetContracts().WithdrawFunds(request.PurchaseId, host.EthAddress); + + AssertClientHasPaidForContract(client, request); + AssertHostsWerePaidForContract(request, hosts, slotFills); AssertHostsCollateralsAreUnchanged(hosts); } + //private void EveryoneWithdrawsFunds(ICodexNodeGroup hosts, ICodexNode client) + //{ + // foreach (var host in hosts) host.Marketplace.WithdrawFunds(); + // client.Marketplace.WithdrawFunds(); + //} + private void AssertContractIsOnChain(IStoragePurchaseContract contract) { AssertOnChainEvents(events => @@ -71,18 +87,7 @@ namespace CodexReleaseTests.MarketTests var balance = GetContracts().GetTestTokenBalance(client); var expectedBalance = StartingBalanceTST.Tst() - GetContractTotalCost(); - Assert.That(balance, Is.EqualTo(expectedBalance)); - } - - private TestToken GetContractTotalCost() - { - return GetContractCostPerSlot() * NumberOfHosts; - } - - private TestToken GetContractCostPerSlot() - { - var duration = GetContractDuration(); - return PricePerSlotPerSecondTSTWei.TstWei() * ((int)duration.TotalSeconds); + Assert.That(balance, Is.EqualTo(expectedBalance), "Client balance incorrect."); } private void AssertHostsWerePaidForContract(IStoragePurchaseContract contract, ICodexNodeGroup hosts, SlotFill[] fills) @@ -97,7 +102,7 @@ namespace CodexReleaseTests.MarketTests foreach (var pair in expectedBalances) { var balance = GetContracts().GetTestTokenBalance(pair.Key); - Assert.That(balance, Is.EqualTo(pair.Value)); + Assert.That(balance, Is.EqualTo(pair.Value), "Host was not paid for storage."); } } @@ -127,36 +132,40 @@ namespace CodexReleaseTests.MarketTests return client.Marketplace.RequestStorage(new StoragePurchaseRequest(cid) { Duration = GetContractDuration(), - Expiry = TimeSpan.FromSeconds(((double)config.Proofs.Period) * 1.0), - MinRequiredNumberOfNodes = NumberOfHosts, - NodeFailureTolerance = NumberOfHosts / 2, + Expiry = GetContractExpiry(), + MinRequiredNumberOfNodes = (uint)NumberOfHosts, + NodeFailureTolerance = (uint)(NumberOfHosts / 2), PricePerSlotPerSecond = PricePerSlotPerSecondTSTWei.TstWei(), ProofProbability = 20, RequiredCollateral = 1.Tst() }); } - private TimeSpan GetContractDuration() + private TestToken GetContractTotalCost() { - var config = GetContracts().Deployment.Config; - return TimeSpan.FromSeconds(((double)config.Proofs.Period) * 2.0); + return GetContractCostPerSlot() * NumberOfHosts; } - private ICodexNodeGroup StartHosts() + private TestToken GetContractCostPerSlot() { - var hosts = StartCodex(NumberOfHosts, s => s.WithName("host")); + var duration = GetContractDuration(); + return PricePerSlotPerSecondTSTWei.TstWei() * ((int)duration.TotalSeconds); + } + private TimeSpan GetContractExpiry() + { + return GetContractDuration() / 2; + } + + private TimeSpan GetContractDuration() + { + return GetHostAvailabilityDuration() / 2; + } + + private TimeSpan GetHostAvailabilityDuration() + { var config = GetContracts().Deployment.Config; - foreach (var host in hosts) - { - host.Marketplace.MakeStorageAvailable(new CodexPlugin.StorageAvailability( - totalSpace: (5 * FilesizeMb).MB(), - maxDuration: TimeSpan.FromSeconds(((double)config.Proofs.Period) * 5.0), - minPriceForTotalSpace: 1.TstWei(), - maxCollateral: 999999.Tst()) - ); - } - return hosts; + return TimeSpan.FromSeconds(((double)config.Proofs.Period) * 8.0); } } } diff --git a/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs b/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs index b7d9a51..b708796 100644 --- a/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs +++ b/Tests/CodexReleaseTests/MarketTests/MarketplaceAutoBootstrapDistTest.cs @@ -5,6 +5,7 @@ using CodexTests; using DistTestCore; using GethPlugin; using Nethereum.Hex.HexConvertors.Extensions; +using Utils; namespace CodexReleaseTests.MarketTests { @@ -27,12 +28,6 @@ namespace CodexReleaseTests.MarketTests handles.Remove(lifecycle); } - protected override void OnCodexSetup(ICodexSetup setup) - { - base.OnCodexSetup(setup); - setup.EnableMarketplace(GetGeth(), GetContracts(), m => m.WithInitial(10.Eth(), StartingBalanceTST.Tst())); - } - protected IGethNode GetGeth() { return handles[Get()].Geth; @@ -43,10 +38,49 @@ namespace CodexReleaseTests.MarketTests return handles[Get()].Contracts; } + protected abstract int NumberOfHosts { get; } + protected abstract int NumberOfClients { get; } + protected abstract ByteSize HostAvailabilitySize { get; } + protected abstract TimeSpan HostAvailabilityMaxDuration { get; } + + public ICodexNodeGroup StartHosts() + { + var hosts = StartCodex(NumberOfHosts, s => s + .WithName("host") + .EnableMarketplace(GetGeth(), GetContracts(), m => m + .WithInitial(10.Eth(), StartingBalanceTST.Tst()) + .AsStorageNode() + ) + ); + + var config = GetContracts().Deployment.Config; + foreach (var host in hosts) + { + host.Marketplace.MakeStorageAvailable(new CodexPlugin.StorageAvailability( + totalSpace: HostAvailabilitySize, + maxDuration: HostAvailabilityMaxDuration, + minPriceForTotalSpace: 1.TstWei(), + maxCollateral: 999999.Tst()) + ); + } + return hosts; + } + + public ICodexNodeGroup StartClients() + { + return StartCodex(NumberOfClients, s => s + .WithName("client") + .EnableMarketplace(GetGeth(), GetContracts(), m => m + .WithInitial(10.Eth(), StartingBalanceTST.Tst()) + ) + ); + } + public SlotFill[] GetOnChainSlotFills(ICodexNodeGroup possibleHosts, string purchaseId) { - return GetOnChainSlotFills(possibleHosts) - .Where(f => f.SlotFilledEvent.RequestId.ToHex(true) == purchaseId) + var fills = GetOnChainSlotFills(possibleHosts); + return fills.Where(f => f + .SlotFilledEvent.RequestId.ToHex(false).ToLowerInvariant() == purchaseId.ToLowerInvariant()) .ToArray(); } @@ -56,7 +90,7 @@ namespace CodexReleaseTests.MarketTests var fills = events.GetSlotFilledEvents(); return fills.Select(f => { - var host = possibleHosts.Single(h => h.EthAddress == f.Host); + var host = possibleHosts.Single(h => h.EthAddress.Address == f.Host.Address); return new SlotFill(f, host); }).ToArray();