工作,学习,生活,这里将会有一些记录. 备用域名:http://meisw.wdlinux.cn 注册 | 登陆
浏览模式: 标准 | 列表全部文章

以太坊的存储结构

 以太坊并不存在中心服务器,而是基于p2p协议连接起来的平等节点,在众多节点中存储了全部数据。当用户发起一笔交易,会通过广播通知每一个节点,矿工对此进行验证打包并进一步广播,在区块链确认以后,此操作即认为是不可更改的。

在每个节点上,数据是以区块链来存储的。区块链由一个个块串起来而组成。以太坊被描述为一个交易驱动的状态机。它在某个状态下接收一些输入,会确定的转移到另一个状态。

状态机,包含一组状态集(states)、一个起始状态(start state)、一组输入符号集(alphabet)、一个映射输入符号和当前状态到下一状态的转换函数(transition function)的计算模型。

在以太坊的一个状态下,每个账户都有确定的余额和状态信息,当他接收到新的交易以后就会进入一个新的状态,从创世块开始,不断的收到新的交易,由此能进入到一系列新的状态。

以太坊每隔一段时间就会把一批交易信息打包存储到一个块里,这个块中包含的信息有:

  1. ParentHash:父块的哈希值
  2. Number:块编号
  3. Timestamp:块产生的时间戳
  4. GasUsed:交易消耗的Gas
  5. GasLimit:Gas限制
  6. Difficulty:POW的难度值
  7. Beneficiary:块打包手续费的受益人,也称矿工
  8. Nonce:一个随机数,使得块头哈希满足POW需求

这些字段我们在上面的web3接口中都可以获取得到。

nonce,整数类型,允许使用相同随机数覆盖自己发送的处于pending状态的交易。

为了防止交易的重播攻击,每笔交易必须有一个nonce随机数,针对每一个账户nonce都是从0开始,当nonce为0的交易处理完之后,才会处理nonce为1的交易,并依次加1的交易才会被处理。以下是nonce使用的几条规则:

  • 当nonce太小,交易会被直接拒绝。
  • 当nonce太大,交易会一直处于队列之中,这也就是导致我们上面描述的问题的原因;
  • 当发送一个比较大的nonce值,然后补齐开始nonce到那个值之间的nonce,那么交易依旧可以被执行。
  • 当交易处于queue中时停止geth客户端,那么交易queue中的交易会被清除掉。

ssh普通用户目录限制根目录

 Subsystem sftp internal-sftp

Match User dist
ChrootDirectory /var/www/html
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp

以太坊客户端Geth命令用法-参数详解

以太坊客户端Geth命令用法-参数详解

 

 

https://www.cnblogs.com/tinyxiong/p/7918706.html

以太坊开发框架truffle以及testrpc注意事项

 环境版本:

Truffle v3.4.9 (core: 3.4.8)
Solidity v0.4.15 (solc-js)
EthereumJS TestRPC v4.1.1 (ganache-core: 1.1.2)
 
问题:通过Truffle和TestRPC生成测试环境以后,无法通过IP地址访问环境,而只能在本机通过localhost访问
解决方案:修改testrpc和truffle环境的三个地方

1.修改truffle生成的web框架文件里面的truffle.js文件
a96921164cd81032b7e497aa66e24e992f79c652
2.使用###>testrpc -h 0.0.0.0命令启动testrpc
3.修改truffle文件的webpack.config.js文件
c4a8a7a490ac82b3a6dac99d9ce6e1ca475b8f9f
具体全部命令

1. >mkdir myproject  

2. >cd myproject  

3. >truffle init webpack


修改完成,需要重新编译

     >truffle compile -all

4.   >truffle migrate

5.   >testrpc -h 0.0.0.0(请在另一个终端下运行这个命令)

6.   >npm run dev

来自ETH源码,手动生成以太坊钱包,ERC20标准钱包

 安装完成后用node自带的npm(node package manger)下载两个依赖: 椭圆加密算法包,keccak哈希包

npm install secp256k1 
npm install keccak

进入node交互界面

node

执行node脚本

 //引入包  const secp256k1 = require("secp256k1/elliptic")  const createKeccakHash =  require("keccak")  const crypto = require('crypto')   // 生成私钥  const privateKey = crypto.randomBytes(32)  // 生成公钥  const publicKey = secp256k1.publicKeyCreate(privateKey, false).slice(1)  // 生成地址  const address = createKeccakHash("keccak256").update(publicKey).digest().slice(-20)   // 查看结果  privateKey.toString('hex')  address.toString('hex')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

以上代码在 Imtoken钱包 导入成功, 并能够正常使用,即 核对导入后的钱包address与 脚本生成的address一致

