当前位置: 首页 > 编程日记 > 正文

以太坊源码分析之随心笔记

链客,专为开发者而生,有问必答!

此文章来自区块链技术社区,未经允许拒绝转载。

在这里插入图片描述
以太坊索引

table.go 定期随机选取一些节点找他们要他们的节点,放到本地,也就是一个随机找节点的table 里头的bucket 和 nodesByDistance都是为了找节点方便(这里已经有pingpong了)使用的是udp.go

p2p/dial.go目前的理解是table负责用udp发现节点,而dial.go负责发起真正的链接,调用dial和server.go的SetupConn

udp.go 主要是收发消息用的比如ping pong 找节点消息等等,点对点消息

discover/node.go 代表了一个网路节点,其中nodeid是一个公钥的转换

p2p/peer.go 代表一个节点,主要是pingpong消息的转发,以及protocols的转发,这里的msgcode就是protocol的(offset, offset+length) (注意这里NewPeer的驱动的是protocol 对一个模拟的conn写和读,并没有真正的网络conn,为了测试用,newPeer才是真正被用到的,conn是SetupConn创建来的 server.go的conn结构其中transport是rlpx.go newRLPX生成的)

node/node.go

config.go 主要是一些配置其中node里边有网络节点的一些配置,还有一个account(账户)的配置

message.go 定义了p2p交互中的msg和一系列封装 eofSignal 消息字节读取没了给chan中发信号 MsgPipe一个双向交互的消息pipe msgEventer 收发消息时给feed发送一个事件

api.go geth console 到处的js api都在这里

nat目录下的nat.go natpmp.go natupnp.go主要是实现nat,也就是让外网的机器可以访问内网的机器有upnp协议pmp协议还有直接ip出去的 nat.map函数就是把内网的端口映射到外网去

p2p/metrics.go 主要是封装了一层conn 用作仪表,其实就是记录下进出流量的多少

p2p/rlpx.go 是对conn 发送之前加密,和rlp(加解码)和conn作用一样

server.go 表示p2p协议,通过udp协议找到table节点pingpong,然后通过tcp协议真正链接生成peer 其中inboundConn表示链接进来的(本地通过accept的node)而没有这个标记是本地主动dial的节点,tcp和udp都有自己的pingpong,udp的在udp.go tcp的在peer.go

rpc=======================================

subscription.go 维护Notifier主要是Notify函数通过创建codec.CreateNotification并且codec.Write来发消息

rpc整体来说就是通过json等方式调用注册的服务函数,而且通过映射的方式获取函数名等等match到json上

rpc end***************************************************************

node========================================

node.go 代表了一个节点,内含一个p2pserver 和rpcserver 主要的执行是通过Register注册的服务

node end**************************************************************

trie===========================================

node 分为几类 shortnode 主要是一个前缀key+node fullnode是16个字母(key)+一个通用字母 每一个字母对应一个node valnode直接就是叶子节点,还有一类hashnode 是node的hash值,存到db中去了

trie.go 一个树结构有几种节点,其中类型参考node的讲解,其中 hash 这个函数是把节点都存到db里面并且返回(node的hashnode,node的拷贝,err) Commit目前分析就是hash函数的调用过程,主要是把节点存db然后转换成node

hasher.go 用户hash node,并且将hash存在node 的flag里面,或者存到db中去,用的hash算法是keccak256

secure_trie.go 对trie.go中的节点简单的封装和转查

trie就是以key和value的形式构造了一颗用key做索引的树,key被做成了shortnode和fullnode,然后提供了一个hash函数,这个函数递归的hash子节点,最后算出来一个hash根(有一个用途就是blockheader里头的tx hash)

proof.go 提供两个关键函数 prove 通过key生成一条路径的证明,VerifyProof 提供证明和key 验证是否达标 但是具体的验证原理还没有搞的特别明白

tire end************************************************************************

types ============================================

transaction.go 代表了一个tx 内部还有一个msg,这里面有通过price排序的heap 需要注意的是签名中可以获取from地址所以tx的结构中只有个to的字段

receipt.go 代表了tx的执行结果,主要有poststate status 和CumulativeGasUsed(累积使用的gas)一个bloom filter以及logs组成

