EOS区块链帐户名称始未

引子

从上一节中,我们知道在EOS系统中帐户必需遵循以两个准则

  • 必须短于13个字符
  • 仅能包含以下字符:.12345abcdefghijklmnopqrstuvwxyz
    EOS为什么要这样做呢,这样做有什么好处,在EOS源码中又是如何实现的,下面我们从EOS源码中一步步分析,并解答这些疑问。

帐户别名

??在EOS源码中,帐户的类型是account_name,但account_name在C++代码中又是什么类型呢,追踪代码发现,EOS好多类型都用了别名机制,在源码文件types.hpp中的133行,其代码所示

  using action_name      = name; //合约操作名称
  using scope_name       = name; //作用范围名称
  using account_name     = name; //帐户名称
  using permission_name  = name; //权限名称
  using table_name       = name; //数据库表名称

??这些名称都指向同一个name,也就是说帐户等其它名称限制都由name类来完成的,下面我们看一下name类的实现

struct name {
     uint64_t value = 0;
     bool empty()const { return 0 == value; }
     bool good()const { return !empty();   }

     name( const char* str )   { set(str);           }
     name( const string& str ) { set( str.c_str() ); }
     void set( const char* str );

     template<typename T>
     name( T v ):value(v){}
     name(){}

     explicit operator string()const;

     string to_string() const { return string(*this); }

     name& operator=( uint64_t v ) {
        value = v;
        return *this;
    }

     name& operator=( const string& n ) {
        value = name(n).value;
        return *this;
    }
     name& operator=( const char* n ) {
        value = name(n).value;
        return *this;
    }

     friend std::ostream& operator << ( std::ostream& out, const name& n ) {
        return out << string(n);
    }

     friend bool operator < ( const name& a, const name& b ) { return a.value < b.value; }
     friend bool operator <= ( const name& a, const name& b ) { return a.value <= b.value; }
     friend bool operator > ( const name& a, const name& b ) { return a.value > b.value; }
     friend bool operator >=( const name& a, const name& b ) { return a.value >= b.value; }
     friend bool operator == ( const name& a, const name& b ) { return a.value == b.value; }

     friend bool operator == ( const name& a, uint64_t b ) { return a.value == b; }
     friend bool operator != ( const name& a, uint64_t b ) { return a.value != b; }

     friend bool operator != ( const name& a, const name& b ) { return a.value != b.value; }

     operator bool()const           { return value; }
     operator uint64_t()const       { return value; }
     operator unsigned __int128()const       { return value; }
  };

??从name类中只有一个属性value且类型为uint64_t,即无符号64位整型,这是如何存储13位字符的呢?它们之间是如何转换的?等一系列疑问又产生了。

??在name类重载了所有比较运算符用于名称之间的比较,还写了赋值构造和拷贝构造函数用于name类型的构造与赋值。比较重要的函数是set函数和to_string函数。这两个函数应该是实现了字符到整型及整型到字符串的转化。

设置帐户名称set

void name::set( const char* str ) {
     const auto len = strnlen(str, 14);
     EOS_ASSERT(len <= 13, name_type_exception, "Name is longer than 13 characters (${name}) ", ("name", string(str)));
     value = string_to_name(str);
     EOS_ASSERT(to_string() == string(str), name_type_exception,
                "Name not properly normalized (name: ${name}, normalized: ${normalized}) ",
                ("name", string(str))("normalized", to_string()));
  }

??从代码中可以看帐户的名称长度必须最大长度为13位,大于13位会导致代码断言错误并向系统报告名称超过13个字符的异常。然后调用了函数string_to_name将字符转化为整型,其函数string_to_name如下所示

static constexpr uint64_t string_to_name( const char* str )
  {
     uint64_t name = 0;
     int i = 0;
     for ( ; str[i] && i < 12; ++i) {
         // NOTE: char_to_symbol() returns char type, and without this explicit
         // expansion to uint64 type, the compilation fails at the point of usage
         // of string_to_name(), where the usage requires constant (compile time) expression.
          name |= (char_to_symbol(str[i]) & 0x1f) << (64 - 5 * (i + 1));
      }

     // The for-loop encoded up to 60 high bits into uint64 ‘name‘ variable,
     // if (strlen(str) > 12) then encode str[12] into the low (remaining)
     // 4 bits of ‘name‘
     if (i == 12)
         name |= char_to_symbol(str[12]) & 0x0F;
     return name;
  }