ERC20 Token标准接口

下是一个接口合同,声明所需的功能和事件以符合ERC20标准:

 

// https://github.com/ethereum/EIPs/issues/20

  contract ERC20 {

      function totalSupply() constant returns (uint totalSupply);

      function balanceOf(address _owner) constant returns (uint balance);

      function transfer(address _to, uint _value) returns (bool success);

      function transferFrom(address _from, address _to, uint _value) returns (bool success);

      function approve(address _spender, uint _value) returns (bool success);

      function allowance(address _owner, address _spender) constant returns (uint remaining);

      event Transfer(address indexed _from, address indexed _to, uint _value);

      event Approval(address indexed _owner, address indexed _spender, uint _value);

    }

大部分Ethereum主要标记符合ERC20标准。

 

一些令牌包括描述令牌合同的进一步信息:

 

string public constant name = "Token Name";

string public constant symbol = "SYM";

uint8 public constant decimals = 18;  // 大部分都是18

如何工作?

 

以下是令牌合约的一个片段,用于演示令牌合约如何维护Ethereum帐户的令牌余额

 

contract TokenContractFragment {

 

     // Balances 保存地址的余额

     mapping(address => uint256) balances;

 

     // 帐户的所有者批准将金额转入另一个帐户

     mapping(address => mapping (address => uint256)) allowed;

 

      // 特定帐户的余额是多少?

      function balanceOf(address _owner) constant returns (uint256 balance) {

          return balances[_owner]; //从数组中取值

      }

 

      // 将余额从所有者帐户转移到另一个帐户

      function transfer(address _to, uint256 _amount) returns (bool success) {

          //判断条件 发送者余额>=要发送的值  发送的值>0  接收者余额+发送的值>接收者的余额

          if (balances[msg.sender] >= _amount 

              && _amount > 0

              && balances[_to] + _amount > balances[_to]) {

              balances[msg.sender] -= _amount;   //发送者的余额减少

              balances[_to] += _amount;         //接收者的余额增加

              return true;

         } else {

              return false;

          }

      }

 

      // 发送 _value 数量的token从地址 _from 到 地址 _to

      // transferFrom方法用于提取工作流程,允许合同以您的名义发送令牌,例如“存入”到合同地址和/或以子货币收取费用; 该命令应该失败,除非_from帐户通过某种机制故意地授权消息的发送者; 我们提出这些标准化的API来批准:

      function transferFrom(

          address _from,

          address _to,

          uint256 _amount

     ) returns (bool success) {

          //和上面一样的校验规则

          if (balances[_from] >= _amount

              && allowed[_from][msg.sender] >= _amount

              && _amount > 0

              && balances[_to] + _amount > balances[_to]) {

              balances[_from] -= _amount;

              allowed[_from][msg.sender] -= _amount; //减少发送者的批准量

              balances[_to] += _amount;

              return true;

         } else {

             return false;

          }

      }

 

      // 允许_spender多次退出您的帐户,直到_value金额。 如果再次调用此函数,它将以_value覆盖当前的余量。

      function approve(address _spender, uint256 _amount) returns (bool success) {

          allowed[msg.sender][_spender] = _amount; //覆盖当前余量

          return true;

      }

  }

 

http://blog.csdn.net/diandianxiyu_geek/article/details/78082551?utm_source=gold_browser_extension

mysql处理高并发,防止库存超卖

 今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过;但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识。今天就我的一些理解,整理一下这个问题,并希望以后这样的课程能多点。

先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购、秒杀、特价之类的活动,而这样的活动有一个共同的特点就是访问量激增、上千甚至上万人抢购一个商品。然而,作为活动商品,库存肯定是很有限的,如何控制库存不让出现超买,以防止造成不必要的损失是众多电子商务网站程序员头疼的问题,这同时也是最基本的问题。

从技术方面剖析,很多人肯定会想到事务,但是事务是控制库存超卖的必要条件,但不是充分必要条件。

举例:

总库存:4个商品

请求人:a、1个商品 b、2个商品 c、3个商品

程序如下:

beginTranse(开启事务)

try{

    $result = $dbca->query('select amount from s_store where postID = 12345');

    if(result->amount > 0){

        //quantity为请求减掉的库存数量

        $dbca->query('update s_store set amount = amount - quantity where postID = 12345');

    }

}catch($e Exception){

    rollBack(回滚)

}

commit(提交事务)

