Exemple #1
0
        public static async Task CreateMissingIdentities(
            MySqlConnection connection, Web3 cl, int blockchainId, BlockchainType blockchain, BlockchainNetwork network)
        {
            var eth = new EthApiService(cl.Client);

            var allIdentitiesCreated = connection
                                       .Query <OTContract_Profile_IdentityCreated>(@"select * from OTContract_Profile_IdentityCreated IC
            WHERE IC.NewIdentity not in (SELECT OTIdentity.Identity FROM OTIdentity WHERE BlockchainID = @BlockchainID) AND IC.BlockchainID = @blockchainID", new
            {
                blockchainId = blockchainId
            })
                                       .ToArray();

            foreach (var identity in allIdentitiesCreated)
            {
                var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchain, network), identity.NewIdentity);

                var otVersionFunction = ercContract.GetFunction("otVersion");

                var value = await otVersionFunction.CallAsync <BigInteger>();

                await OTIdentity.Insert(connection, new OTIdentity
                {
                    TransactionHash = identity.TransactionHash,
                    Identity        = identity.NewIdentity,
                    Version         = (int)value,
                    BlockchainID    = blockchainId
                });
            }

            //This only happens due to missing blockchain events (only happened in December 2018)
            var profilesCreatedWithoutIdentities = connection.Query(
                @"select TransactionHash, Profile from otcontract_profile_profilecreated
WHERE Profile not in (select otidentity.Identity from otidentity WHERE BlockchainID = @blockchainID) AND BlockchainID = @blockchainID", new
            {
                blockchainId = blockchainId
            }).ToArray();

            foreach (var profilesCreatedWithoutIdentity in profilesCreatedWithoutIdentities)
            {
                string hash     = profilesCreatedWithoutIdentity.TransactionHash;
                string identity = profilesCreatedWithoutIdentity.Profile;

                var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchain, network), identity);

                var otVersionFunction = ercContract.GetFunction("otVersion");

                var value = await otVersionFunction.CallAsync <BigInteger>();

                await OTIdentity.Insert(connection, new OTIdentity
                {
                    TransactionHash = hash,
                    Identity        = identity,
                    Version         = (int)value,
                    BlockchainID    = blockchainId
                });
            }
        }
Exemple #2
0
        public EthereumTransactionDao()
        {
            string url = System.Configuration.ConfigurationManager.AppSettings["ethUrl"];

            _webNode = url == null ? new Web3() : new Web3(url);

            _webNode.TransactionManager.DefaultGasPrice = new BigInteger(0);
            Contract = _webNode.Eth.GetContract(AbiHelper.GetEcobitBlockchainAbi(), System.Configuration.ConfigurationManager.AppSettings["transactionManagerAddress"]);
        }
        public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network)
        {
            ClientBase.ConnectionTimeout = new TimeSpan(0, 0, 5, 0);

            await using (var connection =
                             new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                int blockchainID = await GetBlockchainID(connection, blockchain, network);

                var cl = await GetWeb3(connection, blockchainID, blockchain);

                var eth = new EthApiService(cl.Client);

                foreach (var contract in await OTContract.GetByTypeAndBlockchain(connection,
                                                                                 (int)ContractTypeEnum.Litigation, blockchainID))
                {
                    if (contract.IsArchived && contract.LastSyncedTimestamp.HasValue &&
                        (DateTime.Now - contract.LastSyncedTimestamp.Value).TotalDays <= 5)
                    {
#if DEBUG
                        Logger.WriteLine(source, "     Skipping contract: " + contract.Address);
#endif
                        continue;
                    }

                    Logger.WriteLine(source, "     Using contract: " + contract.Address);

                    var holdingContract = new Contract(eth,
                                                       AbiHelper.GetContractAbi(ContractTypeEnum.Litigation, blockchain, network), contract.Address);

                    var litigationInitiatedEvent = holdingContract.GetEvent("LitigationInitiated");
                    var litigationAnsweredEvent  = holdingContract.GetEvent("LitigationAnswered");
                    var litigationTimedOutEvent  = holdingContract.GetEvent("LitigationTimedOut");
                    var litigationCompletedEvent = holdingContract.GetEvent("LitigationCompleted");
                    var replacementStartedEvent  = holdingContract.GetEvent("ReplacementStarted");

                    ulong size = (ulong)10000;

                    BlockBatcher batcher = BlockBatcher.Start(contract.SyncBlockNumber, (ulong)LatestBlockNumber.Value, size,
                                                              async delegate(ulong start, ulong end)
                    {
                        await Sync(connection, litigationInitiatedEvent, litigationAnsweredEvent,
                                   litigationTimedOutEvent,
                                   litigationCompletedEvent,
                                   replacementStartedEvent,
                                   contract, source, start,
                                   end, blockchainID, cl);
                    });

                    await batcher.Execute();
                }
            }

            return(true);
        }
Exemple #4
0
        public EthereumTransactionDao(ILogger logger)
        {
            _logger = logger;

            var webNode = new Web3(System.Configuration.ConfigurationManager.AppSettings["ethUrl"])
            {
                TransactionManager = { DefaultGasPrice = 0 }
            };

            Contract = Duck.Cast <IContract>(webNode.Eth.GetContract(AbiHelper.GetTransactionManagerAbi(), System.Configuration.ConfigurationManager.AppSettings["contractAddress"]));
        }
