BCSkill (Block chain skill ) 技术社区
社区QQ群:791420381
推荐论坛:https://eosfans.io
Telegram: https://t.me/bcskill

Ubuntu18.04上源码安装Haproxy2.x

准备编译安装HAProxy的基础环境

sudo apt install make gcc build-essential libssl-dev zlib1g-dev libpcre3 libpcre3-dev libsystemd-dev libreadline-dev -y

编译安装lua

lua为HAProxy支持基于其实现功能扩展
注:HAProxy要求的lua最低版本为5.3

sudo wget -P /usr/local/src/ http://www.lua.org/ftp/lua-5.3.5.tar.gz
cd /usr/local/src/
sudo tar xf lua-5.3.5.tar.gz
cd lua-5.3.5/src/
sudo make linux

查看编译后的版本

surou@DESKTOP-CRS8RL6:/usr/local/src/lua-5.3.5/src$ ./lua -v
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio

编译安装HAProxy

安装基础环境

sudo apt install iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server nfs-common lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev  gcc openssh-server iotop unzip libreadline-dev libsystemd-dev

clone haproxy

git clone https://github.com/haproxy/haproxy.git
git checkout v2.3-dev5

编译源代码

make -j `lscpu |awk 'NR==4{print $2}'` ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 USE_LUA=1 LUA_INC=/usr/local/src/lua-5.3.5/src/ LUA_LIB=/usr/local/src/lua-5.3.5/src/ PREFIX=/apps/haproxy && make install PREFIX=./dist/haproxy

编译完,查看当前目录

cd dist/haproxy/sbin

查看版本

./haproxy -v
surou@DESKTOP-CRS8RL6:~/dist/haproxy/sbin$ ./haproxy -v
HA-Proxy version 2.3-dev5-7faeea-1 2020/09/26 - https://haproxy.org/
Status: development branch - not safe for use in production.
Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open
Running on: Linux 4.4.0-18362-Microsoft #1049-Microsoft Thu Aug 14 12:01:00 PST 2020 x86_64

参考

https://www.cnblogs.com/molson/p/13341108.html

Error 3010004: Invalid authority

当设置一个账户的权限为多个账户时

cleos set account permission bcskillsurou active  '{"threshold":1,"keys":[{"key":"EOS5bu13CujrEUdKB57LnvihUAqkdUycwSz2p7vPuac7vNBvfh7M7","weight":1}],"accounts":[{"permission":{"actor":"222222222222","permission":"eosio.code"},"weight":1},{"permission":{"actor":"111111111111","permission":"eosio.code"},"weight":1}],"waits":[{"wat_sec":1,"weight":1}]}'  owner -p bcskillsurou

报错如下

Error 3010004: Invalid authority
Ensure that your authority JSON is valid follows the following format!
{
  "threshold":      <INTEGER [1-2^32): the threshold that must be met to satisfy this authority>,
  "keys": [         <keys must be alpha-numerically sorted by their string representations and unique>
    ...
    {
      "key":        <STRING: EOS.IO compatible Public Key>,
      "weight":     <INTEGER [1-2^16): a signature from this key contributes this to satisfying the threshold>
    }
    ...
  ],
  "accounts": [     <accounts must be alpha-numerically sorted by their permission (actor, then permission) and unique>
    ...
    {
      "permission": {
        "actor":      <STRING: account name of the delegated signer>,
        "permission": <STRING: permission level on the account that must be satisfied>,
      },
      "weight":     <INTEGER [1-2^16): satisfying the delegation contributes this to satisfying the threshold>
    }
    ...
  ],
  "waits": [        <waits must be sorted by wait_sec, largest first, and be unique>
    ...
    {
      "wait_sec":   <INTEGER [1-2^32): seconds of delay which qualifies as passing this wait>
      "weight":     <INTEGER [1-2^16): satisfying the delay contributes this to satisfying the threshold>
    }
    ...
  ]
}

Error Details:
Authority failed validation! ensure that keys, accounts, and waits are sorted and that the threshold is valid and satisfiable!

解决问题

将添加的accounts按照ascii顺序添加
例如上面的例子,先添加 111111111111 再添加 222222222222

cleos set account permission bcskillsurou active  '{"threshold":1,"keys":[{"key":"EOS5bu13CujrEUdKB57LnvihUAqkdUycwSz2p7vPuac7vNBvfh7M7","weight":1}],"accounts":[{"permission":{"actor":"111111111111","permission":"eosio.code"},"weight":1},{"permission":{"actor":"222222222222","permission":"eosio.code"},"weight":1}],"waits":[{"wat_sec":1,"weight":1}]}'  owner -p bcskillsurou