以上代码就是我们平时控制库存写的代码了,大多数人都会这么写,看似问题不大,其实隐藏着巨大的漏洞。数据库的访问其实就是对磁盘文件的访问,数据库中的表其实就是保存在磁盘上的一个个文件,甚至一个文件包含了多张表。例如由于高并发,当前有三个用户a、b、c三个用户进入到了这个事务中,这个时候会产生一个共享锁,所以在select的时候,这三个用户查到的库存数量都是4个,同时还要注意,mysql innodb查到的结果是有版本控制的,再其他用户更新没有commit之前(也就是没有产生新版本之前),当前用户查到的结果依然是就版本;

然后是update,假如这三个用户同时到达update这里,这个时候update更新语句会把并发串行化,也就是给同时到达这里的是三个用户排个序,一个一个执行,并生成排他锁,在当前这个update语句commit之前,其他用户等待执行,commit后,生成新的版本;这样执行完后,库存肯定为负数了。但是根据以上描述,我们修改一下代码就不会出现超买现象了,代码如下:

beginTranse(开启事务)

try{

    //quantity为请求减掉的库存数量
    $dbca->query('update s_store set amount = amount - quantity where postID = 12345');

    $result = $dbca->query('select amount from s_store where postID = 12345');

    if(result->amount < 0){

       throw new Exception('库存不足');

    }

}catch($e Exception){

    rollBack(回滚)

}

commit(提交事务)

 

另外,更简洁的方法:

 

beginTranse(开启事务)

try{

    //quantity为请求减掉的库存数量
    $dbca->query('update s_store set amount = amount - quantity where amount>=quantity and postID = 12345');

}catch($e Exception){

    rollBack(回滚)

}

commit(提交事务)

 

=====================================================================================

1、在秒杀的情况下,肯定不能如此高频率的去读写数据库,会严重造成性能问题的
必须使用缓存,将需要秒杀的商品放入缓存中,并使用锁来处理其并发情况。当接到用户秒杀提交订单的情况下,先将商品数量递减(加锁/解锁)后再进行其他方面的处理,处理失败在将数据递增1(加锁/解锁),否则表示交易成功。
当商品数量递减到0时,表示商品秒杀完毕,拒绝其他用户的请求。

 

2、这个肯定不能直接操作数据库的,会挂的。直接读库写库对数据库压力太大,要用缓存。
把你要卖出的商品比如10个商品放到缓存中;然后在memcache里设置一个计数器来记录请求数,这个请求书你可以以你要秒杀卖出的商品数为基数,比如你想卖出10个商品,只允许100个请求进来。那当计数器达到100的时候,后面进来的就显示秒杀结束,这样可以减轻你的服务器的压力。然后根据这100个请求,先付款的先得后付款的提示商品以秒杀完。


3、首先,多用户并发修改同一条记录时,肯定是后提交的用户将覆盖掉前者提交的结果了。

这个直接可以使用加锁机制去解决,乐观锁或者悲观锁。
乐观锁,就是在数据库设计一个版本号的字段,每次修改都使其+1,这样在提交时比对提交前的版本号就知道是不是并发提交了,但是有个缺点就是只能是应用中控制,如果有跨应用修改同一条数据乐观锁就没办法了,这个时候可以考虑悲观锁。
悲观锁,就是直接在数据库层面将数据锁死,类似于oralce中使用select xxxxx from xxxx where xx=xx for update,这样其他线程将无法提交数据。
除了加锁的方式也可以使用接收锁定的方式,思路是在数据库中设计一个状态标识位,用户在对数据进行修改前,将状态标识位标识为正在编辑的状态,这样其他用户要编辑此条记录时系统将发现有其他用户正在编辑,则拒绝其编辑的请求,类似于你在操作系统中某文件正在执行,然后你要修改该文件时,系统会提醒你该文件不可编辑或删除。

 

4、不建议在数据库层面加锁,建议通过服务端的内存锁(锁主键)。当某个用户要修改某个id的数据时,把要修改的id存入memcache,若其他用户触发修改此id的数据时,读到memcache有这个id的值时,就阻止那个用户修改。


5、实际应用中,并不是让mysql去直面大并发读写,会借助“外力”,比如缓存、利用主从库实现读写分离、分表、使用队列写入等方法来降低并发读写。

时间,纳秒

 

  1.  fmt.Println(time.Now().Unix()) //获取当前秒  
  2.     fmt.Println(time.Now().UnixNano())//获取当前纳秒  
  3.     fmt.Println(time.Now().UnixNano()/1e6)//将纳秒转换为毫秒  
  4.     fmt.Println(time.Now().UnixNano()/1e9)//将纳秒转换为秒  
  5.     c := time.Unix(time.Now().UnixNano()/1e9,0) //将毫秒转换为 time 类型  
  6.     fmt.Println(c.String()) //输出当前英文时间戳格式