Exemple #5
0
        private T CallTransactionFunction <T>(string address, string functionName)
        {
            dynamic transactionContract;

            if (TransactionContract == null)
            {
                transactionContract = _webNode.Eth.GetContract(AbiHelper.GetTransactionAbi(), address);
            }
            else
            {
                transactionContract = TransactionContract;
            }

            return(CallTransactionFunction <T>(functionName, transactionContract));
        }
        public async Task <string> GetLatestABIForContract([FromQuery] int blockchainID, [FromQuery] int contractType)
        {
            await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                var blockchainRow = await connection.QueryFirstAsync("SELECT * FROM blockchains where id = @id", new { id = blockchainID });

                string blockchainName = blockchainRow.BlockchainName;
                string networkName    = blockchainRow.NetworkName;

                BlockchainType    blockchainEnum  = Enum.Parse <BlockchainType>(blockchainName);
                BlockchainNetwork networkNameEnum = Enum.Parse <BlockchainNetwork>(networkName);

                return(AbiHelper.GetContractAbi((ContractTypeEnum)contractType, blockchainEnum, networkNameEnum));
            }
        }
Exemple #7
0
        public void GetContractAbi(ContractTypeEnum type)
        {
            string abi = AbiHelper.GetContractAbi(type, BlockchainType.Ethereum, BlockchainNetwork.Mainnet);

            Assert.NotNull(abi);
            Assert.NotEmpty(abi);

            abi = AbiHelper.GetContractAbi(type, BlockchainType.Ethereum, BlockchainNetwork.Rinkeby);

            Assert.NotNull(abi);
            Assert.NotEmpty(abi);

            abi = AbiHelper.GetContractAbi(type, BlockchainType.xDai, BlockchainNetwork.Mainnet);

            Assert.NotNull(abi);
            Assert.NotEmpty(abi);
        }
Exemple #8
0
        private async Task ProcessJob(MySqlConnection connection, int blockchainID, OTIdentity[] identities,
                                      string address, BlockchainType blockchain, BlockchainNetwork network, Source source, uint id)
        {
            string abi = AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchain, network);

            string nodeUrl = await connection.ExecuteScalarAsync <string>(@"SELECT BlockchainNodeUrl FROM blockchains WHERE id = @id", new
            {
                id = blockchainID
            });

            var cl = new Web3(nodeUrl);

            var eth = new EthApiService(cl.Client);

            Int32 percentage = 0;
            int   counter    = 0;

            foreach (OTIdentity identity in identities)
            {
                counter++;
                try
                {
                    int loopPercentage = (int)Math.Round((decimal)counter * 100 / identities.Count(), MidpointRounding.AwayFromZero);
                    if (loopPercentage != percentage)
                    {
                        percentage = loopPercentage;

                        await connection.ExecuteAsync(@"UPDATE findnodesbywalletjob SET Progress = @percentage WHERE ID = @id", new
                        {
                            id = id,
                            percentage
                        });
                    }

                    var ercContract = new Contract(eth, abi, identity.Identity);

                    Function keyHasPurposeFunction = ercContract.GetFunction("keyHasPurpose");

                    var    abiEncode = new ABIEncode();
                    byte[] data      = abiEncode.GetABIEncodedPacked(address.HexToByteArray());

                    byte[] bytes = CalculateHash(data);

                    await TimeConstraint;
                    bool  hasPermission = await keyHasPurposeFunction.CallAsync <bool>(bytes, 1);

                    if (hasPermission)
                    {
                        await connection.ExecuteAsync(@"INSERT INTO findnodesbywalletresult(JobID, Identity)
VALUES(@jobID, @identity)", new
                        {
                            jobID    = id,
                            identity = identity.Identity
                        });
                    }
                }
                catch (Exception ex)
                {
                    throw;
                }
            }

            await connection.ExecuteAsync(@"UPDATE findnodesbywalletjob SET Progress = 100, EndDate = @endDate WHERE ID = @id", new
            {
                id      = id,
                endDate = DateTime.UtcNow
            });
        }