transaction_signing.go 对tx做签名,从签名中获取到chainId以及sender(from)

block.go 定义一个区块,区块包含几个部分一个是header 一个是uncle headers 一个是tx

types end************************************************************************

genesis.go 主要是生成genesis block 其中SetupGenesisBlock生成了一个genesis block 并且把相关的信息存放在db中去,比如config信息

les ================================================

peer.go 定义了一个peer和peerset,前者主要用于各种收发协议消息,后者是peer的set,用于对peer进行peerSetNotify的注册和反注册

execqueue.go 里面有一个func的queue,在一个单独的go线程执行

protocol.go 定义了 announceData 有点像比特币中的header消息,用于从远方拉block的消息,并且提供了 announceData 的 sign和验证的函数sign和checkSignature

distributor.go 主要是distPeer(其实就是peer)和distReq两个类型的协同工作 distReq代表一个请求,主要是request函数返回了一个func,这个func可以放到queueSend中去而requestDistributor就是loop distReq队列然后对其进行queueSend,而queue就是对外的函数,用于放进队列distReq进而进入loop发送请求,发送完以后通过queue的返回值(一个chan)返回一个peer(dispeer接口对应的对象是peer)

flowcontrol 感觉是通过上次发送的时间和对面的handsake 得到的一些buflimit等信息来决定下次发送需要多久,以让各个节点都有时间处理,减少发送失败的情况(猜的哈)

txrelay.go 一个tx消息的中继器,主要是peer.go distributor.go两个逻辑的结合,选取peer发送distReq进而发送tx

serverPool.go 是一个链接池对应的是p2p的peer,维护了这么一个链接池connect是链接进来的peer调用 registered是完成handshake调用, 其中newQueue代表connect进来的knownQueue表示已经完成registered,其中start函数的两个参数可以看出一个server表示启动p2p开始做dial链接,而topic是一个discorver逻辑发现节点用的对应的是udp发现节点通过tcpserver进行dial连接

retrieve.go 主要是有 distributor.go 用于把消息发送出去(retrieve函数) 然后通过自身提供的函数deliver分发到应答的消息到pee

odr_requests.go 代表了集中request 和他们的接口函数,其中每一种类型的req会使用peer里边的函数发送,另外每一种类型req都有一个validate函数是在retrive.go的deliver函数中使用用于验证消息的合法性

odr.go 主要是Retrieve函数收到一个req(odr_requests.go)封装了一下转发出去,另外封装了一些indexer(chain_indexer.go postprocess.go)这个Retrieve 函数不但把req发出了而且还把结果取回来通过req的StoreResult或者Validate把结果存到db或者自身去了,这里要注意

handler.go 主要是处理消息然后转发给 retrieve.go解析的,同时也响应部分消息,比如要求发送block的消息,直接通过 peer发送出去

fetcher.go 目前理解是一个记录了各个peer有多少个node header然后定期从各个peer上获取东西到本地的一个类

les end********************************************************************************

light================================================

postprocess.go是对chain_indexer.go的一个封装填充了backend NewBloomTrieIndexer NewChtIndexer 两个分别是两个backend

lightchain.go 这个文件中实现了一个链的逻辑 InsertHeaderChain这个函数比较重要就是把参数传进来的一系列的header写到数据库中(先要验证)想法连到主链上,如果连不到就连的侧链上,然后通过chainSideFeed和chainHeadFeed通知外部链接的情况,通过SubscribeChainHeadEvent和SubscribeChainSideEvent,和SubscribeChainEvent来监听

trie.go一个封装了一个trie的结构(odrTrie)),如果发现本地db有这个trie的内容就直接返回,如果没有就循环的通过Retrieve函数从别的地方获取

txpool.go 目前了解有点类似比特币中的mempool,是一个tx的缓存池,加入到池子中有一些简单的验证,比如验证nonce和gas值对不对,然后放到pending的map中,并通过txrelay转发出去,如果有些block被链接到链上了还会标记这些penging的tx已经mined或者block被从链上退回来了,也会放到rollback列表中去,然后告诉txrelay去处理一些发送的pending节点

另外通过SubscribeNewTxsEvent来通知外部有新的tx加入到pool中,它自身又通过SubscribeChainHeadEvent监听了lightchain关于head的事件