参考

https://github.com/EOSIO/eos/issues/4433

基于 EOS 公钥加密,私钥解密示例

eos-crypto-java 使用指南

源码:https://github.com/yanjunli/eos-crypto-java

eos-crypto-java 目前可以支持 基于 ECC+AES 的加解密方式。

在本压缩包中,包含基于jdk1.5 打好的jar 包。

要求

jdk 1.5+

基于 EOS 公钥加密,私钥解密示例

        String privateKey =  "5KTZYCDdcfNrmEpcf97SJBCtToZjYHjHm8tqTWvzUbsUJgkxcfk";
        EosPrivateKey eosPrivateKey = new EosPrivateKey(privateKey);
        EosPublicKey  eosPublicKey = eosPrivateKey.getPublicKey();
        // 转换成 EC privatekey
        ECPrivateKey ecPrivateKey = eosPrivateKey.getECPrivateKey();
        ECPublicKey ecPublicKey = eosPublicKey.getECPublicKey();

        byte[] plaindata = "{\"age\": 1,\"12345\":\"24qqwazzxdtttdxkaskjewuizckczxnlsdosasda4!!!@#$$%^&&*(()(^#\"}".getBytes("utf8");

        System.out.println("加密原文:" + new String(plaindata));

        byte[] encryptdata = ECCUtil.publicEncrypt(plaindata,ecPublicKey);

        System.out.println("加密后密文:" + HexUtils.toHex(encryptdata));

        plaindata = ECCUtil.privateDecrypt(encryptdata,ecPrivateKey);

        System.out.println("解密后原文: "+ new String(plaindata));

基于ECC+AES 双向验证 加解密示例

/**
*
* sender  发起方密钥对
*
* EOS8g1u3ktAGHs4QsVp9aeaWNebFLtprQHwpaSjegx6iEuoTNhjXU
* 5KTZYCDdcfNrmEpcf97SJBCtToZjYHjHm8tqTWvzUbsUJgkxcfk
*
* receiver 接收方一密钥对
*
* EOS7ez2gagfoXw9XdW3kRx3EsCoWvupGR6u6ZJhFPEe9Q12V8JgUL
* 5JUrqxYcssR9LLVtWDeQcc9HCX4FEqBG7d9GW6t7mvmB1rUuZr9
*
* receiver 接收方二 密钥对
* EOS5WMHqw6jDDBPBm7JXTHemAwtSo2tp93pRysJMRhiT1zUYb24vL
* 5HrcVeuHHNwHsivrMoJ9XvU6EM7Q2wQ2ECiy8GeoiuamhNiSuZq
*/

// 1.  调用钱包获取 发送方私钥
  String senderPrivateKey =  "5KTZYCDdcfNrmEpcf97SJBCtToZjYHjHm8tqTWvzUbsUJgkxcfk";
  EosPrivateKey senderECPrivateKey = new EosPrivateKey(senderPrivateKey);
//        EosPublicKey senderECPublicKey = new EosPublicKey(senderPublicKey);
        // 2.  根据私钥 生成公钥。 或者直接根据公钥 调用钱包获取私钥。 都可以。
  EosPublicKey senderECPublicKey = senderECPrivateKey.getPublicKey();

  String senderPublicKey = senderECPublicKey.toString();
  /**
   * 调用钱包获取 接收方私钥   获取公私钥方式 根据需求确定。
   *  1. 可以根据公钥,从钱包里获取私钥
   *  2. 也可以直接从钱包里取出私钥,反向生成公钥
   *  
   *  实际业务场景,发起方只会有接收方公钥,并没有接收方私钥. 
   *  此时 可以通过 new EosPublicKey(receiverPublicKey) 方式 生成EosPublicKey 对象。
   */
  String receiverPrivateKey = "5JUrqxYcssR9LLVtWDeQcc9HCX4FEqBG7d9GW6t7mvmB1rUuZr9";
  EosPrivateKey receiverECPrivateKey = new EosPrivateKey(receiverPrivateKey);
  EosPublicKey receiverECPublicKey = receiverECPrivateKey.getPublicKey();
  String receiverPublicKey = receiverECPublicKey.toString();
  //        String receiverPublicKey =  "EOS7ez2gagfoXw9XdW3kRx3EsCoWvupGR6u6ZJhFPEe9Q12V8JgUL";


  /**
   * 使用 发送者方私钥 和接收方公钥,生成 aes key, 对数据进行加密
   * nonce  为初始化向量,可以使用固定值,
   *                      也可以使用随机值,并使用私有协议。根据业务需求选择。
   */
  byte[] nonce = new byte[16];
  MTRandom random=new MTRandom();
  random.nextBytes(nonce);

  // 待加密 数据
  byte[] params = "{\"test1\": 1,\"test2\":\"24qqwazzxdtttdxkaskjewuizckczxnlsdosasda4!!!@#$$%^&&*((){}(^#\"}".getBytes("utf8");

  System.out.println("原始加密数据: " + new String(params,"utf8"));

  byte[] encrypted = new byte[0];
  try {
      encrypted = CryptUtil.encrypt(senderECPrivateKey,receiverECPublicKey,nonce,params);
  } catch (InvalidCipherTextException e) {
      e.printStackTrace();
      System.out.println("  do something!!!!");
  }

  System.out.println("加密后数据: " + new String(encrypted,"utf8"));
  try {
      byte[] plainText = CryptUtil.decrypt(receiverECPrivateKey,senderECPublicKey,nonce,encrypted);
      // 解密后数据
      System.out.println("解密后数据 :  "+new String(plainText, "utf8"));
  } catch (InvalidCipherTextException e) {
      e.printStackTrace();
      System.out.println("  do something!!!!");
  }