Exemple #9
0
        public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network)
        {
            ClientBase.ConnectionTimeout = new TimeSpan(0, 0, 5, 0);

            await using (var connection =
                             new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                int blockchainID = await GetBlockchainID(connection, blockchain, network);

                var cl = await GetWeb3(connection, blockchainID, blockchain);

                var profileStorageContractAddress = (await OTContract
                                                     .GetByTypeAndBlockchain(connection, (int)ContractTypeEnum.ProfileStorage, blockchainID)).SingleOrDefault(a => a.IsLatest);

                if (profileStorageContractAddress == null)
                {
                    return(false);
                }

                var profileStorageContract =
                    new Contract(new EthApiService(cl.Client),
                                 AbiHelper.GetContractAbi(ContractTypeEnum.ProfileStorage, blockchain, network),
                                 profileStorageContractAddress.Address);
                var profileFunction = profileStorageContract.GetFunction("profile");

                var currentIdentities = await OTIdentity.GetAll(connection, blockchainID);

                Dictionary <string, decimal> paidOutBalances = (await connection
                                                                .QueryAsync <PayoutGroupHolder>(
                                                                    @"SELECT Holder, SUM(Amount) Amount FROM OTContract_Holding_Paidout WHERE BlockchainID = @blockchainID GROUP BY Holder",
                                                                    new
                {
                    blockchainID = blockchainID
                }))
                                                               .ToDictionary(k => k.Holder, k => k.Amount);

                Dictionary <string, OfferGroupHolder> offerTotals = (await connection.QueryAsync <OfferGroupHolder>(
                                                                         @"select i.Identity, COUNT(o.OfferID) as OffersTotal,
(SELECT count(so.OfferID) FROM otoffer_holders sh join otoffer so on so.OfferID = sh.OfferID AND so.BlockchainID = sh.BlockchainID
    WHERE sh.blockchainid = @blockchainID and sh.Holder = i.Identity AND so.CreatedTimestamp >= Date_Add(NOW(), INTERVAL -7 DAY)) as OffersLast7Days
 from otidentity i
join otoffer_holders h on h.Holder = i.Identity AND h.BlockchainID = i.BlockchainID
join otoffer o on o.OfferID = h.OfferID AND o.BlockchainID = h.BlockchainID
WHERE i.blockchainid = @blockchainID
GROUP BY i.Identity", new
                {
                    blockchainID
                })).ToDictionary(k => k.Identity, k => k);
//                NodeManagementWallet[] managementWallets = (await connection.QueryAsync<NodeManagementWallet>(
//                    @"SELECT I.Identity, PC.ManagementWallet as CreateWallet, IT.ManagementWallet TransferWallet FROM OTIdentity I
//LEFT JOIN OTContract_Profile_ProfileCreated PC ON PC.Profile = I.Identity AND PC.BlockchainID = I.BlockchainID
//LEFT JOIN OTContract_Profile_IdentityTransferred IT ON IT.NewIdentity = I.Identity AND IT.BlockchainID = I.BlockchainID
//WHERE I.Version > 0 AND I.BlockchainID = @blockchainID", new
//                    {
//                        blockchainID
//                    })).ToArray();


                foreach (OTIdentity currentIdentity in currentIdentities)
                {
                    bool     updateProfile    = true;
                    DateTime?lastActivityDate = null;

                    if (currentIdentity.Version != Constants.CurrentERCVersion)
                    {
                        if (currentIdentity.LastSyncedTimestamp.HasValue)
                        {
                            DateTime adjustedNowTime = DateTime.Now;

                            if ((adjustedNowTime - currentIdentity.LastSyncedTimestamp.Value).TotalDays <= 14)
                            {
                                updateProfile = false;
                            }
                        }
                    }
                    else if (currentIdentity.LastSyncedTimestamp.HasValue)
                    {
                        var dates = (await connection.QueryAsync <DateTime?>(@"
select MAX(Timestamp) from otcontract_profile_identitycreated r
join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID
WHERE r.NewIdentity = @identity AND r.blockchainID = @blockchainID
union
select MAX(Timestamp) from otcontract_profile_identitytransferred r
join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID
WHERE r.NewIdentity = @identity AND r.blockchainID = @blockchainID
union
select MAX(Timestamp) from otcontract_profile_profilecreated r
join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID
WHERE r.Profile = @identity AND r.blockchainID = @blockchainID
union
select MAX(Timestamp) from otcontract_profile_tokensdeposited r
join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID
WHERE r.Profile = @identity AND r.blockchainID = @blockchainID
union
select MAX(Timestamp) from otcontract_profile_tokensreleased r
join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID
WHERE r.Profile = @identity AND r.blockchainID = @blockchainID
union
select MAX(Timestamp) from otcontract_profile_tokensreserved r
join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID
WHERE r.Profile = @identity AND r.blockchainID = @blockchainID
union
select MAX(Timestamp) from otcontract_profile_tokenstransferred r
join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID
WHERE (r.Sender = @identity OR r.Receiver = @identity) AND r.blockchainID = @blockchainID
union
select MAX(Timestamp) from otcontract_profile_tokenswithdrawn r
join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID
WHERE r.Profile = @identity AND r.blockchainID = @blockchainID
union
select MAX(b.Timestamp) from otoffer_holders h
join otoffer o on o.offerid = h.offerid and o.BlockchainID = h.BlockchainID
join ethblock b on b.blocknumber = o.finalizedblocknumber AND h.BlockchainID = b.BlockchainID
where h.Holder = @identity  AND h.blockchainID = @blockchainID
union
SELECT MAX(Timestamp)
FROM otcontract_litigation_litigationcompleted lc
WHERE lc.HolderIdentity = @identity AND lc.DHWasPenalized = 1 AND lc.blockchainID = @blockchainID
union
select MAX(b.Timestamp) from otcontract_holding_paidout p
join ethblock b on b.blocknumber = p.blocknumber and b.BlockchainID = p.BlockchainID
where p.holder = @identity AND p.blockchainID = @blockchainID
union
select MAX(b.Timestamp)  from otcontract_holding_offerfinalized of
join otcontract_holding_offercreated oc on oc.OfferId = of.OfferId and oc.BlockchainID = of.BlockchainID
join OTIdentity i on i.NodeId = oc.DCNodeId and i.BlockchainID = oc.BlockchainID
join ethblock b on of.BlockNumber = b.BlockNumber and b.BlockchainID = of.BlockchainID
where i.Identity = @identity AND of.blockchainID = @blockchainID", new
                        {
                            identity = currentIdentity.Identity,
                            blockchainID
                        })).ToArray().Where(d => d.HasValue).Select(d => d.Value).ToArray();



                        var adjustedNowTime = DateTime.Now;



                        if (dates.Any())
                        {
                            lastActivityDate = dates.Max();

                            if (lastActivityDate.Value <= currentIdentity.LastSyncedTimestamp)
                            {
                                if ((adjustedNowTime - currentIdentity.LastSyncedTimestamp.Value).TotalHours <= 16)
                                {
                                    updateProfile = false;
                                }
                            }
                        }
                        else
                        {
                            if ((adjustedNowTime - currentIdentity.LastSyncedTimestamp.Value).TotalHours <= 24)
                            {
                                updateProfile = false;
                            }
                        }
                    }

                    if (updateProfile || (currentIdentity.NodeId ?? "").Length > 40)
                    {
                        var output =
                            await profileFunction.CallDeserializingToObjectAsync <ProfileFunctionOutput>(
                                currentIdentity.Identity);

                        var stake               = Web3.Convert.FromWei(output.stake);
                        var stakeReserved       = Web3.Convert.FromWei(output.stakeReserved);
                        var nodeId              = HexHelper.ByteArrayToString(output.nodeId, false).Substring(0, 40);
                        var withdrawalAmount    = Web3.Convert.FromWei(output.withdrawalAmount);
                        var withdrawalTimestamp = (UInt64)output.withdrawalTimestamp;
                        var reputation          = (UInt64)output.reputation;

                        if (currentIdentity.Stake != stake ||
                            currentIdentity.StakeReserved != stakeReserved ||
                            currentIdentity.NodeId != nodeId ||
                            currentIdentity.WithdrawalAmount != withdrawalAmount ||
                            currentIdentity.WithdrawalPending != output.withdrawalPending ||
                            currentIdentity.WithdrawalTimestamp != withdrawalTimestamp ||
                            currentIdentity.Reputation != reputation)
                        {
                            currentIdentity.Stake               = stake;
                            currentIdentity.StakeReserved       = stakeReserved;
                            currentIdentity.NodeId              = nodeId;
                            currentIdentity.WithdrawalAmount    = withdrawalAmount;
                            currentIdentity.WithdrawalPending   = output.withdrawalPending;
                            currentIdentity.WithdrawalTimestamp = withdrawalTimestamp;
                            currentIdentity.Reputation          = reputation;
                            currentIdentity.LastSyncedTimestamp = DateTime.Now;

                            await OTIdentity.UpdateFromProfileFunction(connection, currentIdentity);
                        }
                        else
                        {
                            currentIdentity.LastSyncedTimestamp = DateTime.Now;
                            await OTIdentity.UpdateLastSyncedTimestamp(connection, currentIdentity);
                        }
                    }

                    if (!paidOutBalances.TryGetValue(currentIdentity.Identity, out var paidRow))
                    {
                        paidRow = 0;
                    }

                    offerTotals.TryGetValue(currentIdentity.Identity, out var offerRow);

                    if (currentIdentity.Paidout != paidRow ||
                        currentIdentity.TotalOffers != (offerRow?.OffersTotal ?? 0) ||
                        currentIdentity.OffersLast7Days != (offerRow?.OffersLast7Days ?? 0) ||
                        currentIdentity.ActiveOffers != 0 ||
                        (currentIdentity.LastActivityTimestamp != lastActivityDate && lastActivityDate.HasValue))
                    {
                        currentIdentity.Paidout               = paidRow;
                        currentIdentity.TotalOffers           = offerRow?.OffersTotal ?? 0;
                        currentIdentity.OffersLast7Days       = offerRow?.OffersLast7Days ?? 0;
                        currentIdentity.ActiveOffers          = 0;
                        currentIdentity.LastActivityTimestamp = lastActivityDate;

                        await OTIdentity.UpdateFromPaidoutAndApprovedCalculation(connection, currentIdentity);
                    }
                }
            }

            return(true);
        }