light end********************************************************************************

core/state=============================================

这个目录里面就是以太坊api实际作用到磁盘上的东东,stateobject就是以太坊的状态对象,包含了对一个账户余额等的操作以及key-value对的设置以及code的设置这三部分

journal.go算是一个回滚列表,容易拍一个state快照然后回滚,对state数据库的回滚操作

statedb.go 是state_object的集合通过addr 为key的map, 自己也有trie存放的是state_object

state_object.go 维护了一个stateObject对象 主要是getstate setstate 和账户balance维护以及codeshash的维护,内部有一个节点的trie存放的key-value对都是hash,最后这些都不会被放到db中

core/state end***********************************************************************

core/type =============================================

receipt CumulativeGasUsed代表了一个block到这个tx的时候用了多少的gas,而gasused代表这一个tx用了多少的gas, receipt目前我理解的有几个用途,一个是记录了一个PostState字段代表了走到这个tx的时候状态数据库的roothash是什么,更方便确定一个tx的状态确认,另外是Bloom可以快速的查看一个日志是否在这个tx中,并且有logs这个字段,这里还有一个疑问或者注意点,就是虚拟机有些错误有了,但是还是会收录到tx里边所以receipt有个Status来代表vm是否执行成功,其中我目前理解的有些错误如gas用完了之类的,虽然是错误但是这个tx依然反映到了db中去,gas不还了哈哈

(todo vm执行失败,看看vm内部会不会回滚一点db,反正部分失败是在外部是不会回滚db的)

todo vm执行失败,看看vm内部会不会回滚一点db,反正部分失败是在外部是不会回滚db的 ?,在vm/evm.go这个文件的call函数中都有回滚

而且其实ErrInsufficientBalance这个错误(也就是转账以太坊失败的这种错误),是不会写入区块链,而别的错误vm/error.go,虽然状态会被回滚(vm/evm.go这个文件的call函数)但是会写入区块链的,并且返回receipt

core/type end*************************************************************************

core================================================

chain_indexer.go eventLoop等有新的head 出现的时候(目前来看是从headerchain过来的,也就是有head被连到主链时候发送消息过来)收到一个event 然后调整本地有可能是换链最新的head(head的seg) updateLoop 是等待更新消息(eventloop在发现有新的section的时候发送),然后调用processSection 进而调用backend整块的处理section中的head

section的概念有点类似比特币中的难度一段一段的那种

chainDb 存放的是实际的数据

indexDb 存放的是index的数据(index就是section的一些信息,如一个section的头是哪个blockheader)

children 存放的是一些子的chainindexe

backend 后台处理程序接口,主要是reset Process 和commit三个函数,这一套函数处理一个section reset接收section num + 上一个section的head, process循环调用处理本section中的head,commit用于提交一般用于写入数据库

headerchain.go 一个代表header链的结构,其中currentheader 是链头,Canonical这个单词表示是正链,其他的函数都是只存数据库不是主链的意思比如WriteCanonicalHash表示在朱脸上写hash WriteHeadHeaderHash就只是存了一下

state_transition.go 这里有tx执行的过程调用包括虚拟机的执行,尤其是gas使用的一些逻辑,不过这里目前有一个疑问为啥退款是使用min(gas的一半,剩余的gas)也就是有封顶,而且如果达到封顶值以后一些钱就消失了没有给矿主,矿主只拿到了gasused

state_processor.go 目是对block中的tx运行虚拟机生成receipt和state等

blockchain.go 真正的链操作,通过downloader等把块数据传到这里如InsertChain,然后通过验证块(state_processor.go的 Process等)加入区块

block_validator.go 应该是主要验证一些block的body信息

core end********************************************************************************

consensus/ethash========================================

ethash.go 目前看明白的是两个hash cache 一个就叫cache一个叫dataset,这两个包含到了ethash这个结构中,epoch这个是一个区段的意思,一个区段有一个cache和dataset

consensus.go 共识engine,主要是看header uncle等结构以及难度确定和验证用的 VerifySeal表示验证了header的难度其中header的MixDigest是一个另类的头的hash 这个和比特币不一样相当于存了一个hash到header中 verifyHeader检查header的各个字段如果seal参数为true就检查难度是否达标