static constexpr uint64_t char_to_symbol( char c ) {
     if( c >= ‘a‘ && c <= ‘z‘ )
        return (c - ‘a‘) + 6;
     if( c >= ‘1‘ && c <= ‘5‘ )
        return (c - ‘1‘) + 1;
     return 0;
  }

??从代码中可以看出char_to_symbol是将一个字符转换为一个64位的无符号整型,在此判断判断了字符必须为a-z和1-5的字符。并将1-5的字符与数值1-5所对应,而字符a-z字符与数值6-31,对于字符.则对应数值为0.从而将所有帐户合法字符都转化为一个数值。 在string_to_name函数中,采用循环遍历帐户中的所有字符,并调用char_to_symbol函数将帐户中的字符转化所对应的数值,然后只取低5位,左移64- 5 * (i + 1)位,并与name做|操作。最后将所有字符所对应的数值都存储到name类型中。从中可以计算一下帐户总共有32个字符,所对应的数值为0到31,在计算机中采用二进制表示数据,0到31只需要5位就可以存储。一个64位的无符号整型最多可以存储64/5=12,余4位,也就是说最多13个字符且不能以字符z结尾,否则可能会出现问题。当不够13字符时则以字符.补充。

将name转化可见帐户

name::operator string()const {
    static const char* charmap = ".12345abcdefghijklmnopqrstuvwxyz";

     string str(13,‘.‘);

     uint64_t tmp = value;
     for( uint32_t i = 0; i <= 12; ++i ) {
        char c = charmap[tmp & (i == 0 ? 0x0f : 0x1f)];
        str[12-i] = c;
        tmp >>= (i == 0 ? 4 : 5);
    }

     boost::algorithm::trim_right_if( str, []( char c ){ return c == ‘.‘; } );
     return str;
  }

??将name变量转化为字符串,首先将合法字符按其所对应的数值大小排列并赋值给charmap变量,并作为查找表,然后在name变量的属性value中依次取5位(第一次取4位),并按其值在查找表中找出对应的字符,从而还原出对应可见帐户名称,在帐户规则中小于13位字符时高位用字符.来补充,所以帐户最高位不能是字符.,将补充的字符.移除,从而完成帐户还原。

总结

??综上所述,这就是EOS帐户名称有所限制的原因,它需要将13个字符装入一个64位的无符号整型,且能将整型转化为所对应的字符帐户的过程。

优点:

1、减少内存使用,帐户13个字符存储需要14个字节,而采用name变量存储只需要8个字节。

2、程序运行速度快,在做帐户查找与比较时,整型比较的效率会大大高于字符串比较。

缺点:

1、减少了帐户名称取名的最大范围,比较不能有特殊字符和67890等字符。

2、对帐户名称的长度有所限制。

链接

星河公链
了解最新更多区块链相关文章
敬请关注星链微信公众号,星链与你共成长

原文地址:https://blog.51cto.com/14267585/2436016

时间: 2024-11-06 11:32:57

EOS区块链帐户名称始未的相关文章

EOS区块链游戏系统定制开发

EOS区块链游戏系统定制开发 找131.2935.5821 微/电 EOS生态app系统开发,EOS区块链技术系统开发,EOS生态游戏app开发 自区块链成为热潮之后,很多公司都义无反顾地扑向了这项新技术,这其中,一部分是随时都会被风吹跑的投机派,而另一派则是实实在在想用区块链这项技术干实事的人. 2018年是区块链应用落地的元年,那么今年区块链在全球迅速升温,各个国家相继出台区块链数字货币的相关政策,甚至已经用于银行的贷款或者转账等等.同时在这个迅速发展的领域也迎来了新的突破--EOS. EO

EOS区块链开发IDE推荐使用Visual Studio Code和CLion

每一个开发人员都需要一个良好的IDE,EOS开发也是一样,为项目开发过程构建一个良好的IDE环境是第一步.这就是为什么我们要写这个如何使用VS Code或者CLion进行EOS开发的快速教程的原因. 我们还为VS Code创建了一些脚本,这些脚本将你在终端中使用的一些命令自动化. 设置Visual Studio Code 首先,如果你还没有这些VS Code扩展的话,安装一下.对于EOS Dapp开发,它们将非常有帮助: C/C++ - VS Code的智能感知.调试和代码浏览 CMake -

EOS区块链究竟有几个线程