Exemple #10
0
        public static async Task <BeforePayoutResult> CanTryPayout(string nodeID, string offerId, string holdingAddress,
                                                                   string holdingStorageAddress, string litigationStorageAddress, string identity, int?blockchainID,
                                                                   string selectedAddress)
        {
            if (nodeID == null || offerId == null || holdingAddress == null || holdingStorageAddress == null || litigationStorageAddress == null || identity == null || blockchainID == null || selectedAddress == null)
            {
                return(new BeforePayoutResult
                {
                    CanTryPayout = false,
                    Header = "Stop!",
                    Message = "Missing data in request."
                });
            }

            await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                var holdingStorageAddressModel = await connection.QueryFirstOrDefaultAsync <ContractAddress>(ContractsSql.GetHoldingStorageAddressByAddress, new
                {
                    holdingStorageAddress = holdingStorageAddress,
                    blockchainID
                });

                holdingStorageAddress = holdingStorageAddressModel?.Address;

                if (holdingStorageAddress == null)
                {
                    return(new BeforePayoutResult
                    {
                        CanTryPayout = false,
                        Header = "Stop!",
                        Message = "OT Hub is not familiar with this holding storage smart contract address for this blockchain id " + blockchainID
                    });
                }

                var blockchainRow = await connection.QueryFirstAsync("SELECT * FROM blockchains where id = @id", new { id = blockchainID });

                string blockchainName         = blockchainRow.BlockchainName;
                string networkName            = blockchainRow.NetworkName;
                string explorerTransactionUrl = blockchainRow.TransactionUrl;

                BlockchainType    blockchainEnum  = Enum.Parse <BlockchainType>(blockchainName);
                BlockchainNetwork networkNameEnum = Enum.Parse <BlockchainNetwork>(networkName);

                string nodeUrl = await connection.ExecuteScalarAsync <string>(@"SELECT BlockchainNodeUrl FROM blockchains WHERE id = @id", new
                {
                    id = blockchainID
                });

                var cl = new Web3(nodeUrl);

                var eth = new EthApiService(cl.Client);


                var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchainEnum, networkNameEnum), identity);

                Function keyHasPurposeFunction = ercContract.GetFunction("keyHasPurpose");


                var    abiEncode = new ABIEncode();
                byte[] test      = abiEncode.GetABIEncodedPacked(selectedAddress.HexToByteArray());

                byte[] bytes = CalculateHash(test);

                bool hasPermission = await keyHasPurposeFunction.CallAsync <bool>(bytes, 1) || await keyHasPurposeFunction.CallAsync <bool>(bytes, 2);

                if (!hasPermission)
                {
                    return(new BeforePayoutResult
                    {
                        CanTryPayout = false,
                        Header = "Stop!",
                        Message = "The address you have selected in MetaMask (" + selectedAddress + ") does not have permission to payout on the identity " + identity + ". You need to pick either your management wallet or operational wallet."
                    });
                }


                var holdingStorageAbi = AbiHelper.GetContractAbi(ContractTypeEnum.HoldingStorage, blockchainEnum, networkNameEnum);

                holdingAddress = (await connection.QueryFirstOrDefaultAsync <ContractAddress>(ContractsSql.GetHoldingAddressByAddress, new
                {
                    holdingAddress = holdingAddress,
                    blockchainID
                }))?.Address;

                if (holdingAddress == null)
                {
                    return(new BeforePayoutResult
                    {
                        CanTryPayout = false,
                        Header = "Stop!",
                        Message = "OT Hub is not familiar with this holding smart contract address for this blockchain id " + blockchainID
                    });
                }

                var offerIdArray = offerId.HexToByteArray();

                var holdingStorageContract =
                    new Contract(new EthApiService(cl.Client), holdingStorageAbi,
                                 holdingStorageAddress);
                var getHolderStakedAmountFunction = holdingStorageContract.GetFunction("getHolderStakedAmount");
                var holderStakedAmount            = await getHolderStakedAmountFunction.CallAsync <BigInteger>(offerIdArray, identity);

                var getHolderPaymentTimestampFunction = holdingStorageContract.GetFunction("getHolderPaymentTimestamp");
                var holderPaymentTimestamp            = await getHolderPaymentTimestampFunction.CallAsync <BigInteger>(offerIdArray, identity);

                var getOfferHoldingTimeInMinutesFunction = holdingStorageContract.GetFunction("getOfferHoldingTimeInMinutes");
                var offerHoldingTimeInMinutes            = await getOfferHoldingTimeInMinutesFunction.CallAsync <BigInteger>(offerIdArray);

                var getHolderPaidAmountFunction = holdingStorageContract.GetFunction("getHolderPaidAmount");
                var holderPaidAmount            = await getHolderPaidAmountFunction.CallAsync <BigInteger>(offerIdArray, identity);

                if (holderStakedAmount <= 0)
                {
                    return(new BeforePayoutResult
                    {
                        CanTryPayout = false,
                        Header = "Stop!",
                        Message = "The smart contract says this identity did not hold data for this job. The transaction will likely fail if you try to send this manually."
                    });
                }


                //long holdingTime = await connection.ExecuteScalarAsync<long>(
                //    @"select HoldingTimeInMinutes from otoffer where OfferID = @offerID and blockchainID = @blockchainID",
                //    new
                //    {
                //        offerId,
                //        blockchainID
                //    });

                var latestBlockParam = BlockParameter.CreateLatest();

                var block = await cl.Eth.Blocks.GetBlockWithTransactionsByNumber.SendRequestAsync(latestBlockParam);

                DateTime blockDate = TimestampHelper.UnixTimeStampToDateTime((double)block.Timestamp.Value);

                DateTime jobStartDate = await connection.ExecuteScalarAsync <DateTime>(@"SELECT Timestamp FROM otcontract_holding_offerfinalized where OfferID = @offerID and BlockchainID = @blockchainID",
                                                                                       new
                {
                    offerID = offerId,
                    blockchainID
                });

                DateTime jobEndDate = jobStartDate.AddMinutes((int)offerHoldingTimeInMinutes);

                if (blockDate > jobEndDate)
                {
                    blockDate = jobEndDate;
                }

                BigInteger blockTimestamp = new BigInteger(TimestampHelper.DateTimeToUnixTimeStamp(blockDate));


                var amountToTransfer = holderStakedAmount;
                amountToTransfer = amountToTransfer * (blockTimestamp - holderPaymentTimestamp);
                amountToTransfer = amountToTransfer / (offerHoldingTimeInMinutes * 60);

                decimal friendlyEstimatedPayout = Web3.Convert.FromWei(amountToTransfer);



                if (holderPaidAmount == holderStakedAmount)
                {
                    var friendlyAmount = Web3.Convert.FromWei(holderPaidAmount);

                    return(new BeforePayoutResult
                    {
                        CanTryPayout = false,
                        Header = "Stop!",
                        Message = "The smart contract says you have been paid " + friendlyAmount +
                                  " TRAC for this job. The transaction will likely fail if you try to send this manually."
                    });
                }

                if (!String.IsNullOrWhiteSpace(litigationStorageAddress))
                {
                    litigationStorageAddress = (await connection.QueryFirstOrDefaultAsync <ContractAddress>(@"select Address from otcontract
where Type = 9 AND Address = @litigationStorageAddress AND blockchainID = @blockchainID", new
                    {
                        litigationStorageAddress = litigationStorageAddress,
                        blockchainID
                    }))?.Address;

                    if (litigationStorageAddress == null)
                    {
                        return(new BeforePayoutResult
                        {
                            CanTryPayout = false,
                            Header = "Stop!",
                            Message = "OT Hub is not familiar with this litigation storage smart contract address for this blockchain id " + blockchainID
                        });
                    }

                    Contract storageContract = new Contract((EthApiService)cl.Eth,
                                                            AbiHelper.GetContractAbi(ContractTypeEnum.LitigationStorage, blockchainEnum, networkNameEnum), litigationStorageAddress);
                    Function getLitigationStatusFunction = storageContract.GetFunction("getLitigationStatus");

                    Function   getLitigationTimestampFunction = storageContract.GetFunction("getLitigationTimestamp");
                    BigInteger litigationTimestampInt         =
                        await getLitigationTimestampFunction.CallAsync <BigInteger>(latestBlockParam, offerIdArray,
                                                                                    identity);

                    Function getOfferLitigationIntervalInMinutesFunction =
                        holdingStorageContract.GetFunction("getOfferLitigationIntervalInMinutes");
                    BigInteger litgationInterval =
                        await getOfferLitigationIntervalInMinutesFunction.CallAsync <BigInteger>(latestBlockParam,
                                                                                                 offerIdArray) * 60;



                    var status =
                        await getLitigationStatusFunction.CallAsync <UInt16>(latestBlockParam, offerIdArray, identity);

                    if (status == 1) //initiated
                    {
                        if (litigationTimestampInt + (litgationInterval * 2) >= block.Timestamp.Value)
                        {
                            return(new BeforePayoutResult
                            {
                                CanTryPayout = false,
                                Header = "Stop!",
                                Message =
                                    "The smart contract says 'Unanswered litigation in progress, cannot pay out'. The transaction will likely fail if you try to send this manually."
                            });
                        }
                    }
                    else if (status == 2) //answered
                    {
                        if (litigationTimestampInt + (litgationInterval) >= block.Timestamp.Value)
                        {
                            return(new BeforePayoutResult
                            {
                                CanTryPayout = false,
                                Header = "Stop!",
                                Message =
                                    "The smart contract says 'Unanswered litigation in progress, cannot pay out'. The transaction will likely fail if you try to send this manually."
                            });
                        }
                    }
                    else if (status == 0) //completed
                    {
                        //Do nothing as this is fine
                    }
                    else
                    {
                        return(new BeforePayoutResult
                        {
                            CanTryPayout = false,
                            Header = "Stop!",
                            Message =
                                "The smart contract says 'Data holder is replaced or being replaced, cannot payout!'. The transaction will likely fail if you try to send this manually."
                        });
                    }
                }

                return(new BeforePayoutResult
                {
                    CanTryPayout = true,
                    BlockchainExplorerUrlFormat = explorerTransactionUrl,
                    EstimatedPayout = friendlyEstimatedPayout
                });
            }
        }
