Blockchain.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. using System;
  2. using System.Text;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using Newtonsoft.Json;
  7. using Console = HyperCube.Utils.AdvConsole;
  8. namespace HyperCube.Models
  9. {
  10. public class Blockchain
  11. {
  12. public static string Connected
  13. {
  14. get {
  15. var bc = GetMain();
  16. if (bc != null)
  17. return $"{bc.name}";
  18. return "none";
  19. }
  20. }
  21. public static string URLdefault = "127.0.0.1";
  22. public static int defaultPort = 8545;
  23. public static string defaultName = "Ethereum dev network";
  24. public static bool newData = false;
  25. public static Dictionary<string, Blockchain> loaded = new();
  26. public Dictionary<int, SmartContract> contracts = new();
  27. public Dictionary<string, SmartContract> contractNames = new();
  28. public int port;
  29. public string url;
  30. public string address = "";
  31. public string name;
  32. static Blockchain instance;
  33. public static Blockchain GetInstance()
  34. {
  35. if (instance == null)
  36. instance = new Blockchain(URLdefault, defaultPort);
  37. return instance;
  38. }
  39. Blockchain()
  40. {
  41. }
  42. public Blockchain(string url, int port)
  43. {
  44. this.url = url;
  45. this.port = port;
  46. }
  47. public async Task<string> CreateBlockchainAccount(AccountModel account)
  48. {
  49. var res = await GetMain().RunFunction("personal_newAccount", "\"password\"");
  50. Console.WriteLine($"CreateBlockchainAccount {account}: {res}");
  51. var query = $"update aspnetusers set eth_address='{res}' where UserName='{account.Name}'";
  52. account.eth_address = res;
  53. Console.WriteLine($"CreateBlockchainAccount query {query}");
  54. MySQLConnector.Instance().SQLInsert(query);
  55. return res;
  56. }
  57. public static string bin2hex(string code)
  58. {
  59. //code = "0x".bin2hex('getCount()');
  60. var bytes = Encoding.UTF8.GetBytes(code);
  61. var hex = BitConverter.ToString(bytes).Replace("-", "");
  62. Console.WriteLine("hex " + hex);
  63. return "0x" + hex;
  64. }
  65. public static string zerofill(string hex, int charCount, bool hexPrefix0x)
  66. {
  67. if (hexPrefix0x)
  68. hex = hex.Remove(0, 2);
  69. Console.WriteLine($"zerofill input {hex} count {hex.Length}");
  70. var res = hex.PadLeft(charCount, '0');
  71. Console.WriteLine($"zerofill out {hex} count {res.Length}");
  72. return res;
  73. }
  74. public static Blockchain GetMain()
  75. {
  76. if (loaded.Count > 0)
  77. return loaded.Last().Value;
  78. return null;
  79. }
  80. public async Task<string> Initialize()
  81. {
  82. string addr = await ListAccounts();
  83. if (!loaded.ContainsKey(addr))
  84. loaded.Add(addr, this);
  85. name = defaultName;
  86. url = URLdefault;
  87. port = defaultPort;
  88. Console.WriteLine("Initialize: loaded blockchains " + loaded.Count);
  89. await LoadContracts();
  90. Console.WriteLine("LoadContracts count " + contracts.Count);
  91. Console.WriteLine("connected " + Connected);
  92. return $"{name} {url}:{port}";
  93. }
  94. public async Task LoadContracts()
  95. {
  96. MySQLConnector dbCon = MySQLConnector.Instance();
  97. contracts = await dbCon.SQLSelectContracts();
  98. foreach (var contract in contracts.Values)
  99. {
  100. await contract.LoadFunction();
  101. }
  102. }
  103. public static async Task<string> GetSHA3(string code)
  104. {
  105. var hex = bin2hex(code);
  106. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"web3_sha3\",\"params\":[\"{hex}\"], \"id\":1}}";
  107. var answer = await Post.PostRequestAsync(req);
  108. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  109. Console.WriteLine("result " + jsonDe.result);
  110. return jsonDe.result;
  111. }
  112. public async Task<string> RunFunction(string name, string parms)
  113. {
  114. Console.WriteLine($"RunFunction {name} params {parms}");
  115. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"{name}\",\"params\":[{parms}], \"id\":1}}";
  116. var answer = await Post.PostRequestAsync(req);
  117. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  118. Console.WriteLine("RunFunction result " + jsonDe.result);
  119. return jsonDe.result;
  120. //return "test answer";
  121. }
  122. public async Task<string> GetBalance(string address)
  123. {
  124. var ret = await RunFunction("eth_getBalance", $"\"{address}\",\"latest\"");
  125. return ret;
  126. }
  127. public async void RunContractRead()
  128. {
  129. string answer = "no";
  130. string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{\"to\":\"0x874c6a51e62680d4594cd2555ed8fa47b63ed253\", \"data\":\"0xa87d942c\"},\"latest\"],\"id\":1}";
  131. //string req = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x0000000000000000000000000000000000000000000000000000000000000004\"}";
  132. //Console.WriteLine($"req " + req);
  133. await Post.PostRequestAsync(req);
  134. //Console.WriteLine($"answer {answer} len {answer.Length}" );
  135. address = answer;
  136. }
  137. public async Task<string> SendTransaction(string fromAddress, string toAddress, string sum)
  138. {
  139. Console.WriteLine($"SendTransaction from {fromAddress} to {toAddress} sum {sum}");
  140. var answer = await RunFunction("eth_sendTransaction", $"{{\"from\":\"{address}\",\"to\":\"{toAddress}\",\"gas\":\"0x31b2ef\", \"data\":\"\", \"value\":\"{sum}\"}}");
  141. return answer;
  142. }
  143. //{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{ "from":"0xD81eeE6b39d9556c3067A3551A3FB2882b92F327", "to":"0x119b58faddcdbc09cafcd272530aa079cec10004", "gas":"0x31b2ef", "data":"0x11111111"}], "id":1}
  144. public async Task<string> RunContractWrite(string contractAddress, string data)
  145. {
  146. Console.WriteLine("RunContract contractAddress " + contractAddress);
  147. var answer = await RunFunction("eth_sendTransaction", $"{{\"from\":\"{address}\",\"to\":\"{contractAddress}\",\"gas\":\"0x31b2ef\", \"data\":\"{data}\", \"value\":\"0x32555\"}}");
  148. //$"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_sendTransaction\",\"params\":[{{\"from\":\"{address}\",\"to\":\"{contractAddress}\",\"gas\":\"0x31b2ef\", \"data\":\"{data}\"}}], \"id\":1}}";
  149. //var answer = await Post.PostRequestAsync(req);
  150. //dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  151. //Console.WriteLine("result " + answer);
  152. return answer;
  153. }
  154. public async Task<string> GetReceipt(string transactionAddress, bool returnAddress = false)
  155. {
  156. Console.WriteLine("transactionAddress " + transactionAddress);
  157. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionReceipt\",\"params\":[\"{transactionAddress}\"], \"id\":1}}";
  158. var answer = await Post.PostRequestAsync(req);
  159. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  160. var blockHash = jsonDe.result.blockHash;
  161. var blockNumber = jsonDe.result.blockNumber;
  162. var contractAddress = jsonDe.result.contractAddress;
  163. MySQLConnector.Instance().SQLInsert($"insert into transactions (result, name) values ('{Convert.ToString(jsonDe.result)}', 'eth_getTransactionReceipt')");
  164. Console.WriteLine("result " + answer);
  165. if (returnAddress)
  166. return contractAddress;
  167. else
  168. return Convert.ToString(jsonDe.result);
  169. }
  170. public async void GetGas(string bytecode)
  171. {
  172. }
  173. public async Task<object[]> AddContract(string name, string code, string bytecode)
  174. {
  175. Console.WriteLine("bytecode " + bytecode);
  176. var req = $"{{ \"jsonrpc\":\"2.0\",\"method\":\"eth_sendTransaction\",\"params\":[{{\"from\":\"{address}\",\"gas\":\"0x31b2e\", \"data\":\"{bytecode}\"}}], \"id\":1}}";
  177. var answer = await Post.PostRequestAsync(req);
  178. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  179. var res = jsonDe.result;
  180. Console.WriteLine("result AddContract transactionAddress: " + res);
  181. if (res != null)
  182. {
  183. int id = (int)MySQLConnector.Instance().SQLInsert($"insert into smart_contracts (code, bytecode, name, date_add) values ('{code}','{bytecode}','{name}',NOW())");
  184. SmartContract newctr = new SmartContract(id, name, code, bytecode);
  185. contracts.Add(id, newctr);
  186. contractNames.Add(name, newctr);
  187. return new object[] { res, newctr };
  188. }
  189. return null;
  190. }
  191. public async Task<string> ListAccounts()
  192. {
  193. string answer = "no";
  194. //{ "jsonrpc":"2.0","method":"eth_getCode","params":["0x938cae6f6c21ed9d55196e96ef880f562e530553", "latest" ],"id":1}
  195. //string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getCode\",\"params\":[\"0x874c6a51e62680d4594cd2555ed8fa47b63ed253\",\"latest\"],\"id\":1}";
  196. string req = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_accounts\", \"params\":[],\"id\":1}";
  197. answer = await Post.PostRequestAsync(req);
  198. //string json = Encoding.UTF8.GetString(bytedata, 1, bytedata.Length - 1);
  199. //try
  200. //{
  201. Console.WriteLine("Json string " + answer);
  202. dynamic jsonDe = JsonConvert.DeserializeObject(answer);
  203. address = jsonDe.result[0];
  204. var query = $"update blockchains set address_main='{address}' where id=1";
  205. Console.WriteLine("query " + query);
  206. MySQLConnector.Instance().SQLInsert(query);
  207. Console.WriteLine("Json addr " + jsonDe.result[0]);
  208. var methodName = (string)jsonDe.name;
  209. newData = true;
  210. return address;
  211. }
  212. public string GetAddress()
  213. {
  214. //this.address = address;
  215. return address;
  216. //post запрос
  217. }
  218. }
  219. }