基于数字信封的 加解密示例


/**
         *
         * sender
         *
         * EOS8g1u3ktAGHs4QsVp9aeaWNebFLtprQHwpaSjegx6iEuoTNhjXU
         * 5KTZYCDdcfNrmEpcf97SJBCtToZjYHjHm8tqTWvzUbsUJgkxcfk
         *
         * receiver 平台公私钥对
         *
         * EOS7ez2gagfoXw9XdW3kRx3EsCoWvupGR6u6ZJhFPEe9Q12V8JgUL
         * 5JUrqxYcssR9LLVtWDeQcc9HCX4FEqBG7d9GW6t7mvmB1rUuZr9
         *
         * receiver 省侧公私钥对
         * EOS5WMHqw6jDDBPBm7JXTHemAwtSo2tp93pRysJMRhiT1zUYb24vL
         * 5HrcVeuHHNwHsivrMoJ9XvU6EM7Q2wQ2ECiy8GeoiuamhNiSuZq
         */

        // 1.  调用钱包获取 发送方私钥
        String senderPrivateKey =  "5KTZYCDdcfNrmEpcf97SJBCtToZjYHjHm8tqTWvzUbsUJgkxcfk";
        EosPrivateKey senderECPrivateKey = new EosPrivateKey(senderPrivateKey);
//        EosPublicKey senderECPublicKey = new EosPublicKey(senderPublicKey);
        // 2.  根据私钥 生成公钥。 或者直接根据公钥 调用钱包获取私钥。 都可以,看具体业务需求
        EosPublicKey senderECPublicKey = senderECPrivateKey.getPublicKey();

        String senderPublicKey = senderECPublicKey.toString();
        /**
         * 调用钱包获取 接收方私钥   获取公私钥方式 根据业务需求确定。
         *  1. 可以根据公钥,从钱包里获取私钥
         *  2. 也可以直接从钱包里取出私钥,反向生成公钥
         */
        String receiverPrivateKey = "5JUrqxYcssR9LLVtWDeQcc9HCX4FEqBG7d9GW6t7mvmB1rUuZr9";
        EosPrivateKey receiverECPrivateKey = new EosPrivateKey(receiverPrivateKey);

        EosPublicKey receiverECPublicKey = receiverECPrivateKey.getPublicKey();

        /**
         * 生成对称密钥
         */
        byte[] nonce = new byte[16];
        MTRandom random=new MTRandom();
        random.nextBytes(nonce);

        // 待加密 数据
        byte[] params = "{\"age\": 1,\"汉字\":\"为初始化向量,可以使用固定值,\",\"12345\":\"24qqwazzxdtttdxkaskjewuizckczxnlsdosasda4!!!@#$$%^&&*(()(^#\"}".getBytes("utf8");

        System.out.println("加密前原始数据: " + new String(params,"utf8"));

        // 发起方使用对称密钥,对原始数据进行加密
        byte[] encryptedData = null;
        try {
            encryptedData = CryptUtil.aesEncryptWithNOIV(nonce,params);
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
            System.out.println("  do something!!!!");
        }

        System.out.println("加密后数据: " + HexUtils.toHex(encryptedData));


        System.out.println("加密前对称密钥: " + HexUtils.toHex(nonce));

        // 发起方使用 接收方公钥,对对称密钥进行加密
        byte[] encryptedKey = null;
        try {
            encryptedKey = ECCUtil.publicEncrypt(nonce,receiverECPublicKey.getECPublicKey());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("  do something!!!!");
        }

        System.out.println("加密后对称密钥: " + HexUtils.toHex(encryptedKey));

        // 将对称密钥加密后的数据,密文组装后,进行网络传输。
        // 组装 demo
        /**
         *    4 byte                       |      encryptedKey                 |       4 byte              | encryptedData
         *    对称密钥加密后的数据长度      |      ECC 加密后的对称秘钥           |       密文数据长度         | AES 加密后的密文
         */

        ByteBuffer bytebuffer = ByteBuffer.allocate( 4 + encryptedKey.length + 4 +encryptedData.length);
        bytebuffer.putInt(encryptedKey.length);
        bytebuffer.put(encryptedKey);
        bytebuffer.putInt(encryptedData.length);
        bytebuffer.put(encryptedData);