Exemple #11
0
        private static async Task ProcessHoldingSmartContractEvent(int blockchainID, BlockchainType blockchainType,
                                                                   BlockchainNetwork blockchainNetwork, EthApiService eth, FilterLog filterLog, FilterLog transaction, Web3 cl)
        {
            var contract = new Contract(eth,
                                        AbiHelper.GetContractAbi(ContractTypeEnum.Holding, blockchainType, blockchainNetwork), filterLog.Address);

            var offerCreatedEvent   = contract.GetEvent("OfferCreated");
            var offerFinalizedEvent = contract.GetEvent("OfferFinalized");
            var offerTaskEvent      = contract.GetEvent("OfferTask");
            var paidOutEvent        = contract.GetEvent("PaidOut");

            await using (var connection =
                             new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                try
                {
                    if (offerCreatedEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            offerCreatedEvent.DecodeAllEventsForEvent <Models.Program.OfferCreated>(
                                new[] { filterLog });

                        foreach (EventLog <Models.Program.OfferCreated> eventLog in events)
                        {
                            await SyncHoldingContractTask.ProcessOfferCreated(connection, blockchainID, cl,
                                                                              filterLog.Address, eventLog);
                        }

                        await ProcessJobsTask.Execute(connection, blockchainID, blockchainType, blockchainNetwork);
                    }

                    if (offerFinalizedEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            offerFinalizedEvent.DecodeAllEventsDefaultForEvent(new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncHoldingContractTask.ProcessOfferFinalised(connection, blockchainID, cl,
                                                                                filterLog.Address,
                                                                                eventLog);
                        }

                        await ProcessJobsTask.Execute(connection, blockchainID, blockchainType, blockchainNetwork);
                    }
                    if (paidOutEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            paidOutEvent.DecodeAllEventsDefaultForEvent(new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncHoldingContractTask.ProcessPayout(connection, blockchainID, cl,
                                                                        filterLog.Address, eventLog);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.WriteLine(Source.BlockchainSync, ex.ToString());
                }
            }
        }
Exemple #12
0
        private static async Task ProcessProfileSmartContractEvent(int blockchainID, BlockchainType blockchainType,
                                                                   BlockchainNetwork blockchainNetwork, EthApiService eth, FilterLog filterLog, FilterLog transaction, Web3 cl)
        {
            var contract = new Contract(eth,
                                        AbiHelper.GetContractAbi(ContractTypeEnum.Profile, blockchainType, blockchainNetwork),
                                        filterLog.Address);

            var identityCreatedEvent = contract.GetEvent("IdentityCreated");
            var profileCreatedEvent  = contract.GetEvent("ProfileCreated");
            var tokensDepositedEvent = contract.GetEvent("TokensDeposited");
            var tokensReleasedEvent  = contract.GetEvent("TokensReleased");
            var tokensWithdrawnEvent = contract.GetEvent("TokensWithdrawn");

            await using (var connection =
                             new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                try
                {
                    if (identityCreatedEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            identityCreatedEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncProfileContractTask.ProcessIdentityCreated(connection, filterLog.Address,
                                                                                 blockchainID, cl,
                                                                                 eventLog, eth);
                        }

                        await SyncProfileContractTask.CreateMissingIdentities(connection, cl, blockchainID,
                                                                              blockchainType, blockchainNetwork);
                    }

                    if (profileCreatedEvent.IsLogForEvent(transaction))
                    {
                        Function createProfileFunction = contract.GetFunction("createProfile");

                        var events =
                            profileCreatedEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncProfileContractTask.ProcessProfileCreated(connection, filterLog.Address, createProfileFunction,
                                                                                blockchainID, cl,
                                                                                eventLog, eth);
                        }

                        await SyncProfileContractTask.CreateMissingIdentities(connection, cl, blockchainID,
                                                                              blockchainType, blockchainNetwork);
                    }

                    if (tokensDepositedEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            tokensDepositedEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (var eventLog in events.GroupBy(t => t.Log.TransactionHash))
                        {
                            await SyncProfileContractTask.ProcessTokensDeposited(connection, filterLog.Address,
                                                                                 blockchainID, cl,
                                                                                 eventLog, eth);
                        }
                    }

                    if (tokensReleasedEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            tokensReleasedEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (var eventLog in events.GroupBy(t => t.Log.TransactionHash))
                        {
                            await SyncProfileContractTask.ProcessTokensReleased(connection, filterLog.Address,
                                                                                blockchainID, cl,
                                                                                eventLog, eth);
                        }
                    }

                    if (tokensWithdrawnEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            tokensWithdrawnEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (var eventLog in events.GroupBy(t => t.Log.TransactionHash))
                        {
                            await SyncProfileContractTask.ProcessTokensWithdrawn(connection, filterLog.Address,
                                                                                 blockchainID, cl,
                                                                                 eventLog, eth);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.WriteLine(Source.BlockchainSync, ex.ToString());
                }
            }
        }
Exemple #13
0
        private static async Task ProcessLitigationSmartContractEvent(int blockchainID, BlockchainType blockchainType,
                                                                      BlockchainNetwork blockchainNetwork, EthApiService eth, FilterLog filterLog, FilterLog transaction, Web3 cl)
        {
            var contract = new Contract(eth,
                                        AbiHelper.GetContractAbi(ContractTypeEnum.Litigation, blockchainType, blockchainNetwork),
                                        filterLog.Address);

            var litigationInitiatedEvent = contract.GetEvent("LitigationInitiated");
            var litigationAnsweredEvent  = contract.GetEvent("LitigationAnswered");
            var litigationTimedOutEvent  = contract.GetEvent("LitigationTimedOut");
            var litigationCompletedEvent = contract.GetEvent("LitigationCompleted");
            var replacementStartedEvent  = contract.GetEvent("ReplacementStarted");

            await using (var connection =
                             new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                try
                {
                    if (litigationInitiatedEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            litigationInitiatedEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncLitigationContractTask.ProcessLitigationInitiated(connection,
                                                                                        blockchainID, cl,
                                                                                        eventLog, eth);
                        }
                    }

                    if (litigationAnsweredEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            litigationAnsweredEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncLitigationContractTask.ProcessLitigationAnswered(connection,
                                                                                       blockchainID, cl,
                                                                                       eventLog, eth);
                        }
                    }

                    if (litigationTimedOutEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            litigationTimedOutEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncLitigationContractTask.ProcessLitigationTimedOut(connection,
                                                                                       blockchainID, cl,
                                                                                       eventLog, eth);
                        }
                    }

                    if (litigationCompletedEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            litigationCompletedEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncLitigationContractTask.ProcessLitigationCompleted(connection,
                                                                                        blockchainID, cl,
                                                                                        eventLog, eth);
                        }
                    }

                    if (replacementStartedEvent.IsLogForEvent(transaction))
                    {
                        var events =
                            replacementStartedEvent.DecodeAllEventsDefaultForEvent(
                                new[] { filterLog });

                        foreach (EventLog <List <ParameterOutput> > eventLog in events)
                        {
                            await SyncLitigationContractTask.ProcessLitigationCompleted(connection,
                                                                                        blockchainID, cl,
                                                                                        eventLog, eth);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.WriteLine(Source.BlockchainSync, ex.ToString());
                }
            }
        }