consensus/ethash end*****************************************************************

eth/downloader=============================================

downloader.go 主要是通过网络下载block和header和receipt三种信息然后通过chain放到链中去

queue.go 一个队列通过retrievexxx和deliverxxx两个类型的函数排队下载最后放结果,deliver函数通过一个haderProcCh把结果高出去

eth/downloader end************************************************************************

consensus/ethash============================================

sealer.go Seal 通过提供这个函数挖矿

consensus/ethash*************************************************************************

miner====================================================

agent.go负责挖hash,然后把成的模块给worker.go

worker.go负责从txpool中生成block,然后形成work给agent算hash 生成block以及验证block验证tx的逻辑都在这里

miner.go是对worker的一个封装

worker 的commitNewWork把区块准备好(验证什么的)但是没有算hash等

agent 的mine实际算hash

Worker wait函数把挖矿好的block插入到放到链中WriteBlockWithState

另外一个区块的目标难度和几个因素有关系一个是和上一个区块的隔离时间,一个是上一个区块有几个uncle,还有一个是上一个区块的难度

miner end**********************************************************************************

vm======================================================

contract.go 抽象了一个智能合约,有caller 有自己的code 有合约带的gas等

contracts.go 定义了一个map代表里系统合约PrecompiledContract

 ecrecover系统合约从输入(输入中包含了sig和hash)中解出来了一个公钥sha256hash系统合约进行了一个sha256的hash计算ripemd160hash系统合约进行一次ripemd160hash的计算dataCopy系统合约直接返回输入数据bigModExp 对一段数据做exp操作具体的看bigint 的exp函数bn256Add 对bn256 做+操作bn256ScalarMul 对bn256做*操作bn256Pairing 对bn256做pairing操作

opcodes.go 所有指令的定义

analysis.go codeBitmap表示一段代码中的数据,生成一个bitmap,如果这个位置为1表示这一个字节是数据否则是代码 destinations是一个code hash到codebitmap的map,has函数看看索引上的指令是不是jmpdest指令

jump_table.go 定义了指令的operation每一个指令对应一个operation结构主要包含 executionFunc执行函数gasFunc gas消耗函数 stackValidationFunc堆栈检查函数 memorySizeFunc内存消耗函数

instructions.go 指令的执行函数都在这里 executionFunc

opAdd opSub opMul opDiv — opSAR 基本运算,把栈顶相关运算数取出来然后将结果放到堆栈去

opSha3 从堆栈中获取内存的地址(offset+size)从内存中取出来数据,然后做keccak256处理,然后把算出来的hash入栈,有一个梗是会把(hash,data)当作preimage写到数据库中

opAddress 获取contract.Address字段

opBalance 把堆栈顶端的地址换成了该地址对应的余额

opOrigin 代表evm执行程序的最开始的caller地址

opCaller 这个合约的calle

opCallValue 堆栈中push contract.value

opCallDataLoad 栈顶拿一个地址(offset)从input中获取一个32位的数,放到栈顶

opCallDataSize 栈顶放一个input的size

opCallDataCopy 把input内的内容copy到内存(栈顶有三个参数内存offset, input offset 和len)

opReturnDataSize 栈顶push interpreter的returnData的size

opReturnDataCopy 把 interpreter的returnData 的部分内容copy到内存(栈顶三个参数 内存offset returndata的offset和size)

opExtCodeSize 栈顶的code地址转换成codesize

opCodeSize 把合约自己的codesize放到栈顶

opCodeCopy 合约自己的code部分内容copy到内存中(内存offset, code offset, size)

opExtCodeCopy 把一段代码的部分copy到内存中(code的地址,内存offset, code offset, size)

opGasprice 获取gas的价格evm的GasPrice参数

opBlockhash 把栈顶的block num转换成block hash

opCoinbase 把coinbase的地址放到栈顶

opMload 栈顶给一个内存地址取出来一个32字节数据放到栈顶

opMstore 存一个地址到内存

opSload 将栈顶的key转换成对应的状态value

opSstore 设置对应的key,value

opJumpi 通过栈顶的跳转目标和条件变量决定是否跳转到pc

