区块链学习

一、go语言基础(1)一个包怎么调用另一包的函数,go语言中公有性和私有性怎么表达?函数大写表示公有,小写表示私有(2)简单的介绍一下闭包使用场景,优缺点?首先闭包的特点是当闭包函数引用外部变量的时候,会把这个变量放在堆中,所以在内部函数引用外部函数的变量时,值不会被释放packagemainimport"fmt"funcexternalFunc(countint)func()int{returnfunc()int{count++returncount}}funcmain(){//这时候的external是个函数,externalFunc函数返回了个匿名函数external:=externalFunc(1)//这时候的count==1fmt.Println(external())//输出2fmt.Println(external())//输出3fmt.Println(external())//输出4}用法1.函数计数器//函数计数器funccounter(ffunc())func()int{n:=0returnfunc()int{f()n+=1returnn}}//测试的调用函数funcfoo(){fmt.Println("callfoo")}funcmain(){cnt:=counter(foo)cnt()cnt()cnt()fmt.Println(cnt())}/*输出结果:callfoocallfoocallfoocallfoo4*/2)装饰器和中间件,即函数作为参数传递funcwrapping(ffunc()string){fmt.Println("domywork...")fmt.Println("wrappingfunction:",f())fmt.Println("myworkfinished!")}funcsayHello()string{return"Hello!"}funcsayByeBye()string{return"ByeBye!"}funcmain(){wrapping(sayHello)wrapping(sayByeBye)}/*输出:domywork...wrappingfunction:Hello!myworkfinished!domywork...wrappingfunction:ByeBye!myworkfinished!*/(3)map和arraymake的使用区别?go语言中new和make是内置函数,主要用来创建分配类型内存。new(T)创建一个没有任何数据的类型为T的实例,并返回该实例的指针;make(T,args)只能创建slice,map,channel,并返回一个有初始值args(非零)的T类型的实例,非指针。二者都是内存的分配(堆上),但是make只用于slice、map、channel的初始化,而new用于类型的内存分配,并且内存内置为0.make返回的还是这三个引用类型本身;而new返回的是指向类型的指针。slice和array接近,不过更加的灵活,可以在新的元素加入的时候增加长度。slice总是指向底层的一个array。slice是一个指向array的指针,这是其与array不同的地方;slice是引用类型,这意味着当赋值某个slice到另外一个变量,两个引用会指向同一个array。例如,如果一个函数需要一个slice参数,在其内对slice元素的修改也会体现在函数调用者中,这和传递底层的array指针类似。append:向slice追加零值或者其他的x值,并且返回追加后的新的slice。如果原来的slice没有足够的容量,那么append会分配一个足够大的,新的slice来存放原来的slice和后面追加的值。因此返回的slice可能和原来的不是指向同一个arraySlice所允许申请的最大容量大小,与当前值类型和当前平台位数有直接关系slice扩容机制1.如果切片的容量小于1024个元素,那么扩容的时候slice的cap就翻番,乘以2;一旦元素个数超过1024个元素,增长因子就变成1.25,即每次增加原来容量的四分之一。2.如果扩容之后,还没有触及原数组的容量,那么,切片中的指针指向的位置,就还是原数组,如果扩容之后,超过了原数组的容量,那么,Go就会开辟一块新的内存,把原来的值拷贝过来,这种情况丝毫不会影响到原数组。make创建make([]T,length,capacity)slice1:=make([]T,length)length表示slice中已经使用的数据长度capacity表示slice中指针执行的数组容量,如果缺省capacity和length大小相等(4)defer的工作模式go的defer语句是用来延迟执行函数的,而且延迟发生在调用函数return之后,同时defer的执行顺序和栈类似,先进后出(5)匿名函数的使用(难点)常用的感觉就是闭包和gofunc协程了,再说吧。。。。。二、面向对象和并发(1)go语言如何表现继承go中没有extends关键字,所以没有原生级别的继承。go本质上是使用interface实现的,是使用组合来实现继承,用组合来代替继承。在go的结构体struct,通过匿名成员的方式实现继承,比如,Student继承了MentypeMenstruct{namestringageint}typeStudentstruct{Menscoreint}对于接口interface,通过直接引入另一接口的方式实现继承,比如,ReadWriter继承了Reader和WritertypeReaderinterface{}typeWriterinterface{}typeReadWriterinterface{ReaderWriter}(2)接口的优点,使用场景。实现代码解耦(3)并发通信采用什么消息机制。goroutine+channel数据共享

2021-3-1 746 0
2021-2-17 696 0
2021-2-2 650 0
区块链学习

一、共识相关1、POW共识工作量证明,按劳分配,算力决定一切,谁的算力多,谁记账的概率就越大。具体:找到一个hash值SHA256(SHA256(Block_Header)),使得新区块头的哈希值小于某一个指定的值,即区块头中的“难度目标”。找到之后,会全网进行广播打包的区块进行验证,验证通过,该区块会被接受,从而记录到账本中。2、POS共识股权证明,根据用户持有货币的多少和时间(币龄),发放利息的制度。纯POS机制的加密货币,只能通过IPO的方式发行,这就导致“少数人”获得大量成本极低的加密货币。信用基础并不牢固。出块方式是通过随机数。3、DPOS权益持有者选举任何数量的见证人来生成区块,类似人民代表大会制度。即将POS中多有可记账改为只有选举出的见证者才可以记账。优点是交易确认时间短。二、HyperLedgerFabric共识算法1、solo模式单一order节点出块2、kafka模式3、拜占庭容错三、Hyperledger工作流程Fabric基本的流程包括四个阶段,分别是模拟(simulate)、排序(order)、验证(validata)、提交(commit)模拟如其名字所说的一样,这一阶段只是模拟进行交易,并不真正更新ledger。client发起交易请求,请求被发送至endorsers(endorsementpeer,这些peer是根据endorsementpolicy选出来的),endorsers根据当前本地的ledger状态并行模拟进行这些交易,虽然不改变ledger状态,但是会产生一个readset和一个writeset记录这个交易的影响,模拟完成后,endorser对readset和writeset进行签名并将其一起返回给client。如果client收到的readset和writeset是一致的(可能存在恶意endorser或者智能合约存在不确定的算法导致出现不一致),那么client就会生成一个真正的交易请求,包含readset、writeset和对应的签名,并将这个请求发送给orderingservice。排序orderingservice对来自client的交易进行排序,需要注意的是这里并不检查交易的内容,默认按照交易到达的顺序进行排序(这种简单的排序可能导致大量的交易冲突,降低性能,如果按某一特定的顺序排序可以极大的较少交易冲突,提高吞吐量,这也是这篇论文提出的最重要的工作,这里就不细说)。orderingservice将交易排序后打包成block,发送给网络中的peers,这里不保证所有的peer同时收到这个block,但保证收到的block的顺序是一致的(使用gossip协议)。验证当peer收到block后,就开始验证阶段。验证阶段主要包括两个检查:EndorsementPolicy检查检查交易是否满足endorsementpolicy以及是否包含有效的签名,否则说明交易可能被client或者恶意peer篡改过,直接丢弃。交易冲突检查检查交易之间是否存在冲突,也就是是否读脏数据的问题(某个交易在读取ledger之前,ledger被前一个交易改变了),如果存在就丢弃该交易。两次检查都通过的话就可以进入commit阶段了。提交peer将block添加到链上,注意这里是所有的交易(有效的和无效的)都加进来了。然后根据有效的交易改变当前的ledger状态。参考链接https://blog.csdn.net/yijiull/article/details/94966044

2021-1-28 927 0
编程语言

本文代码托管于githubcmake_democmake中一些预定义变量PROJECT_SOURCE_DIR工程的根目录PROJECT_BINARY_DIR运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/buildCMAKE_INCLUDE_PATH环境变量,非cmake变量CMAKE_LIBRARY_PATH环境变量CMAKE_CURRENT_SOURCE_DIR当前处理的CMakeLists.txt所在的路径CMAKE_CURRENT_BINARY_DIRtarget编译目录使用ADD_SURDIRECTORY(srcbin)可以更改此变量的值SET(EXECUTABLE_OUTPUT_PATH<新路径>)并不会对此变量有影响,只是改变了最终目标文件的存储路径CMAKE_CURRENT_LIST_FILE输出调用这个变量的CMakeLists.txt的完整路径CMAKE_CURRENT_LIST_LINE输出这个变量所在的行CMAKE_MODULE_PATH定义自己的cmake模块所在的路径SET(CMAKE_MODULE_PATH${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置LIBRARY_OUTPUT_PATH重新定义目标链接库文件的存放位置PROJECT_NAME返回通过PROJECT指令定义的项目名称CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS用来控制IFELSE语句的书写方式系统信息CMAKE_MAJOR_VERSIONcmake主版本号,如2.8.6中的2CMAKE_MINOR_VERSIONcmake次版本号,如2.8.6中的8CMAKE_PATCH_VERSIONcmake补丁等级,如2.8.6中的6CMAKE_SYSTEM系统名称,例如Linux-2.6.22CAMKE_SYSTEM_NAME不包含版本的系统名,如LinuxCMAKE_SYSTEM_VERSION系统版本,如2.6.22CMAKE_SYSTEM_PROCESSOR处理器名称,如i686UNIX在所有的类UNIX平台为TRUE,包括OSX和cygwinWIN32在所有的win32平台为TRUE,包括cygwin开关选项BUILD_SHARED_LIBS控制默认的库编译方式。如果未进行设置,使用ADD_LIBRARY时又没有指定库类型,默认编译生成的库都是静态库(可在t3中稍加修改进行验证)CMAKE_C_FLAGS设置C编译选项CMAKE_CXX_FLAGS设置C++编译选项cmake常用命令基本语法规则:cmake变量使用${}方式取值,但是在IF控制语句中是直接使用变量名环境变量使用$ENV{}方式取值,使用SET(ENV{VAR}VALUE)赋值指令(参数1参数2…)参数使用括弧括起,参数之间使用空格或分号分开。以ADD_EXECUTABLE指令为例:ADD_EXECUTABLE(hellomain.cfunc.c)或者ADD_EXECUTABLE(hellomain.c;func.c)指令是大小写无关的,参数和变量是大小写相关的。推荐你全部使用大写指令。部分常用命令列表:PROJECTPROJECT(projectname[CXX][C][Java])指定工程名称,并可指定工程支持的语言。支持语言列表可忽略,默认支持所有语言SETSET(VAR[VALUE][CACHETYPEDOCSTRING[FORCE]])定义变量(可以定义多个VALUE,如SET(SRC_LISTmain.cutil.creactor.c))MESSAGEMESSAGE([SEND_ERROR|STATUS|FATAL_ERROR]“messagetodisplay”…)向终端输出用户定义的信息或变量的值SEND_ERROR,产生错误,生成过程被跳过STATUS,输出前缀为—的信息FATAL_ERROR,立即终止所有cmake过程ADD_EXECUTABLEADD_EXECUTABLE(bin_file_name${SRC_LIST})生成可执行文件ADD_LIBRARYADD_LIBRARY(libname[SHARED|STATIC|MODULE][EXCLUDE_FROM_ALL]SRC_LIST)生成动态库或静态库SHARED动态库STATIC静态库MODULE在使用dyld的系统有效,若不支持dyld,等同于SHAREDEXCLUDE_FROM_ALL表示该库不会被默认构建SET_TARGET_PROPERTIES设置输出的名称,设置动态库的版本和API版本CMAKE_MINIMUM_REQUIREDCMAKE_MINIMUM_REQUIRED(VERSIONversion_number[FATAL_ERROR])声明CMake的版本要求ADD_SUBDIRECTORYADD_SUBDIRECTORY(src_dir[binary_dir][EXCLUDE_FROM_ALL])向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置EXCLUDE_FROM_ALL含义:将这个目录从编译过程中排除SUBDIRSdeprecated,不再推荐使用(hellosample)相当于分别写ADD_SUBDIRECTORY(hello),ADD_SUBDIRECTORY(sample)INCLUDE_DIRECTORIESINCLUDE_DIRECTORIES([AFTER|BEFORE][SYSTEM]dir1dir2…)向工程添加多个特定的头文件搜索路径,路径之间用空格分隔,如果路径包含空格,可以使用双引号将它括起来,默认的行为为追加到当前头文件搜索路径的后面。有如下两种方式可以控制搜索路径添加的位置:CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过SET这个cmake变量为on,可以将添加的头文件搜索路径放在已有路径的前面通过AFTER或BEFORE参数,也可以控制是追加还是置前LINK_DIRECTORIESLINK_DIRECTORIES(dir1dir2…)添加非标准的共享库搜索路径TARGET_LINK_LIBRARIESTARGET_LINK_LIBRARIES(targetlib1lib2…)为target添加需要链接的共享库ADD_DEFINITIONS向C/C++编译器添加-D定义ADD_DEFINITIONS(-DENABLE_DEBUG-DABC),参数之间用空格分隔ADD_DEPENDENCIESADD_DEPENDENCIES(target-namedepend-target1depend-target2…)定义target依赖的其他target,确保target在构建之前,其依赖的target已经构建完毕AUX_SOURCE_DIRECTORYAUX_SOURCE_DIRECTORY(dirVAR)发现一个目录下所有的源代码文件并将列表存储在一个变量中把当前目录下的所有源码文件名赋给变量DIR_HELLO_SRCSEXEC_PROGRAMEXEC_PROGRAM(Executable[dirwheretorun][ARGS<args>][OUTPUT_VARIABLE<var>][RETURN_VALUE<value>])用于在指定目录运行某个程序(默认为当前CMakeLists.txt所在目录),通过ARGS添加参数,通过OUTPUT_VARIABLE和RETURN_VALUE获取输出和返回值,如下示例#在src中运行ls命令,在src/CMakeLists.txt添加EXEC_PROGRAM(lsARGS"*.c"OUTPUT_VARIABLELS_OUTPUTRETURN_VALUELS_RVALUE)IF(notLS_RVALUE)MESSAGE(STATUS"lsresult:"${LS_OUTPUT})#缩进仅为美观,语法无要求ENDIF(notLS_RVALUE)INCLUDEINCLUDE(file[OPTIONAL])用来载入CMakeLists.txt文件INCLUDE(module[OPTIONAL])用来载入预定义的cmake模块OPTIONAL参数的左右是文件不存在也不会产生错误可以载入一个文件,也可以载入预定义模块(模块会在CMAKE_MODULE_PATH指定的路径进行搜索)载入的内容将在处理到INCLUDE语句时直接执行FIND_FIND_FILE(<VAR>namepath1path2…)VAR变量代表找到的文件全路径,包含文件名FIND_LIBRARY(<VAR>namepath1path2…)VAR变量代表找到的库全路径,包含库文件名FIND_LIBRARY(libXX11/usr/lib)IF(NOTlibx)MESSAGE(FATAL_ERROR"libXnotfound")ENDIF(NOTlibX)FIND_PATH(<VAR>namepath1path2…)VAR变量代表包含这个文件的路径FIND_PROGRAM(<VAR>namepath1path2…)VAR变量代表包含这个程序的全路径FIND_PACKAGE(<name>[major.minor][QUIET][NO_MODULE][[REQUIRED|COMPONENTS][componets…]])用来调用预定义在CMAKE_MODULE_PATH下的Find<name>.cmake模块,你也可以自己定义Find<name>模块,通过SET(CMAKE_MODULE_PATHdir)将其放入工程的某个目录供工程使用IF语法:IF(expression)COMMAND1(ARGS...)COMMAND2(ARGS...)...ELSE(expression)COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDIF(expression)#一定要有ENDIF与IF对应IF(expression),expression不为:空,0,N,NO,OFF,FALSE,NOTFOUND或<var>_NOTFOUND,为真IF(notexp),与上面相反IF(var1ANDvar2)IF(var1ORvar2)IF(COMMANDcmd)如果cmd确实是命令并可调用,为真IF(EXISTSdir)IF(EXISTSfile)如果目录或文件存在,为真IF(file1IS_NEWER_THANfile2),当file1比file2新,或file1/file2中有一个不存在时为真,文件名需使用全路径IF(IS_DIRECTORYdir)当dir是目录时,为真IF(DEFINEDvar)如果变量被定义,为真IF(varMATCHESregex)此处var可以用var名,也可以用${var}IF(stringMATCHESregex)当给定的变量或者字符串能够匹配正则表达式regex时为真。比如:IF("hello"MATCHES"ell")MESSAGE("true")ENDIF("hello"MATCHES"ell")数字比较表达式IF(variableLESSnumber)IF(stringLESSnumber)IF(variableGREATERnumber)IF(stringGREATERnumber)IF(variableEQUALnumber)IF(stringEQUALnumber)按照字母表顺序进行比较IF(variableSTRLESSstring)IF(stringSTRLESSstring)IF(variableSTRGREATERstring)IF(stringSTRGREATERstring)IF(variableSTREQUALstring)IF(stringSTREQUALstring)一个小例子,用来判断平台差异:IF(WIN32)MESSAGE(STATUS“Thisiswindows.”)ELSE(WIN32)MESSAGE(STATUS“Thisisnotwindows”)ENDIF(WIN32)上述代码用来控制在不同的平台进行不同的控制,但是,阅读起来却并不是那么舒服,ELSE(WIN32)之类的语句很容易引起歧义。可以SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTSON)这时候就可以写成:IF(WIN32)ELSE()ENDIF()配合ELSEIF使用,可能的写法是这样:IF(WIN32)#dosomethingrelatedtoWIN32ELSEIF(UNIX)#dosomethingrelatedtoUNIXELSEIF(APPLE)#dosomethingrelatedtoAPPLEENDIF(WIN32)WHILE语法:WHILE(condition)COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDWHILE(condition)其真假判断条件可以参考IF指令FOREACHFOREACH指令的使用方法有三种形式:列表语法:FOREACH(loop_vararg1arg2...)COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDFOREACH(loop_var)示例:AUX_SOURCE_DIRECTORY(.SRC_LIST)FOREACH(F${SRC_LIST})MESSAGE(${F})ENDFOREACH(F)范围语法:FOREACH(loop_varRANGEtotal)COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDFOREACH(loop_var)示例:从0到total以1为步进FOREACH(VARRANGE10)MESSAGE(${VAR})ENDFOREACH(VAR)输出:012345678910范围和步进语法:FOREACH(loop_varRANGEstartstop[step])COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDFOREACH(loop_var)从start开始到stop结束,以step为步进,注意:直到遇到ENDFOREACH指令,整个语句块才会得到真正的执行。FOREACH(ARANGE5153)MESSAGE(${A})ENDFOREACH(A)输出:581114cmake中如何生成动态库和静态库参考ADD_LIBRARY和SET_TARGET_PROPERTIES用法t3示例cmake中如何使用动态库和静态库(查找库的路径)参考INCLUDE_DIRECTORIES,LINK_DIRECTORIES,TARGET_LINK_LIBRARIES用法t4示例使用动态库或静态库t5示例如何使用cmake预定义的cmake模块(以FindCURL.cmake为例演示)t6示例如何使用自定义的cmake模块(编写了自定义的FindHELLO.cmake)注意读t5和t6的CMakeLists.txt和FindHELLO.cmake中的注释部分cmake中如何指定生成文件的输出路径如上ADD_SUBDIRECTORY的时候指定目标二进制文件输出路径(推荐使用下面这种)使用SET命令重新定义EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH变量来指定最终的二进制文件的位置SET(EXECUTABLE_OUTPUT_PATH${PROJECT_BINARY_DIR}/bin)SET(LIBRARY_OUTPUT_PATH${PROJECT_BINARY_DIR}/lib)上面的两条命令通常紧跟ADD_EXECUTABLE和ADD_LIBRARY,与其写在同一个CMakeLists.txt即可cmake中如何增加编译选项使用变量CMAKE_C_FLAGS添加C编译选项使用变量CMAKE_CXX_FLAGS添加C++编译选项使用ADD_DEFINITION添加cmake中如何增加头文件路径参考INCLUDE_DIRECTORIES命令用法cmake中如何在屏幕上打印信息参考MESSAGE用法cmake中如何给变量赋值参考SET和AUX_SOURCE_DIRECTORY用法建议:在Project根目录先建立build,然后在build文件夹内运行cmake..,这样就不会污染源代码,如果不想要这些自动生成的文件了,只要简单的删除build文件夹就可以转载于https://blog.csdn.net/wzzfeitian/article/details/40963457/

2020-8-9 1475 0