Exemple #14
0
        private async Task PopulateSmartContracts(MySqlConnection connection, string hubAddress, bool isLatest,
                                                  int blockchainID, BlockchainType blockchain, BlockchainNetwork network)
        {
            var web3 = await GetWeb3(connection, blockchainID, blockchain);

            EthApiService eth = new EthApiService(web3.Client);

            var hubContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.Hub, blockchain, network),
                                           hubAddress);

            HubAddress hubAddressModel = await GetHubAddressModel(connection, hubAddress, blockchainID, isLatest);

            if (blockchain == BlockchainType.Ethereum && network == BlockchainNetwork.Mainnet)
            {
                await PopulateOriginalETHContracts(connection, blockchainID, hubAddressModel.FromBlockNumber);
            }

            Event contractsChangedEvent = hubContract.GetEvent("ContractsChanged");

            ulong diff = (ulong)LatestBlockNumber.Value - hubAddressModel.SyncBlockNumber;

            ulong size = (ulong)10000;

beforeSync:
            if (diff > size)
            {
                ulong currentStart = hubAddressModel.SyncBlockNumber;
                ulong currentEnd   = currentStart + size;

                if (currentEnd > LatestBlockNumber.Value)
                {
                    currentEnd = (ulong)LatestBlockNumber.Value;
                }

                bool canRetry = true;
                while (currentStart == 0 || currentStart < LatestBlockNumber.Value)
                {
start:
                    try
                    {
                        await SyncContractsChanged(contractsChangedEvent,
                                                   currentStart, currentEnd,
                                                   hubContract, web3, connection, blockchainID);
                    }
                    catch (RpcResponseException ex) when(ex.Message.Contains("query returned more than"))
                    {
                        size = size / 2;

                        Logger.WriteLine(Source.BlockchainSync, "Swapping to block sync size of " + size);

                        goto beforeSync;
                    }
                    catch (RpcClientUnknownException ex) when(canRetry &&
                                                              ex.GetBaseException().Message.Contains("Gateway"))
                    {
                        canRetry = false;
                        goto start;
                    }

                    currentStart = currentEnd;
                    currentEnd   = currentStart + size;

                    if (currentEnd > LatestBlockNumber.Value)
                    {
                        currentEnd = (ulong)LatestBlockNumber.Value;
                    }
                }
            }
            else
            {
                await SyncContractsChanged(contractsChangedEvent,
                                           hubAddressModel.SyncBlockNumber, (ulong)LatestBlockNumber.Value,
                                           hubContract, web3, connection, blockchainID);
            }

            await SyncLatestContractsOnHub(hubAddressModel.FromBlockNumber, hubContract, connection, blockchainID, isLatest);
        }