opPc 把栈顶放上pc的值

opMsize 栈顶放上内存现在的大小

opGas 把合约当前的gas放到栈顶

opCreate 创建一个合约,参数为给合约的转账,合约地址(内存offset 和size),创建合约后消耗gas并把执行结果也就是合约的地址写到堆栈

opCall 调用合约把返回值写到内存中指定的位置,并且会在堆栈中写入0,1代表调用是否成功

opCallCode 调用合约把返回值写到内存中指定的位置,并且会在堆栈中写入0,1代表调用是否成功只不过这个调用用的toaddr和calladdr一样(但是code是被调用合约的)

opDelegateCall 同上调用的函数是DelegateCall

opStaticCall 同上调用的函数是StaticCall

opSuicide 获取到当前合约的balance然后转账到堆栈顶端的地址

opRevert 直接回滚返回错误errExecutionReverted,这个逻辑在interpreter.go

gas_table.go gas的消耗函数都在这里 gasFunc

stack_table.go stackValidationFunc 堆栈检查函数在这里

memory_table.go 内存消耗函数都在这里 memorySizeFunc

stack.go 一个堆栈结构

intpool.go 封装了一个stack

interpreter.go 主要是一个run函数(注释里面有句话很重要,说是所有返回的err都是回滚+消耗掉所有gas除了errExecutionReverted表示回滚但是不消耗gas) 主要是运行一个合约

memory.go 代表内存的一个结构就是setvalue和getvalue之类的函数

合约里的input是做什么用的?, 其实就是opCallDataLoad通过堆栈中的一个input的偏移来找一个big32大小的数据并且放到堆栈中去

intpool又是做什么的?感觉就是一个普通的bigint的缓存池,没有实际意义因为所有的get操作都直接被set成另外一个值了

call和callcode等的区别是什么?

call callcode 和DelegateCall这三个的区别主要是三个合约的成员变量

1、caller代表了自己调用者 2、self代表了自己 3、value代表合约里有多少钱

这三个又可以归结为两个一个是状态数据库(key value)一个是合约里有多少钱

状态数据库只能写当前合约地址的也就是self的keyvalue,所以self影响了状态数据库

合约里转账也只能转合约的value其实还是对应的self这个地址(因为value对应的是数据库里的地址的,contract.value仅仅是查询使用的),所以这里会影响value(opCreate和opSuiside)

而self在调用别的合约的时候就变成了caller了,所以self会影响calle

这三种调用

call 是caller是传入的参数caller,self用的传入的参数to,value用的是传入的value,并且真实的把caller的value转账到了to,并且如果这个合约地址不存在新建一个合约账户,这样写的数据库是to的数据库,用的钱是caller转给他的钱

callcode 是caller是传入的参数caller,self用的传入的参数caller,value用的是传入的value,但是由于caller和self都是caller所以没有实际转账,这样写的数据库是caller的数据库,用的钱是caller的钱

DelegateCall caller是caller的caller,self是caller本身,value为caller的caller的value,因为是代理调用所以其实不用转账,这样写的数据库是caller的数据库,用的前是caller的钱,其实这个合约调用就相当于重新建了一个caller的合约(除了code不一样其他都一样)

vm end*************************************************************************************

params===================================================

gas_table.go 一些gas定价的表格参数

params*************************************************************************************

问题

每一个peer有一个pubkey这个是从哪儿来的?目前理解为p2p加密通信协议,用于对消息进行加密,每一个peer的nodeid就是pubkey,handshake的时候他们用公私密钥进行加解密

todo vm执行失败,看看vm内部会不会回滚一点db,反正部分失败是在外部是不会回滚db的 ?,在vm/evm.go这个文件的call函数中都有回滚

receipt在哪儿存?(通过blockchain.go的WriteBlockWithState写到数据库) block中只有receipt的hash,以及为啥要设计他?他有啥用?他有啥用目前来看是只有block数据和receipt数据是在网络上传输的,而state数据是没有传输的

还有从一个地方可以看出来receipt用途的一个小点,就是api.go中的GetTransactionReceipt会把所有的receipt字段重新封装了一些字段给到客户端

