hxwallet

command module
v0.0.0-...-d1cf776 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2020 License: LGPL-3.0 Imports: 1 Imported by: 0

README

Hengxin Wallet

恒信简介

Hengxin Network是使用有向无环图实现的分布式账簿系统。在Hengxin Network中,每一次记账行为就是往主网上发送了一次Transaction;主网将为每一个被确认了的Transaction生成一个快照Snapshot。基于Snapshot,各个节点构建了有向无环图,从而实现了高效,低功耗的分布式账簿系统。

与其他区块链项目不同,Hengxin Network从一开始就兼顾了隐私保护。Hengxin Network上的地址都包含三对公私钥:Private View Key / Public View Key, Private Spend Key / Public Spend Key, Private Encrypt Key / Public Encrypt Key。其中, Public View Key, Public Spend Key 以及 Public Encrypt Key构成了Address。只有持有了相应的私钥,才可以分辨出指向该地址的记录:

  1. 若持有某Address,则可以向该Address发送Transaction
  2. 若持有某Address的Private View Key,则可以识别出链上所有指向该Address的UTXO
  3. 若持有某Address的Private View Key 以及 Private Spend Key,则可以消费与该Address相关的UTXO

另外,Hengxin Network中亦引入了Asset概念。实际使用中,可以使用不同的Asset来区分不同的业务方。

链上数据

Hengxin Network中,raw data(用户数据,可以为图片,语音,文字等任何数据)将加密存储于Data Provider中;链上将只存储data hash数据。

数据上链流程:

当用户A (AddrA) 需要向用户B (AddrB), 用户C (Addr C) 生成Transaction,发送数据D时,

  1. 用户A选取加密算法,并随机生成加密密钥,生成加密密钥明文信息K ({"alg":"SM4","key":"xxxx"})
  2. 用户A使用加密算法对明文数据D进行加密,生成数据密文d
  3. 用户A分别使用用户A,B,C的Public Encrypt Key对加密密钥明文信息K进行加密,得到加密密钥密文数据组M ({Addr_A:"K_encrypted_by_A",Addr_B:"K_encrypted_by_B",Addr_C:"K_encrypted_by_C"})
  4. 用户A将数据密文K与加密密钥密文数据组M发送至Data Provider
  5. 用户A生成Memo: {"h":"data_hash","exp":123}
  6. 用户A生成Transaction,指向[Addr_A, Addr_B, Addr_C],完成数据上链

数据流程:

  1. 用户A同步链上Snapshot,得到Transaction,解析出Memo信息
  2. 用户使用data_hash在Data Provider中读到数据密文d 以及 加密密钥密文数据
  3. 用户使用Private Encrypt Key对加密密钥密文数据进行解密,得到加密密钥明文信息K
  4. 用户使用加密密钥明文信息K对数据密文d进行解密,得到明文数据

编译

go install github.com/fox-one/hxwallet

运行

复制config.template.yaml到config.yaml,并适当配置。

Setup DB:

./hxwallet setdb --config config.local.yaml

Create User:

./hxwallet createuser --config config.local.yaml

指令将有如下输出:

user id: 6e5afa15-eb51-3d58-87cb-70dda3231df0
address: HXvrMpQKfFNTnLFSuGULugcsLxxxMWV3qBUnWc2HH81RhAdXKtUNxFnfoN7qXaNqs6LGgx1JL6ry1nd9sKjMDoRFJUjw6QRLJW9D7meogsdYHjWYEZKWVJzbMN6v5wYHxYnraimXzebPt772279NFQe6mWBFWwytTwU9mWxBXBmXV1JywPewNmZzGVYG8vHa8ySrbss9oU6Eso5CpG13rdJeV32
keystore: HXKSxUSRLudmJ4yxr7aC6Nq4Q1RPVim9woufmxyUGmvWcMizDshdvBiqWq54qj6TX7K592xzoy1vyrhRodnqSwGQzH4ZW7gKaF3K4EqNy8UNUo6DfsZoLzRH8jwP9e5K7xT316zX1zNSmmcfCobUJ4CfFR44poW3VwZweUFzwvGiMmkqGhpm5gKyXN53vaqAciVReBFzfEdEyAQiBm5oFbTfB5kBz1bUFJ3BJbfz1Ac6MauFpzotToYJD85fDCtxfEKekj

此账号作为系统账号,将address提供给kernel运行方,运行方将会提供足够的balance以使得系统可以正常运转。

Worker:

./hxwallet worker --debug --config config.local.yaml

Server:

./hxwallet server --debug --config config.local.yaml --port 8082

API

Auth

Hengxin Wallet实现了两种鉴权,

  1. Basic: "Authorization: Basic base64(user_id)"
  2. JWT: "Authorization: Bearer jwt_token"

若配置文件中开启了verify_auth_token, 则必须使用Bearer方式;否则两种皆可。

JWT Token

JWT Header:

{
  "alg": "SM2",
  "typ": "JWT"
}

JWT Payload:

{
  "exp": 1584064554, // 此 token过期时间。Unix Timestamp, 以s为单位
  "iat": 1583978154, // 此 token签发时间,为当前时间即可。Unix Timestamp, 以s为单位
  "iss": "HXy9YaTXHcNcQUXAHS2sBFX2A8yd2zEiePL4Bo5ZmwRGtgXbtnv142aja1Qw4k8m1pWfPaSS4cddx8GjDDdUFV5hgHZT1M5VrRBVsiiGb4iU953i9M9tKhUXWtZFKKZHaNWNnAiMnsVHUifyubY5Mm5PtqwJDNNzU2hYt1Mtqvhcd8ZnJwBeNygvgjicnBajr52ZjKPtd85bezMnVUFCrK4iUDn", // 根用户的 address
  "nc": "__uuid__",
  "sig": "xxxx", // optional. request signature,sm3.hash(METHOD+URI+BODY),注意,URI不包含host,例如sms.hash("GET/snapshots")。若Wallet未开启verify_request_signature,则"sig"可以唯恐
}

生成JWT Token Demo:

func GenerateToken(ekInPEM, address string, expires int64) (string, error) {
  block, _ := pem.Decode([]byte(ekInPEM))
  if block == nil {
    return "", errors.New("failed to decode private key")
  }
  ek, err := sm2.ParsePKCS8PrivateKey(block.Bytes, nil)
  if err != nil {
    return "", err
  }

  header := `{"alg":"SM2","typ":"JWT"}`
  iat := time.Now().Unix()
  payload := fmt.Sprintf(`{"exp":%d,"iat":%d,"iss":"%s"}`, iat+expires, iat, address)

  signedData := strings.Join([]string{
    strings.TrimRight(base64.URLEncoding.EncodeToString([]byte(header)), "="),
    strings.TrimRight(base64.URLEncoding.EncodeToString([]byte(payload)), "="),
  }, ".")

  hasher := sm3.New()
  hasher.Write([]byte(signedData))

  sig, err := ek.Sign(rand.Reader, hasher.Sum(nil), nil)
  if err != nil {
    return "", err
  }

  return strings.Join([]string{
    signedData,
    strings.TrimRight(base64.URLEncoding.EncodeToString([]byte(sig)), "="),
  }, "."), nil
}
User INFO
GET /info

Response:

{
  "code": 0,
  "data": {
    "user_id": "6c54d04f-585a-3c0b-869f-6e63f6912410",
    "created_at": "2020-03-12T02:15:11Z",
    "address": "HX266NGnUZ5HmXzzgBW4C1asDcPGqxteTJZu9EaoFUGLxT6KZEcH96bNE1L4zqy3neBbjdZLScbr1vMM8rB186qrHFERetcwY36ecxW1yToJG3MZ6gw3Pf4oGx7NyELanCzNWbnRL8NmjoRQsuUtPKEgXegoq5oh6yyJ5y9prH43gTj7zjYxgkkcvnGj9osFkKb9vk6q4nDGL5vtpa63kUjV6oSe"
  }
}
Create User
POST /users

Response:

{
  "code": 0,
  "data": {
    "user_id": "6c54d04f-585a-3c0b-869f-6e63f6912410",  // 在访问该用户资源(如snapshot列表)时使用,通过user_id完成用户鉴权
    "created_at": "2020-03-05T22:21:13.321112+08:00",
    "address": "HX266NGnUZ5HmXzzgBW4C1asDcPGqxteTJZu9EaoFUGLxT6KZEcH96bNE1L4zqy3neBbjdZLScbr1vMM8rB186qrHFERetcwY36ecxW1yToJG3MZ6gw3Pf4oGx7NyELanCzNWbnRL8NmjoRQsuUtPKEgXegoq5oh6yyJ5y9prH43gTj7zjYxgkkcvnGj9osFkKb9vk6q4nDGL5vtpa63kUjV6oSe",  // 在生成Transaction时使用
    "keystore": "HXKS7ET32Wgs4JntsxqewKMPQTR19EAxjFtxMhVvUMAP6uu2nxYZUtLgJMmNA6nv1Jr7eVWdEJxSrn1ggjVjEYarPEKpiogyNvHrLKX5sZcnsdeYYgYT2uK9KZJayNHJ3u7bJfSuKB7ZoXcPMst8fuSCMPjmFLq5h3dN8i6pLK2RFVuXbAYiAsDfxrPK7aiXZgq71u8FxEgszVjZn2HBezVFtUmy6VhdRcNSYgnNevmhiKWYG4aVpJtFDQ1xJi6yWnaENh"
  }
}
提交 Transaction
POST /transactions