Exemple #15
0
        public void ThatTransactionManagerAbiIsParsedCorrectly()
        {
            string abi = AbiHelper.GetTransactionManagerAbi();

            Assert.AreEqual(@"[]", abi);
        }
Exemple #16
0
        public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network)
        {
            ClientBase.ConnectionTimeout = new TimeSpan(0, 0, 5, 0);


            await using (var connection =
                             new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                int blockchainID = await GetBlockchainID(connection, blockchain, network);

                var cl = await GetWeb3(connection, blockchainID, blockchain);

                var eth = new EthApiService(cl.Client);

                foreach (var contract in await OTContract.GetByTypeAndBlockchain(connection, (int)ContractTypeEnum.Profile, blockchainID))
                {
                    if (contract.IsArchived && contract.LastSyncedTimestamp.HasValue &&
                        (DateTime.Now - contract.LastSyncedTimestamp.Value).TotalDays <= 5)
                    {
#if DEBUG
                        Logger.WriteLine(source, "     Skipping contract: " + contract.Address);
#endif
                        continue;
                    }

                    Logger.WriteLine(source, "     Using contract: " + contract.Address);

                    string abi = AbiHelper.GetContractAbi(ContractTypeEnum.Profile, blockchain, network);


                    var profileContract = new Contract(eth, abi, contract.Address);

                    var      profileCreatedEvent      = profileContract.GetEvent("ProfileCreated");
                    var      identityCreatedEvent     = profileContract.GetEvent("IdentityCreated");
                    var      identityTransferredEvent = profileContract.GetEvent("IdentityTransferred");
                    var      tokensDepositedEvent     = profileContract.GetEvent("TokensDeposited");
                    var      tokensReleasedEvent      = profileContract.GetEvent("TokensReleased");
                    var      tokensWithdrawnEvent     = profileContract.GetEvent("TokensWithdrawn");
                    var      tokensTransferredEvent   = profileContract.GetEvent("TokensTransferred");
                    var      tokensReservedEvent      = profileContract.GetEvent("TokensReserved");
                    Function createProfileFunction    = profileContract.GetFunction("createProfile");
                    Function transferProfileFunction  = profileContract.GetFunction("transferProfile");

                    ulong size = (ulong)10000;

                    BlockBatcher batcher = BlockBatcher.Start(contract.SyncBlockNumber, (ulong)LatestBlockNumber.Value, size,
                                                              async delegate(ulong start, ulong end)
                    {
                        await Sync(connection, profileCreatedEvent, identityCreatedEvent,
                                   identityTransferredEvent,
                                   tokensDepositedEvent,
                                   tokensReleasedEvent, tokensWithdrawnEvent, tokensTransferredEvent,
                                   tokensReservedEvent,
                                   contract, source, createProfileFunction, transferProfileFunction, start,
                                   end, blockchainID, cl);
                    });

                    await batcher.Execute();
                }

                await CreateMissingIdentities(connection, cl, blockchainID, blockchain, network);
            }

            return(true);
        }