合约账户的私钥在哪儿?合约的地址是通过caller的地址加上caller的nonce生成的,不是通过私钥生成的,所以没有私钥,也就不存在 私钥在哪儿的这个问题(evm/evm.go create函数)但是引出来一个问题,对应合约的钱是通过什么机制转出去的?这里的答案是opSuicide 这个指令也就是只有合约自己可以把钱转出去,其实还有一个opcreate是在创建子合约的时候也会转账,另外还有一个方式是调用opcall指令(对应的是addr.transfer这个函数)

对比构造函数和一般的函数调用对应的指令因为看源码vm/evm.go的代码好像调用都是从code的第一个字节开始执行的?这里不知道有啥蹊跷没有 (in *Interpreter) Run的起始pc都是0,这个可以看以太坊技术详解与实战第五章

以太坊中的虚拟机执行的err有的没有回滚原因是什么?

以太坊中的挖完的区块怎么连接到链上,也就是对应比特币中的区块候选链在哪儿 WriteBlockWithState 挖完矿直接进这里了

其他备忘:

uncle的选取是,找自己7个以上的祖先,和然后找这7个祖先对应的uncle,自己添加的uncle必须是7个祖先的后代(也就是uncle老爹必须是在7代主线内),而且必须不在7个祖先的uncle里

挖矿的奖励目前看只和uncles数有关系(固定阶段的两个分支也有区别)没有像比特币一样和时间有关系

abi调用过程目前知道的是发送调用

经过(b *bridge) Send(bridge.go)->(c *BoundContract) Call(abi/bind/backends/base.go)-> (b *SimulatedBackend) callContract(simulated.go)->(st *StateTransition) TransitionDb()(state_transition.go)

返回值通过TransitionDb返回然后abi通过unpack把他转换成json最后返还给客户端

相关文章:

ACM_求N^N的前5位数和后5位数(数论)

NNNNN Time Limit: 2000/1000ms (Java/Others) Problem Description: 对于整数N&#xff0c;求N^N的前5位和后5位&#xff08;1057题加强版) Input: 多组测试数据&#xff0c;每组测试数据输入为一个整数n&#xff08;6 < n < 10^9&#xff09;&#xff0c;n为0时结束。 …

ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml)

我们都知道在使用WebApi的时候Controller会自动将Action的返回值自动进行各种序列化处理&#xff08;序列化为json&#xff0c;xml等&#xff09;&#xff0c;但是如果Controller的自动序列化后的结果不是我们想要的该怎么办呢&#xff1f;其实在MVC中有一个GlobalConfiguratio…

ai为什么要栅格化_三大优势告诉你,为什么一定要加盟AI定制家居

随着90后、00后逐渐成为社会的主力&#xff0c;他们也进入到了住房和家居市场&#xff0c;成为消费的主力军。和以前的消费者不同&#xff0c;生活条件更为优越的他们有能力&#xff0c;有想法追求更好的生活和居住环境&#xff0c;于是定制家居市场在这样的市场条件下蓬勃发展…

当区块链遇到零知识证明

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 什么是零知识证明 零知识证明的官方定义是能够在不向验证者任何有用的信息的情况下&#xff0c;使验证者相信某个论断是正确的。这个定义有点抽象&a…

从条纹边框的实现谈盒子模型(转)

类似下面这个图形&#xff0c;只使用一个标签&#xff0c;可以有多少种实现方式&#xff1a; 假设我们的单标签为 div: 1<div></div>定义如下通用 CSS: 12345div{position:relative;width: 180px;height: 180px;}这一题主要考查的是盒子模型 Box Model 与 背景 bac…

python表格筛选打印_按行名进行表格筛选:awkpythonR

引入Excel确实很强大。用Excel查找一行很容易&#xff0c;同样的事情1000次就很复杂。批量查询的需求应运而生~实验狗确实需要各种帮助&#xff0c;不然就傻傻复制啦~1.awk读取多个文件awk BEGIN{OFSFS"\t"}ARGIND1{print $0, $1;}ARGIND2{} file1 file21)awk初步提取…

SVG和canvas

