public ActionResult CreateNewStatement(TrustLessModelLib.Statement statement) { using (DataContext context = new DataContext()) { if (!PersonController.ValidateLoginSession(context,statement.Person.LoginSession.Token)) return new HttpStatusCodeResult((int)HttpStatusCode.Forbidden); var match = context.Statements.FirstOrDefault(x => x.MedicinOne == statement.MedicinOne && x.MedicinTwo == statement.MedicinTwo); //Does a statement already exists with the same two medicins. if (match != null) // && IsStatementValid(context,match) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); //Security: Don't allow user to specify the person who created the statement. Set it to the current user logged in. statement.Person = context.Persons.FirstOrDefault(x => x.Username == statement.Person.Username); //If the person does not exist, abort. if (statement.Person == null) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); //Rule: refuse a user with zero trust from creating statements. if (CalculateBayesianModelTrust(statement.Person) == 0) return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest); context.Statements.Add(statement); //Add recommendation from user var recommendation = new TrustLessModelLib.Recommendation(){ Person = statement.Person, Statement = statement, IsRecommended = true, Transaction = null, Description = statement.Description, CreationDate = DateTime.Now}; //This will fail if a racecondition was to add two recommendations (given that our key assignment of the table ensures only one of the same recommendation exist). context.Recommendations.Add (recommendation); context.SaveChanges (); BlockChain.MakeRecommendation (context, recommendation); return new HttpStatusCodeResult((int)HttpStatusCode.Created); } }
/// <summary> /// Issues an S or F to a user for a recommendation. /// </summary> /// <param name="recommendation">Recommendation</param> /// <param name="rewardUser">true for S asset and false for F</param> public static void Issue(TrustLessModelLib.Recommendation recommendation, bool rewardUser) { string chainName = WebConfigurationManager.AppSettings["ChainName"]; string nodeIp = WebConfigurationManager.AppSettings["NodeIp"]; MultiChainClient client = new MultiChainClient(chainName,nodeIp); GetTxOutResponse getTxOutResponse = client.GetTxOut(recommendation.Transaction.Tx,recommendation.Transaction.Vout); if (getTxOutResponse == null) return; Dictionary<string,int> amount = new Dictionary<string, int>(); amount.Add(getTxOutResponse.assets.First(x => x.name.StartsWith(rewardUser ? "S_" : "F_")).name,1); string multichainPublicKey = WebConfigurationManager.AppSettings["MultichainPublicKey"]; var resp = client.CreateRawTransaction (recommendation.Person.PublicKey, recommendation.Transaction.Tx,recommendation.Transaction.Vout, amount); var respAppendRawChange = client.AppendRawChange (resp.Hex, multichainPublicKey); var respSignTransaction = client.SignRawTransaction (respAppendRawChange.Hex); if (respSignTransaction.complete) { var respSendRawTransaction = client.SendRawTransaction (respSignTransaction.hex); if (String.IsNullOrEmpty (respSendRawTransaction.TransactionId)) client.LockUnspent (true, recommendation.Transaction.Tx,recommendation.Transaction.Vout); } }
/// <summary> /// Reserves/locks away one S and F asset and sets the recommendation to reference these assets. /// </summary> /// <param name="db">DataContext</param> /// <param name="recommendation">Recommendation</param> public static void MakeRecommendation(DataContext db, TrustLessModelLib.Recommendation recommendation) { string chainName = WebConfigurationManager.AppSettings["ChainName"]; string nodeIp = WebConfigurationManager.AppSettings["NodeIp"]; MultiChainClient client = new MultiChainClient(chainName,nodeIp); Dictionary<string,int> dictionary = new Dictionary<string, int>(); AddressBalance[] addressBalances = client.GetTotalBalances ().Balances; var lastFasset = addressBalances.OrderBy (x => x.name).LastOrDefault (x => x.name.StartsWith ("F_")); var lastSasset = addressBalances.OrderBy (x => x.name).LastOrDefault (x => x.name.StartsWith ("S_")); if (lastFasset == null || lastSasset == null) { GenerateFunds (client); MakeRecommendation (db, recommendation); return; } string lastF = lastFasset.name; string lastS = lastSasset.name; dictionary.Add(lastF,1); dictionary.Add(lastS,1); try { var resp = client.PrepareLockUnspent(dictionary); recommendation.Transaction = new ReservedTransaction() { Tx = resp.txid, Vout = resp.vout }; } catch { //Insurficient funds GenerateFunds(client); MakeRecommendation (db, recommendation); return; } db.SaveChanges (); }
/// <summary> /// Rewards users that have made a correct recommendation with an S asset and punishes users /// who were wrong in their recommendation. /// </summary> /// <param name="context">DataContext</param> /// <param name="statement">Statement</param> private void IssueTrustForStatement(DataContext context,TrustLessModelLib.Statement statement) { var recommendations = context.Recommendations.Include("Person").Include("Transaction").Where(x => x.StatementId== statement.Id && x.Transaction != null).ToList(); int sAmount = recommendations.Count (x => x.IsRecommended) +1; int fAmount = recommendations.Count (x => !x.IsRecommended); foreach (Recommendation recommendation in recommendations) { if (sAmount >= fAmount) { if (recommendation.IsRecommended) { BlockChain.Issue (recommendation,true); } else { BlockChain.Issue (recommendation,false); } } else { if (recommendation.IsRecommended) { BlockChain.Issue (recommendation,false); } else { BlockChain.Issue (recommendation,true); } } } }
/// <summary> /// Returns a boolean clarifying that a statement is complete. /// </summary> /// <param name="context"></param> /// <param name="statement"></param> /// <returns></returns> private bool IsStatementRecommendationsComplete(DataContext context,TrustLessModelLib.Statement statement) { var recommendationAmount = context.Recommendations.Count(x => x.StatementId== statement.Id && x.Transaction != null); int maxVotings = Convert.ToInt32(WebConfigurationManager.AppSettings["MaxVotings"]); return recommendationAmount >= maxVotings; }