/// <summary>
        /// 交易业务说明
        /// SendRaw是将交易数据从 任意节点(任意节点包括共识节点) 流转到 一个共识节点的过程
        ///
        /// 1.流转说明
        /// 如果SendRaw发起者就是共识节点,则不需要再流转了,直接处理交易
        /// 如果不是,只流转给自己连接的节点中plevel 小于等于自己的,这个没见到
        /// 2.sendraw参数
        /// SendRaw(byte[] message,SignData)
        /// 发送交易只需要两个数据,一个 bytearray,一个signdata,一定是byte[],不要整什么MessagePackObjectList
        /// signdata参考neo的最简形态,我们只支持最简的 txpool.TransactionSign 写在那里的
        /// 3.流转验证
        /// 每一次流转,都要检查sendraw 数据对不对
        /// signdata里面的vscript 包含公钥,iscript包含签名数据,执行ecc验签,不通过不转发,还记录本地黑名单,第二次收到,都不需要验证
        ///
        /// 4.txid
        /// 交易的id ,就是交易message 的 hash256,保持和neo兼容
        ///
        /// 5.共识节点收到交易的处理
        /// 交易不是块,和块没有关系
        /// 先忽略共识过程,系统就一个共识节点,自己就是议长。议长干的第一件事是构造一个统一的交易内存池
        /// 收到交易,只需要存在内存里
        /// 我们先假设所有共识节点有同样的交易index,交易的index是由议长分配的,议长分配完id,告知所有的共识节点
        ///
        /// 当前共识节点收到交易,给他分配一个index,就存在自己的内存池里,不需要存数据库。
        /// 分配了index的交易就可以全网广播,>=plevel
        /// 然后开一个定时器,定时从自己的内存池里挑一些交易,组装成块,广播
        ///
        /// block 的header 包括当前块所包含的交易的hash
        /// block 的body 就是 所有的包含的交易的 message 和 signdata
        /// 只需要广播block的header,block的body 各个节点自己就可以组装
        ///
        /// 6.错过广播
        /// 错过广播是很正常的,所以每个节点有一个高度设计,就是block的index
        /// 可以找任意高度大于自己的节点索要指定的block header(by block index or block id) 和 指定的hash(by txid)
        ///
        /// 7.数据存储
        /// 对共识节点,仅当组装成块的时候,一次性写入 block header、block涉及的交易、当前高度,用db 的 writebatch 方式
        /// 刚收到的交易不写数据库,仅有随块一起写入的,并且已写入的交易,内存池里就不必保持了。
        /// 但是所有的txid->block index 的映射,内存池里要保持
        /// </summary>
        /// <param name="from"></param>
        /// <param name="dict"></param>
        //static DateTime start;
        //static int recvcount = 0;
        void OnRecv_Post_SendRaw(IModulePipeline from, MessagePackObjectDictionary dict)
        {
            //if(recvcount == 0 )
            //{
            //    start = DateTime.Now;
            //}
            //recvcount++;
            logger.Info($"------OnRecv_Post_SendRaw  From:{from?.system?.Remote?.ToString()??"Local"} -------");
            //验证交易合法性,合法就收
            var  signData = SerializeHelper.DeserializeWithBinary <TransactionSign>(dict["signData"].AsBinary());
            bool sign     = Helper_NEO.VerifySignature(dict["message"].AsBinary(), signData.IScript, signData.VScript);

            if (!sign)
            {
                logger.Info($"------OnRecv_Post_SendRaw  sign error -------");
                return;
            }
            //if (recvcount % 20 == 0)
            //{
            //    var end = DateTime.Now;
            //    logger.Info("recv count:" + recvcount + " span=" + (end - start).TotalMilliseconds + "  txpool.discard"+ TXPool.txpoolcount);
            //}

            //收到消息后要么转发,要么保存
            if (this.isProved)
            {
                Transaction trans = new Transaction();
                trans.Index    = this.txpool.MaxTransactionID;
                trans.message  = dict["message"].AsBinary();
                trans.signdata = signData;
                lock (blockTimerLock)
                {
                    this.txpool.AddTx(trans);
                }
                //向内存池保存完,向全网广播这个交易
                foreach (var item in this.linkNodes)
                {
                    if (item.Value.hadJoin)
                    {
                        Tell_BoardCast_Tx(item.Value.remoteNode, dict["message"].AsBinary(), dict["signData"].AsBinary());
                    }
                }
            }
            else
            {
                //只流转给非记账节点,按照优先级,小于等于自己的其中一个
                LinkObj minLink = null;
                foreach (var item in this.linkNodes)
                {
                    if ((minLink == null || item.Value.pLevel < minLink.pLevel) && (item.Value.hadJoin))
                    {
                        minLink = item.Value;
                    }
                }
                if (minLink != null)
                {
                    Tell_SendRaw(minLink.remoteNode, dict["message"].AsBinary(), dict["signData"].AsBinary());
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// 根据data得到挑选 dataserver
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        IModulePipeline getServer(byte[] data)
        {
            int hash = Helper_NEO.CalcHash256(data).GetHashCode() % serverPath.Count;
            var path = serverPath[hash];

            return(this.DataServerDic[path]);
        }
 public byte[] GetPrivate(ThinNeo.NEP6.ScryptParameters sp, string password)
 {
     if (nep2key == null)
     {
         return(null);
     }
     return(Helper_NEO.GetPrivateKeyFromNEP2(nep2key, password, sp.N, sp.R, sp.P));
 }
Beispiel #4
0
        public Module_Node(AllPet.Common.ILogger logger, Newtonsoft.Json.Linq.JObject configJson) : base(true)
        {
            this.guid      = Helper_NEO.CalcHash256(Guid.NewGuid().ToByteArray());
            this.logger    = logger;
            this.config    = new Config_Module(configJson);
            this.chainHash = Helper_NEO.CalcHash256(this.config.ChainInfo.ToInitScript());
            //this.config = new Config_ChainInit(configJson);
            this.linkNodes   = new System.Collections.Concurrent.ConcurrentDictionary <ulong, LinkObj>();
            this.provedNodes = new System.Collections.Concurrent.ConcurrentDictionary <ulong, LinkObj>();
            this.linkIDs     = new System.Collections.Concurrent.ConcurrentDictionary <string, ulong>();
            this.listCanlink = new Struct.ThreadSafeQueueWithKey <CanLinkObj>();

            try
            {
                if (configJson.ContainsKey("Key_Nep2") && configJson.ContainsKey("Key_Password"))
                {
                    var nep2     = configJson["Key_Nep2"].AsString();
                    var password = configJson["Key_Password"].AsString();
                    this.prikey = Helper_NEO.GetPrivateKeyFromNEP2(nep2, password);
                    this.pubkey = Helper_NEO.GetPublicKey_FromPrivateKey(prikey);
                    //区分记账人
                    var address = Helper_NEO.GetAddress_FromPublicKey(pubkey); //证明人的地址
                                                                               //如果证明人的地址和初始记账人的地址相同即为记账人
                    if (this.config.ChainInfo.InitOwner.Contains(address))
                    {
                        this.isProved = true;
                        this.pLevel   = 0;//记账节点
                    }
                }
                //return;
                blockChain = new BlockChain();
                blockChain.InitChain(this.config.SimpleDbPath, this.config.ChainInfo);
                this.blockIndex = blockChain.GetBlockCount();

                //记账节点才需要出块
                if (this.isProved)
                {
                    this.blockTimer           = new System.Timers.Timer();
                    this.blockTimer.Interval  = blockTime * 1000; //毫秒
                    this.blockTimer.Enabled   = true;
                    this.blockTimer.AutoReset = true;             //一直执行true
                    this.blockTimer.Elapsed  += new System.Timers.ElapsedEventHandler(MakeBlock);
                    this.blockTimer.Start();
                }
            }
            catch (Exception err)
            {
                logger.Error("Error in Get Prikey:" + err.ToString());
                throw new Exception("error in get prikey.", err);
            }

            this.txpool = new Node.TXPool();
            ResetCanlinkList();
        }
 public bool VerifyPassword(string password)
 {
     try
     {
         var prikey = Helper_NEO.GetPrivateKeyFromNEP2(nep2key, password);
         return(true);
     }
     catch (FormatException)
     {
         return(false);
     }
 }
        void OnRecv_Response_Tx(IModulePipeline from, MessagePackObjectDictionary dict)
        {
            var tx = dict["tx"].AsBinary();

            if (tx != null)
            {
                var trans = SerializeHelper.DeserializeWithBinary <Transaction>(tx);
                //验证交易合法性,合法就收
                bool sign = Helper_NEO.VerifySignature(trans.message, trans.signdata.IScript, trans.signdata.VScript);
                if (!sign)
                {
                    return;
                }
                this.txpool.AddTx(trans);
            }
        }
        void OnRecv_BoardCast_Tx(IModulePipeline from, MessagePackObjectDictionary dict)
        {
            var  signData = SerializeHelper.DeserializeWithBinary <TransactionSign>(dict["signData"].AsBinary());
            bool sign     = Helper_NEO.VerifySignature(dict["message"].AsBinary(), signData.IScript, signData.VScript);

            if (!sign)
            {
                return;
            }
            Transaction trans = new Transaction();

            trans.Index    = this.txpool.MaxTransactionID;
            trans.message  = dict["message"].AsBinary();
            trans.signdata = signData;
            this.txpool.AddTx(trans);
        }
        public JObject ToJson()
        {
            JObject account = new JObject();

            byte[] shash = (ScriptHash);
            var    addr  = Helper_NEO.GetAddress_FromScriptHash(shash);

            account["address"]   = addr;
            account["label"]     = null;
            account["isDefault"] = false;
            account["lock"]      = false;
            account["key"]       = nep2key;
            account["contract"]  = ((NEP6Contract)Contract)?.ToJson();
            account["extra"]     = null;
            return(account);
        }
        public void AddTx(Transaction trans)
        {
            //第一步,验证交易合法性,合法就收

            //第二步,验证Hash是否已经存在
            var txid = Helper_NEO.CalcHash256(trans.message);

            if (TXData.ContainsKey(txid))
            {
                //txpoolcount++;
                return;
            }
            //第三步,放进去并调整MaxTransactionID
            TXData.TryAdd(txid, trans);
            map_tx2index.TryAdd(MaxTransactionID, txid);
            MaxTransactionID++;
        }
Beispiel #10
0
        public RPC_Result RPC_SendRawTransaction(IList <MessagePackObject> _params)
        {
            var message = _params.First();
            var pubkey  = this.pubkey;
            var sign    = Helper_NEO.Sign(message.AsBinary(), this.prikey);

            var signdata = new TransactionSign();

            signdata.VScript = pubkey;
            signdata.IScript = sign;
            var data = SerializeHelper.SerializeToBinary(signdata);

            this.Tell_SendRaw(this._System.GetPipeline(this, "this/node"), message.AsBinary(), data);
            var result = new MessagePackObject(0);

            return(new RPC_Result(result));
        }
Beispiel #11
0
        public static NEP6Account FromJson(Newtonsoft.Json.Linq.JObject json, NEP6Wallet wallet)
        {
            var    strAdd     = (json["address"] as Newtonsoft.Json.Linq.JValue).Value as string;
            var    pubkeyhash = Helper_NEO.GetScriptHash_FromAddress(strAdd);
            string key        = null;

            if (json.ContainsKey("key") && json["key"] != null)
            {
                key = json["key"].Value <string>();
            }
            var acc = new NEP6Account(pubkeyhash, key);

            if (json.ContainsKey("contract") && json["contract"] != null)
            {
                acc.Contract = NEP6Contract.FromJson(json["contract"] as JObject);
            }
            return(acc);
        }
        void OnRecv_ResponseAcceptJoin(IModulePipeline from, MessagePackObjectDictionary dict)
        {
            logger.Info("had join chain");
            var link = this.linkNodes[from.system.PeerID];

            link.hadJoin = true;//已经和某个节点接通
            //如果连上了,标识连上的节点的优先级
            var plevel = dict["plevel"].AsInt32();

            this.getPlevelFromLinkObj(link, plevel);
            //Console.WriteLine("@ from:" + link.publicEndPoint + " plevel:" + link.pLevel + " node:" + this.config.PublicEndPoint + " plevel:" + this.pLevel);

            if (this.prikey != null)//有私钥证明一下
            {
                var check    = dict["checkinfo"].AsBinary();
                var addinfo  = Guid.NewGuid().ToByteArray();
                var message  = addinfo.Concat(check).ToArray();
                var signdata = Helper_NEO.Sign(message, this.prikey);
                Tell_Request_ProvePeer(from, addinfo, signdata);
            }
            Tell_Request_PeerList(from);
            //如果连接上了,要更新自己的优先级
            //if (this.pLevel < 0)
            //{
            //    if (link.pLevel >= 0)//加入的节点优先级有效,且本身节点不是记账人
            //    {
            //        this.pLevel = link.pLevel + 1;
            //    }
            //}
            //else if(this.pLevel > link.pLevel)
            //{
            //    this.pLevel = link.pLevel + 1;
            //    //如果是变更,则广播低优先级节点
            //    foreach (var item in this.linkNodes)
            //    {
            //        if (item.Value.hadJoin && item.Value.pLevel < this.pLevel)
            //        {
            //            Tell_BoradCast_PeerState(item.Value.remoteNode);
            //        }
            //    }
            //}

            //System.Console.WriteLine($"node:{this.config.PublicEndPoint} pLeve:{this.pLevel}  isProved:{this.isProved}");
        }
        void OnRecv_RequestProvePeer(IModulePipeline from, MessagePackObjectDictionary dict)
        {
            var  link     = this.linkNodes[from.system.PeerID];
            var  addinfo  = dict["addinfo"].AsBinary();
            var  pubkey   = dict["pubkey"].AsBinary();
            var  signdata = dict["signdata"].AsBinary();
            var  message  = addinfo.Concat(link.CheckInfo).ToArray();
            bool sign     = Helper_NEO.VerifySignature(message, signdata, pubkey);

            if (sign)
            {
                link.PublicKey = pubkey;
                logger.Info("had a proved peer:" + Helper.Bytes2HexString(pubkey));
            }
            else
            {
                logger.Info("had a error proved peer:" + Helper.Bytes2HexString(pubkey));
            }
        }
Beispiel #14
0
        public NEP6Account CreateAccount(byte[] privateKey, string password)
        {
            var          pubkey   = Helper_NEO.GetPublicKey_FromPrivateKey(privateKey);
            NEP6Contract contract = new NEP6Contract
            {
                Script = Helper_NEO.GetAddressScript_FromPublicKey(pubkey)
            };
            var scripthash = Helper_NEO.CalcHash160(pubkey);

            var nep2key = Helper_NEO.GetNep2FromPrivateKey(privateKey, password);

            NEP6Account account = new NEP6Account(scripthash, nep2key)
            {
                Contract = contract
            };

            AddAccount(account);

            return(account);
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;

            btn.IsEnabled = false;
            var address   = AddressTextBox.Text;
            var startTime = StartTimeDatePicker.SelectedDate;

            try
            {
                Helper_NEO.GetScriptHash_FromAddress(address);
            }
            catch (Exception)
            {
                MessageBox.Show("Address Error");
                return;
            }
            finally
            {
                btn.IsEnabled = true;
            }
            StateTextBlock.Text = $"Starting…";
            DoEvents();
            var totalEntries = 0;

            using (var web = new WebClient())
            {
                var json       = web.DownloadJson(address, 1);
                var totalPages = (int)json["total_pages"];
                totalEntries = (int)json["total_entries"];
                var pageSize = (int)json["page_size"];

                txList.Clear();
                var stop = false;
                for (int i = 1; i <= totalPages; i++)
                {
                    json = web.DownloadJson(address, i);
                    foreach (var item in json["entries"])
                    {
                        var tx = Transaction.FromJson(item);
                        if (tx != null)
                        {
                            if (startTime != null && tx.Time < startTime)
                            {
                                stop = true;
                                break;
                            }
                            txList.Add(tx);
                        }
                    }
                    if (stop)
                    {
                        break;
                    }
                    if (startTime == null)
                    {
                        StateTextBlock.Text = $"{Math.Min(i * pageSize, totalEntries)}/{totalEntries}";
                    }
                    else
                    {
                        StateTextBlock.Text = $"{Math.Min(i * pageSize, totalEntries)}";
                    }
                    DoEvents();
                }
            }
            StateTextBlock.Text = $"Calculating…";
            DoEvents();
            ProcessData();
            StateTextBlock.Text = $"Completed.";
            btn.IsEnabled       = true;
        }