1、SVG实现的圆环旋转效果 参考&#xff1a;http://www.softwhy.com/article-6472-1.html 2、SVG中的图形可以通过 transform"matrix(0,-1,1,0,0,440)"进行旋转。 3、svg代码可以单独放在一个后缀名为 .svg 的文件中保存起来。这个文件就是矢量图片文件。 这点用来制…

用零知识证明解决投票安全

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 背景 我们经常会遇到需要给别人投票的情况&#xff0c;比如有些公司会组织员工给领导做反向打分&#xff0c;但是往往员工都不敢“真心实意”的打分…

gitLab创建自己的私有库

一.创建私有库的流程简介 创建一个项目,留着后面的流程3制作私有库在可以创建私有库的地方创建一个code repository, code repository是代码仓库,我们把代码上传到这个仓库。在可以创建私有库的地方创建一个spec repository, spec repository是配置仓库,所有的配置按照包名、版…

AngularJS安装配置与基础概要整理(上)

以前整理的&#xff0c;可供参考。 安装&#xff1a; 1.首先要安装node.js和它的npm包管理系统。&#xff08;nodejs相关待整理&#xff09; 2.安装grunt .grunt是一个基于任务的Javascript工程命令行构建工具。 在dos窗口输入&#xff1a;npm install grunt-cli -g 具体模块安…

通风与防排烟工程电子书_菠菜关于防排烟系统使用软接头工程量计算注意及定额选用建议...

前言&#xff1a;前几日分享《工程建设标准强制性条文》关于安装专业相关内容&#xff0c;其余规范部分&#xff0c;建议大家自行查看&#xff0c;不再继续分享。今日继续分享《建筑防烟排烟系统技术标准》相关内容依据1&#xff1a;2.1 设于排风兼排烟系统上的软接管必须为不燃…

超级账本(Hyperledger Fabric)之权限管理浅析

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 超级账本&#xff08;Hyperledger Fabric&#xff09;之权限管理浅析 超级账本是联盟链的代表&#xff0c;而其相对于共链&#xff08;例如比特币&a…

Java通过JDBC连接MySQL数据库

代码描述&#xff1a;把前台获取的字段作为查询条件&#xff0c;返回符合条件的记录。 1 package com.imooc.dao;2 3 import java.sql.Connection;4 import java.sql.DriverManager;5 import java.sql.PreparedStatement;6 import java.sql.ResultSet;7 import java.sql.SQLExc…

关于C#调用非托管DLL,报“内存已损坏的”坑,坑,坑

因客户需求&#xff0c;与第三方对接&#xff0c;调用非托管DLL&#xff0c;之前正常对接的程序&#xff0c;却总是报“内存已损坏的异常”&#xff0c;程序进程直接死掉&#xff0c;折腾到这个点&#xff08;2018-05-11 00:26&#xff09;&#xff0c;终于尘埃落定,直接上程序…

python会不会出现内存泄露_Python内存泄漏和内存溢出的解决方案

一、内存泄漏像Java程序一样&#xff0c;虽然Python本身也有垃圾回收的功能&#xff0c;但是同样也会产生内存泄漏的问题。对于一个用 python 实现的&#xff0c;长期运行的后台服务进程来说&#xff0c;如果内存持续增长&#xff0c;那么很可能是有了“内存泄露”。1、内存泄露…

以太坊发展历史回顾

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 以太坊历史 最近历史记录&#xff0c;请查看Taylor Gerring博客发帖。 诞生 2013年末Vitalik Buterin第一次描述了以太坊&#xff0c;作为他研究比…

医学图像分类_TauMed:医学诊断领域中的图像分类测试数据扩增

南京大学智能软件工程实验室iselab.cn摘要&#xff1a;深度学习在医学分类方面取得了长足的进步。但是&#xff0c;在许多现实的环境中&#xff0c;用于训练和测试的数据不足且不平衡&#xff0c;深度学习模型将很容易过度拟合且泛化能力很差。并且由于医院和患者的状况并不总是…

仲兆鹏 160809329 第5次

---恢复内容开始--- 第一题 #include<stdio.h>//输入三个数有小到大排序 int main() {int a;int b;int c;printf("输入三个整数:");scanf("%d %d %d",&a,&b,&c);if(a>c) { ta; ac; ct; } if(b>c) { tb…