一 nodeos工作线程 nodeso节点的工作线程包括:一个主线程,一个信号处理线程和两个线程池. 主线程:main函数启动线程,该线程执行完程序初始化工作后,会调用app().io_service.run(), 启动boost::asio::io_service的异步io服务,通过异步io方式完成节点块生产,交易处理等主要业务工作. 信号处理线程:子线程,通过异步io服务,接收系统信号并处理. 线程池,线程池启动的工作线程数可通过启动参数配置. controller线程池: 异步执行块blo

EOS和以太坊那个区块链平台更好?

显然,你已经听说过两个最受欢迎的智能合约区块链,但想知道EOS与以太坊之中哪个更好?或许你想比较一下两种技术?好吧,你来对了地方,因为我要告诉你你需要知道的一切! 在这个EOS vs Ethereum指南中,我将首先解释每个项目的基础知识,然后概述每个区块链的执行情况.这将包括交易时间,交易费用和可扩展性等内容. 之后,我将简要介绍如何在没有第三方的情况下验证交易.这将包括以太坊使用的工作量证明(Proof of Work)与EOS使用的股份授权证明(Delegated Proof of Sta

Node.js区块链开发 随笔

本书主要讲述了区块链的基础一集js开发工程师如何开发区块链,不仅仅是互联网思维,调用api文档进行开发,而是在基础之上进行的拓展式的开发. 本书主要讲述了,加密货币的一些特征,以及node.js的基础,服务启动如何与链进行交互,以及node.js在区块链技术领域的调查描述,并进行了案例示范,其次对源码进行解读.从架构设计的角度,层层剖析区块链的设计原理,深刻解读相关概念和技术.从项目设计的角度谋篇,从项目入口程序出发,介绍了亿书项目的整体结构,分别介绍了P2P网络.加密解密.签名和多重签名.区块

《Nodejs开发加密货币》之二十三:区块链

前言 亿书,是一款加密货币产品,用时髦的话说,更是一款实用的区块链产品.那么,区块链是什么?有那些特点?最近,以太坊硬分叉事件给了我们很多启示,能不能彻底杜绝区块链分叉行为?这一章,我们通过认真阅读和理解亿书相关的代码逻辑,来详细解释和说明这些问题,以便更加深入的了解和学习这项技术. 源码 blocks.js https://github.com/Ebookcoin/ebookcoin/blob/v0.1.3/modules/blocks.js block.js https://github.c

用 Go 构建一个区块链 -- Part 6: 交易(2)

引言 在这个系列文章的一开始,我们就提到了,区块链是一个分布式数据库.不过在之前的文章中,我们选择性地跳过了"分布式"这个部分,而是将注意力都放到了"数据库"部分.到目前为止,我们几乎已经实现了一个区块链数据库的所有元素.今天,我们将会分析之前跳过的一些机制.而在下一篇文章中,我们将会开始讨论区块链的分布式特性. 之前的系列文章: 基本原型 工作量证明 持久化和命令行接口 交易(1) 地址 本文的代码实现变化很大,请点击 这里 查看所有的代码更改. 奖励 在上一篇文

国内知名区块链技术应用研发公司,区块链交易系统开发

[本文由jys-wu编辑/系统开发微信:jys-wu]银行重金投向区块链等科技创新,欲打金融科技翻身仗据上海证券报报道,银行重金投向科技创新,一是加强基础技术研发与平台建设,推进人工智能.区块链等新兴技术落地应用:二是对线下网点进行统一改造,打造数字化银行,降低成本等.一家大行IT部负责人表示,"在金融科技形势倒逼下,银行IT角色已经改变.过去IT部门是配角,现在要起引领作用,IT目标已经上升到战略层面,需要进行顶层设计,全面赋能业务."美国最大医疗保险公司UnitedHealth宣布

在EOSIO平台上开发区块链dapp(一)

在我倾听Bettina Warburg的演讲之后,我对去中心化经济(dApps)的概念着迷.传统的Web应用程序是: 前端→后端→数据库 相比之下,dApp网站是: 前端→智能合约→区块链 例如,当你进入电子银行时,网页将调用后端代码来获取你的个人数据并将其显示在页面上.后端代码在集中式服务器上运行. 与传统方式不同,dApps在去中心化的P2P网络及区块链(Blockchain)上运行后端代码智能合约(smart contract). 为什么区块链如此热? 区块链是支撑数字货币比特币的技术,但