//        String base58encode = Base58.encode(bytebuffer.array());
//        System.out.println("base58 编码后的:   " + base58encode);

        // 进行 16 进制编码
        String hexencode = HexUtils.toHex(bytebuffer.array());

        System.out.println(" 将数字信封和密文组装后的报文 16进制格式:" + hexencode);

        System.out.println("发送方数据加密完成,可以将数据发送出去 ");

        /**
         *****************************************************  以下为接收方 代码  *************************************
         */

//        byte[] base58decode = Base58.decode(hexencode);
        byte[] hexdecode = HexUtils.toBytes(hexencode);
        ByteBuffer receiveBuffer = ByteBuffer.wrap(hexdecode);

        // 获取到对称秘钥长度
        int receivedEncryptedKeyLength = receiveBuffer.getInt();
        // 加密后的对称密钥key
        byte[] receivedEncryptKey = new byte[receivedEncryptedKeyLength];
        receiveBuffer.get(receivedEncryptKey,0,receivedEncryptedKeyLength);

        System.out.println(" 接收到的 加密后的对称密钥 :" + HexUtils.toHex(receivedEncryptKey));
        // 获取到的 密文的长度
        int contextLength = receiveBuffer.getInt();
        // 密文
        byte[] receivedEncryptContext = new byte[contextLength];
        receiveBuffer.get(receivedEncryptContext,0,contextLength);

        System.out.println(" 接收到的 密文:" + HexUtils.toHex(receivedEncryptContext));


        // 使用接收方私钥,解密对称密钥
        byte[] receiveddecryptKey = null;
        try {
            receiveddecryptKey = ECCUtil.privateDecrypt(receivedEncryptKey,receiverECPrivateKey.getECPrivateKey());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("  do something!!!!");
        }

        System.out.println(" 解密后的对称密钥 :" + HexUtils.toHex(receiveddecryptKey));

        // 使用对称密钥,对密文进行解密

        try {
            byte[] plainText = CryptUtil.aesDecryptWithNOIV(receiveddecryptKey,receivedEncryptContext);
            // 解密后数据
            System.out.println("解密后数据 :  "+new String(plainText, "utf8"));
        } catch (InvalidCipherTextException e) {
            e.printStackTrace();
            System.out.println("  do something!!!!");
        }

EOS js name To Uint64 OR Uint64 to name

源代码仓库地址:
https://github.com/bcskill/eosjs-name

演示地址
Try on run-kit https://npm.runkit.com/eosjs-account-name

测试代码
// name To Uint64

const eosjsAccountName = require("eosjs-account-name")
const n = eosjsAccountName.nameToUint64('eosio');
console.log('eosio to uint64: ' + n);
console.log('uint64 to name: ' + eosjsAccountName.uint64ToName(n));

// Uint64 to name

const uint64 = '6138663577826885632';
const name = eosjsAccountName.uint64ToName(uint64);

EOS 编译 llvmWARshim error

编译EOS2.x版本时,由于使用WSL,或者Windows git 操作过,很容易把软连接丢了,所以报错如下

/eos/libraries/chain/webassembly/eos-vm-oc/llvmWARshim.llvmwar:1:1: error: ‘llvmWARshim’ does not name a type
 llvmWARshim.cpp
 ^~~~~~~~~~~
libraries/chain/CMa

手动修复软连接

cd /eos/libraries/chain/webassembly/eos-vm-oc
rm llvmWARshim.llvmwar
ln -s llvmWARshim.cpp llvmWARshim.llvmwar

修复后ll查看如下

llvmWARshim.llvmwar -> llvmWARshim.cpp*