promise实现多个请求并行串行执行

早上查资料&#xff0c;偶然发现这个话题&#xff0c;发现自己并不会&#xff0c;于是乎&#xff0c;下来研究了一下。 想想之前我们用jquery写请求的时候&#xff0c;要实现请求的串行执行&#xff0c;我们可能是这么做的。 $.ajax({url: ,data: ,success: function (data) {$…

人工智能和区块链的融合

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 AI与区块链结合&#xff0c;可能性有多大&#xff1f; 人工智能和区块链是促进各行业创新和转型的主要技术&#xff0c;对这一点各行业已达成共识。…

AngularJS学习笔记(3)——通过Ajax获取JSON数据

通过Ajax获取JSON数据 以我之前写的与用户交互的动态清单列表为例&#xff0c;使用JSON前todo.html代码如下&#xff1a; <!DOCTYPE html> <html ng-app"todoApp"> <head> <meta charset"UTF-8"> <title>TO DO List</tit…

python爬取哔哩哔哩视频_荐爬取哔哩哔哩中的cosplay小视频

爬取哔哩哔哩小视频前言&#xff1a;想必大家都对小视频感兴趣吧&#xff0c;今天的爬虫的内容为将哔哩哔哩中的视频下载到本地&#xff0c;今天爬取的网站为URL : https://vc.bilibili.com/p/eden/all#/?tab%E5%BE%A1%E5%AE%85%E6%96%87%E5%8C%96&tagCOSPLAY1. 分析站点a…

区块链双语术语大全

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 这是一个简单而又全面的Blockchain词汇表&#xff0c;用于令人印象深刻的blockchain语言世界。 51% Attack&#xff08;51%攻击&#xff09; 当一…

SQL SERVER的锁机制(三)——概述(锁与事务隔离级别)

五、锁与事务隔离级别 事务隔离级别简单的说&#xff0c;就是当激活事务时&#xff0c;控制事务内因SQL语句产生的锁定需要保留多入&#xff0c;影响范围多大&#xff0c;以防止多人访问时&#xff0c;在事务内发生数据查询的错误。设置事务隔离级别将影响整条连接。 SQL Serve…

开源造轮子:一个简洁,高效,轻量级,酷炫的不要不要的canvas粒子运动插件库...

一&#xff1a;开篇 哈哈哈&#xff0c;感谢标题党的莅临~ 虽然标题有点夸张的感觉&#xff0c;但实际上&#xff0c;插件库确实是简洁&#xff0c;高效&#xff0c;轻量级&#xff0c;酷炫酷炫的咯。废话不多说&#xff0c;先来看个标配例子吧&#xff1a; &#xff08;codepe…

python启动appium服务_python下appium服务的自启动和关闭

最近想把前不久写的webUi框架改写成mobile_Ui,也就是 用于手机端的UI自动化框架&#xff0c;目前已经完成该框架的改写&#xff0c;记录其中一些问题&#xff0c;框架后续会单独写篇幅介绍遇到的第一个问题就是1、python怎么能够自动启动和自动关闭appium服务&#xff0c;这样每…

以太坊源码分析

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 前言&#xff1a;人类正在步入数据时代。如今&#xff0c;全球每天就产生超过500亿GB的数据&#xff0c;据IDC预测&#xff0c;到2025年这一数据将超…

yapi-docker

yapi-docker 转载于:https://www.cnblogs.com/vickey-wu/p/9026153.html

灵活性是原则性基础上的灵活

灵活性是原则性基础上的灵活&#xff0c;没有原则性的灵活是耍流氓。 原则性是质&#xff0c;灵活性是量&#xff0c;灵活性有度的要求&#xff0c;就是不能改变质。转载于:https://www.cnblogs.com/jcode/p/5961867.html

办公室自动化系统_信息化管理建设 公司办公室用自动盖章机贵吗?

办公室自动盖章机的应用我们首先要考虑到底有没有用&#xff0c;之后在考虑贵不贵的问题。自动盖章机也称智能印章&#xff0c;是企业单位建设信息化印章管理方式的一种&#xff0c;过去由于人工盖章和管章效率低&#xff0c;且风险较大&#xff0c;为了避免因印章管理不当引起…