Param:

{
  "asset": "b9f49cf777dc4d03bc54cd1367eebca319f8603ea1ce18910d09e2c540c630d8",
  "opponent_addresses": ["HX266NGnUZ5HmXzzgBW4C1asDcPGqxteTJZu9EaoFUGLxT6KZEcH96bNE1L4zqy3neBbjdZLScbr1vMM8rB186qrHFERetcwY36ecxW1yToJG3MZ6gw3Pf4oGx7NyELanCzNWbnRL8NmjoRQsuUtPKEgXegoq5oh6yyJ5y9prH43gTj7zjYxgkkcvnGj9osFkKb9vk6q4nDGL5vtpa63kUjV6oSe"], // 指向用户Address,银行Address,同时还可以添加其他监管机构Address,如金融局地址
  "trace_id": "6c54d04f-585a-3c0b-869f-6e63f6912410",   // 任意字符串,最大长度为36。在Hengxin Wallet内唯一,从而保证一个Transaction只能被记录一次。实际使用中,可以根据业务的信息来生成,这样在请求失败之后可以重复提交保证数据上链成功,而又不会发生重复上链的事件
  "memo": "{\"t\":\"reg\",\"d\":\"{}\",\"h\":\"xxxx\"}" // 链上数据,此数据为公开可见数据,不建议添加隐私数据
}

Response:

{
  "code": 0,
  "data": {
    "trace_id": "6c54d04f-585a-3c0b-869f-6e63f6912410",
    "tx_hash": "2d259a9cbe49eccd7878112e291e378fee7c08af0b443c598b1fbc091d7345fc"
  }
}
Inner Transfer
POST /transfer

Param:

{
  "asset": "b9f49cf777dc4d03bc54cd1367eebca319f8603ea1ce18910d09e2c540c630d8",
  "opponent_id": "c95a14b8-14fe-3228-aa2b-a28c88bd1591", // transaction接收方user_id
  "trace_id": "6c54d04f-585a-3c0b-869f-6e63f6912410",   // 任意字符串,最大长度为36。在Hengxin Wallet内唯一,从而保证一个Transaction只能被记录一次。实际使用中,可以根据业务的信息来生成,这样在请求失败之后可以重复提交保证数据上链成功,而又不会发生重复上链的事件
  "memo": "{}"
}

Response:

{
  "code": 0,
  "data": {
    "trace_id": "6c54d04f-585a-3c0b-869f-6e63f6912410",
    "tx_hash": "2d259a9cbe49eccd7878112e291e378fee7c08af0b443c598b1fbc091d7345fc"
  }
}
Read Snapshots
读取 记账记录列表
GET /snapshots

Param:

asset = b9f49cf777dc4d03bc54cd1367eebca319f8603ea1ce18910d09e2c540c630d8 # 可选,若为空则查询所有
from = 1  # 上一条snapshot深度。ASC时,查询height > from的数据; DESC时查询height < from的数据
limit = 1 # 返回数据条目。最大 500
order = ASC / DESC

Response:

{
  "code": 0,
  "data": [
    {
      "created_at": "2020-03-05T13:17:37Z",
      "asset": "b9f49cf777dc4d03bc54cd1367eebca319f8603ea1ce18910d09e2c540c630d8",
      "user_id": "c852a70d-86ca-3832-b7ab-bbfdf68bc39b",
      "opponent_id": "c95a14b8-14fe-3228-aa2b-a28c88bd1591",
      "amount": "0.00000001", // 正数时为用户接收到transaction;负数时为用户发起的transaction
      "trace_id": "6c54d04f-585a-3c0b-869f-6e63f6912410",    // uuid, 在Hengxin Wallet内唯一
      "memo": "{}",
      "height": 100 // Hengxin Wallet中的snapshot深度, 下次查询时
    }
  ]
}

Documentation

Overview

Copyright © 2020 NAME HERE <EMAIL ADDRESS>

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Directories

Path Synopsis
handler
api
store

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL