关于fabric:fabricjs-可以实现哪些功能-动图介绍

我是开源图形编辑器,vue-fabric-editor的作者,明天整顿了一下fabric.js 能够实现的性能,用动图的模式分享给大家,不便疾速理解fabric.js。 源码见链接 辅助线 曲线文字 垂直文字 3D联合 自定义文字条 缩略图 白板 自定义管制条 Gif展现 图表展现 多边形绘制 拼图 笔刷 多图生成 导入PDF 流动线条 拖入元素 开源利用

February 18, 2024 · 1 min · jiezi

关于fabric:Hyperledger-Fabric-智能合约开发及-fabricsdkgofabricgateway-使用示例

前言在上个试验 Hyperledger Fabric 多组织多排序节点部署在多个主机上 中,咱们曾经实现了多组织多排序节点部署在多个主机上,但到目前为止,咱们所有的试验都只是钻研了联盟链的网络配置办法(只管这的确是重难点),而没有思考具体的利用开发。本文将在后面试验的根底上,首先尝试应用 Go 语言开发了一个工作室联盟链的我的项目信息智能合约,并胜利将其部署至联盟链上;而后根据官网示例,应用 fabric-gateway 模块实现了一个可能治理我的项目信息智能合约的客户端;之后比照了 fabric-gateway 模块和 fabric-sdk- 模块各自的优缺点,剖析官网示例源码实现了通过 fabric-sdk- 模块治理整个联盟链网络。个别语境下,本文默认智能合约等于链码。 工作筹备本文工作以三组织三排序节点的形式启动 Hyperledger Fabric 网络,试验共蕴含四个组织—— council 、 soft 、 web 、 hard , 其中 council 组织为网络提供 TLS-CA 服务,并且运行保护着三个 orderer 服务;其余每个组织都运行保护着一个 peer 节点、一个 admin 用户和一个 user 用户。网络结构为(试验代码已上传至:https://github.com/wefantasy/FabricLearn 的 6_ContractGatewayAndSDK 下): 项运行端口阐明council.ifantasy.net7050council 组织的 CA 服务, 为联盟链网络提供 TLS-CA 服务orderer1.council.ifantasy.net7051council 组织的 orderer1 服务orderer1.council.ifantasy.net7052council 组织的 orderer1 服务的 admin 服务orderer2.council.ifantasy.net7054council 组织的 orderer2 服务orderer2.council.ifantasy.net7055council 组织的 orderer2 服务的 admin 服务orderer3.council.ifantasy.net7057council 组织的 orderer3 服务orderer3.council.ifantasy.net7058council 组织的 orderer3 服务的 admin 服务soft.ifantasy.net7250soft 组织的 CA 服务, 蕴含成员: peer1 、 admin1 、user1peer1.soft.ifantasy.net7251soft 组织的 peer1 成员节点web.ifantasy.net7350web 组织的 CA 服务, 蕴含成员: peer1 、 admin1 、user1peer1.web.ifantasy.net7351web 组织的 peer1 成员节点hard.ifantasy.net7450hard 组织的 CA 服务, 蕴含成员: peer1 、 admin1 、user1peer1.hard.ifantasy.net7451hard 组织的 peer1 成员节点试验筹备本文网络结构间接将 Hyperledger Fabric无排序组织以Raft协定启动多个Orderer服务、TLS组织运行保护Orderer服务 中创立的 4-2_RunOrdererByCouncil 复制为 6_ContractGatewayAndSDK 并批改(倡议间接将本案例仓库 FabricLearn 下的 6_ContractGatewayAndSDK 目录拷贝到本地运行),文中大部分命令在 Hyperledger Fabric定制联盟链网络工程实际 中已有介绍因而不会具体阐明。默认状况下,所有命令皆在 6_ContractGatewayAndSDK 根目录下执行,在开始前面的试验前依照以下命令启动根底试验网络: ...

June 11, 2022 · 13 min · jiezi

关于fabric:Day-19100-React-Fabricjs-实现可拖拽变化的多边形

1、需要实现Canvas绘制多边形。 2、成果 3、代码官网Demo是HTML版本的,我改写了React版本。 // Copyright 2021 zhaoardenimport React, { useState,useCallback } from 'react';import { fabric } from "fabric";import { Button } from 'antd';class Polygon extends React.Component { constructor(props) { super(props); this.state={ canvas:{} } } componentDidMount(){ console.log('componentDidMount'); const canvas = new fabric.Canvas('c'); console.log('canvas',canvas); this.setState({canvas:canvas}) // console.log('state-canvas',this.state.canvas); var points = [{ x: 3, y: 4 }, { x: 16, y: 3 }, { x: 30, y: 5 }, { x: 25, y: 55 }, { x: 19, y: 44 }, { x: 15, y: 30 }, { x: 15, y: 55 }, { x: 9, y: 55 }, { x: 6, y: 53 }, { x: -2, y: 55 }, { x: -4, y: 40 }, { x: 0, y: 20 }] var polygon = new fabric.Polygon(points, { left: 100, top: 50, fill: '#D81B60', strokeWidth: 4, stroke: 'green', scaleX: 4, scaleY: 4, objectCaching: false, transparentCorners: false, cornerColor: 'blue', }); canvas.viewportTransform = [0.7, 0, 0, 0.7, -50, 50]; canvas.add(polygon); } render() { const controls={ display: 'inline-block' }; const {canvas}=this.state // define a function that can locate the controls. // this function will be used both for drawing and for interaction. function polygonPositionHandler(dim, finalMatrix, fabricObject) { var x = (fabricObject.points[this.pointIndex].x - fabricObject.pathOffset.x), y = (fabricObject.points[this.pointIndex].y - fabricObject.pathOffset.y); return fabric.util.transformPoint( { x: x, y: y }, fabric.util.multiplyTransformMatrices( fabricObject.canvas.viewportTransform, fabricObject.calcTransformMatrix() ) ); } // define a function that will define what the control does // this function will be called on every mouse move after a control has been // clicked and is being dragged. // The function receive as argument the mouse event, the current trasnform object // and the current position in canvas coordinate // transform.target is a reference to the current object being transformed, function actionHandler(eventData, transform, x, y) { var polygon = transform.target, currentControl = polygon.controls[polygon.__corner], mouseLocalPosition = polygon.toLocalPoint(new fabric.Point(x, y), 'center', 'center'), polygonBaseSize = polygon._getNonTransformedDimensions(), size = polygon._getTransformedDimensions(0, 0), finalPointPosition = { x: mouseLocalPosition.x * polygonBaseSize.x / size.x + polygon.pathOffset.x, y: mouseLocalPosition.y * polygonBaseSize.y / size.y + polygon.pathOffset.y }; polygon.points[currentControl.pointIndex] = finalPointPosition; return true; } // define a function that can keep the polygon in the same position when we change its // width/height/top/left. function anchorWrapper(anchorIndex, fn) { return function (eventData, transform, x, y) { var fabricObject = transform.target, absolutePoint = fabric.util.transformPoint({ x: (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x), y: (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y), }, fabricObject.calcTransformMatrix()), actionPerformed = fn(eventData, transform, x, y), newDim = fabricObject._setPositionDimensions({}), polygonBaseSize = fabricObject._getNonTransformedDimensions(), newX = (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x) / polygonBaseSize.x, newY = (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y) / polygonBaseSize.y; fabricObject.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5); return actionPerformed; } } function Edit() { console.log('canvas',canvas); console.log('Edit'); // clone what are you copying since you // may want copy and paste on different moment. // and you do not want the changes happened // later to reflect on the copy. var poly = canvas.getObjects()[0]; canvas.setActiveObject(poly); poly.edit = !poly.edit; if (poly.edit) { var lastControl = poly.points.length - 1; poly.cornerStyle = 'circle'; poly.cornerColor = 'rgba(0,0,255,0.5)'; poly.controls = poly.points.reduce(function (acc, point, index) { acc['p' + index] = new fabric.Control({ positionHandler: polygonPositionHandler, actionHandler: anchorWrapper(index > 0 ? index - 1 : lastControl, actionHandler), actionName: 'modifyPolygon', pointIndex: index }); return acc; }, {}); } else { poly.cornerColor = 'blue'; poly.cornerStyle = 'rect'; poly.controls = fabric.Object.prototype.controls; } poly.hasBorders = !poly.edit; canvas.requestRenderAll(); } return <div> <h1>Learn, {this.props.name}</h1> <div className={controls}> <p> <Button id="edit" onClick={Edit}>Toggle editing polygon</Button> </p> </div> <canvas id="c" width="500" height="400" style={{border:'1px solid #ccc'}}></canvas> </div>; }}export default Polygon;参考文档http://fabricjs.com/docs/fabr... ...

December 23, 2021 · 3 min · jiezi

关于fabric:治愈系列

1、即便没有人为你鼓掌,也要优雅的谢幕,感激本人的认真付出。 2、只有小孩子才问你为什么不理我,成年人都是心领神会地互相疏远。 3、不要向任何人诉苦,因为20%的人不关怀,还有80%的人听到后很快乐。 4、遇见的人多了,你才会明确哪些人值得用生命去珍惜,哪些人只适宜绕道而行。 5、有时候,咱们必须闭上嘴,放下自豪,抵赖是本人错了。这不是认输,而是成长。 6、该扔的就扔,该放弃就放弃,从今天起,余生做个俗人,以本人最好的姿势生存。 7、生存有一百种过法,他人的故事再好,始终容不下你。活成什么样子,本人决定。 8、生存就是这样,痛并高兴着。好的坏的咱们都收下吧,而后一声不响,持续生存。 9、凡是能说透的货色,根本也就是释怀了,要晓得,心结,是说不清楚的,甚至说不出口。 10、凶恶要有底线,慷慨要有准则。不分青红皂白,只晓得对人好,那会辜负本人的一片善意。 11、无论这个世界对你怎么,都请你判若两人的致力,人生是一场一个人的旅程,无人可代替。 12、别总因为迁就他人就冤屈本人,弯腰的工夫久了,只会让人习惯于你的低姿态,你的不重要。 13、难熬的日子总会过来,不信你回头看看,你都曾经在人不知;鬼不觉中,熬过了很多苦难,很棒吧。 14、这世界上除了生命,其实没什么货色让你迷失本人,学会笑着接受,笑着说:没什么了不起! 15、你长大了,你须要的,是一个可能爱护你爱护你的人,而不是一个只晓得让你付出和惆怅的人。 16、有时候疏远不是厌恶,而是太喜爱又很无奈,我不想抱着冀望期待落空,只好伪装慷慨本人先走。 17、大多数时候,耗费你能量的都不是工作,而是工作中遇到的人。干活自身是不累的,均衡情绪最累。 18、不要到处鼓吹你的心田,这世上不止你一个人有故事;也不要到处宣泄你的苦楚,没人会感同身受。 19、没有人会活得一无是处,也没有人能活得了无遗憾;美妙的生存,并不是没有瑕疵,而是懂得取舍。 20、任何人都是这样,解决他人的事件总是大刀阔斧一把抓住问题,轮到本人却沉迷在细枝末节不肯撒手。 21、茶凉了,就别再续了,再续也不是原来的滋味了;人走了,就别再留了,再留下也不是原来的感觉了。 22、能笑的时候就开心大笑,感觉累了痛了就纵情地哭。每个人在这世上都是惟一,做就做最实在的本人。 23、累的时候抱抱本人,哭的时候哄哄本人,身边不可能无时无刻有一个人陪着你宠着你,要学会本人疼本人。 24、小时候认为流血了,就是很重大的事件,不论痛不痛,先哭再说,长大当前才发现,原来流泪,比流血还要疼。 25、看淡一点,再致力一点,越致力越侥幸,这世上没有谁活得比谁容易,只是有人在呼天喊地,有人在静默坚守。 26、当你下定决定做一件事,那就去尽力做,给本人一个期限,不必通知所有人,也不要犹豫,直到你真的尽力为止。 27、抓不紧的就放掉,得不到的就放弃,这并不是没有毅力,而是智慧的抉择。切记不要浪费时间在得不到后果的人和事上。

November 28, 2021 · 1 min · jiezi

关于fabric:fabricjs-矩形拖动效果myCanvasvue

<script>export default { data () { return { setColor: ['#FF0000', '#F2C94C', '#EBFF00', '#9B51E0', '#6FCF97', '#F2F2F2', '#00FFF0', '#33FF00', '#00A3FF', '#FF00C7', '#FF7A00', '#0075FF'] } }, mounted () { }, methods: { oCoords (w, h, x2, y2, reg) { return { tl: this.rotatoNi(x2 - w / 2, y2 - h / 2, x2, y2, reg), tr: this.rotatoNi(x2 + w / 2, y2 - h / 2, x2, y2, reg), bl: this.rotatoNi(x2 - w / 2, y2 + h / 2, x2, y2, reg), br: this.rotatoNi(x2 + w / 2, y2 + h / 2, x2, y2, reg) } }, rotatoNi (x1, y1, x2, y2, reg) { // 在平面坐标上,任意点P(x1,y1),绕一个坐标点Q(x2,y2)逆时针旋转角度后,新的坐标设为(x, y)的计算公式: // x= (x1 - x2)*cos() - (y1 - y2)*sin() + x2 ; // y= (x1 - x2)*sin() + (y1 - y2)*cos() + y2 ; let x = parseInt((x1 - x2) * Math.cos(Math.PI * reg / 180) - (y1 - y2) * Math.sin(Math.PI * reg / 180) + x2); let y = parseInt((x1 - x2) * Math.sin(Math.PI * reg / 180) + (y1 - y2) * Math.cos(Math.PI * reg / 180) + y2); return { x: x, y: y } //旋转后的坐标(x,y) }, rotatoNi2 (x1, y1, x2, y2, reg) { let x = ((x1 - x2) * Math.cos(Math.PI * reg / 180) - (y1 - y2) * Math.sin(Math.PI * reg / 180) + x2); let y = ((x1 - x2) * Math.sin(Math.PI * reg / 180) + (y1 - y2) * Math.cos(Math.PI * reg / 180) + y2); return { x: x, y: y } //旋转后的坐标(x,y) }, //左上角直角三角形 creatPath (list, i, type) { //console.log('以后箱体左上角直角三角形数据', list, i, type) let wc = 0 let x1 = list.x - list.width / 2 + wc let y1 = list.y - list.height / 2 + wc let prot = this.rotatoNi(x1, y1, list.x, list.y, list.rotationAngle) let x = prot.x let y = prot.y let u = 'M ' + x + ' ' + y + ' L ' + (x + 10) + ' ' + y + ' L ' + x + ' ' + (y + 10) + ' z' var path = new fabric.Path(u); //console.log(i + '三角形的坐标点', x, y) return path.set({ angle: list.rotationAngle, left: x, //间隔画布上边的间隔 top: y, //间隔画布左侧的间隔,单位是像素 fill: '#FFFFFF', //填充的色彩 selectable: false, stroke: '#FFFFFF', // 边框色彩 opacity: 0.3, strokeWidth: 1, id: list.id, networkPort: list.networkPort, operateType: type, }); }, //创立中心点 makeCircle2 (list) { var circle = new fabric.Circle({ originX: "center", originY: "center", left: list.x, //间隔画布上边的间隔 top: list.y, //间隔画布左侧的间隔,单位是像素 radius: 4, //圆形半径 fill: '#000', //填充的色彩 stroke: this.setColor[list.portId % 12] ? this.setColor[list.portId % 12] : '#fff', // 边框色彩 selectable: false, evented: false, id: list.id, networkPort: list.networkPort, index: list.index, hoverCursor: "pointer",//鼠标指针形式 strokeWidth: 2 // 边框大小 }); return circle }, //创立文本 makeText (t, list, i, type) { let x1 = list.x - list.width / 2 let y1 = list.y - list.height / 2 let prot = this.rotatoNi(x1, y1, list.x, list.y, list.rotationAngle) let x = (prot.x - list.x) / 1.5 + list.x let y = (prot.y - list.y) / 1.5 + list.y //console.log(i + '文本的坐标点', x, y) var textBox = new fabric.Textbox(t, { /* originX: "left", originY: "top", */ originX: "center", originY: "center", left: x, top: y, centeredRotation: true, //核心旋转 fontSize: 12, selectable: false, evented: false, networkPort: list.networkPort, fill: '#fff', id: list.id, operateType: type, }); return textBox }, //创立矩形 makeRect (left, top, ids, width, height, angle, groupId, boxId, boxFileId) { let rect = new fabric.Rect({ //rx: 4, //圆角半径 // ry: 4, //圆角半径 angle: angle, left: left, top: top, originX: "center", //绝对于坐标点地位 originY: "center", //绝对于坐标点地位 width: width, height: height, //hoverCursor: "pointer", fill: "rgba(0,153,255,0.20)",//"#1C445E", stroke: '#136094', // 边框色彩 strokeWidth: 2, // 边框大小 borderColor: "#0099FF", //选中边框色 cornerStyle: "circle", // 手柄形态 正方形 rect||圆 circle cornerColor: "#0099FF", //手柄背景色 cornerStrokeColor: "#0099FF", //手柄框边框 hasControls: true, //手柄 hasBorders: true, //手柄线 visible: true, //是否可见 selectable: true, //是否可抉择的对象 evented: true, //是否拖动 centeredRotation: true, //核心旋转 centeredScaling: true, //居中缩放 transparentCorners: false, //选中框通明角 preserveObjectStacking: true, // opacity: 0.5, networkPort: ids.networkPort,//网口 index: ids.index,//序号 groupId: groupId, id: boxId ? boxId : null, boxFileId: boxFileId, //lockRotation: true,//锁定对象旋转 }); rect.setControlsVisibility({ mt: false, mb: false, bl: false, br: false, tl: false, tr: false, mr: false, ml: false, mtr: true, }); return rect; }, //创立线段 /* coords 坐标 list 以后对象 arr虚线 jt, 虚线箭头 */ makeLine (coords, list, arr, jt, startId, endId) { //console.log('list.networkPort', list.networkPort) return new fabric.Line(coords, { fill: this.setColor[list && list.portId % 12] ? this.setColor[list && list.portId % 12] : '#fff', stroke: this.setColor[list && list.portId % 12] ? this.setColor[list && list.portId % 12] : '#fff', strokeWidth: 2, originX: "center", originY: "center", selectable: false, evented: false, hasControls: false, hasBorders: false, hasRotatingPoint: false, hoverCursor: "default", index: list.index, networkPort: list && list.networkPort, jt: jt || '', id: list && list.id, startId, endId, //myJoker: arr, strokeDashArray: arr || [], huadongbs: list.huadongbs || false }); }, //创立连线上的实体三角形箭头 createArrowHead (x1, y1, x2, y2, width, height, list, type, startId, endId) { return new fabric.Triangle({ angle: this.getAngle(x1, y1, x2, y2), fill: "white", top: y2, left: x2, width: width, height: height, originX: "center", originY: "center", selectable: false, evented: false, id: list.id, index: list.index, networkPort: list.networkPort, startId, endId, huadongbs: list.huadongbs || false }); }, /* 绘制箭头函数 ------->-------- fromX, fromY:终点坐标(也能够换成p1,只不过它是一个数组) toX, toY:起点坐标 (也能够换成p2,只不过它是一个数组) theta:三角斜边一直线夹角 headlen:三角斜边长度 width:箭头线宽度 color:箭头色彩 */ drawArrow (canvas, fromX, fromY, toX, toY, theta, headlen, width, color) { width = 1;//箭头宽度设置为1 var theta = theta || 30, headlen = headlen || 10, width = width || 1, color = color || '#000', angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI, angle1 = (angle + theta) * Math.PI / 180, angle2 = (angle - theta) * Math.PI / 180, topX = headlen * Math.cos(angle1), topY = headlen * Math.sin(angle1), botX = headlen * Math.cos(angle2), botY = headlen * Math.sin(angle2); var arrowX, arrowY; arrowX = toX + topX; //箭头结尾右边坐标 arrowY = toY + topY; canvas.add(this.makeLine([arrowX, arrowY, toX, toY], '', [], 'jt')); //ctx.moveTo(arrowX, arrowY); //ctx.lineTo(toX, toY); //箭头开始坐标 arrowX = toX + botX; //箭头结尾左边坐标 arrowY = toY + botY; canvas.add(this.makeLine([arrowX, arrowY, toX, toY], '', [], 'jt')); // ctx.lineTo(arrowX, arrowY); }, //三角形角度计算 getAngle (x1, y1, x2, y2) { var dx = x2 - x1, dy = y2 - y1, angle = Math.atan2(dy, dx); angle *= 180 / Math.PI; angle += 90; return angle; }, // //扭转画布大小 // zoomIt (factor) { // factor: 比例 // let cWidth = canvas.width; // canvas.setWidth(cWidth * factor); // canvas.setHeight(cWidth * factor); // if (canvas.backgroundImage) { // var bi = canvas.backgroundImage; // bi.width = bi.width * factor; // bi.height = bi.height * factor; // } // var objects = canvas.getObjects(); // for (var i in objects) { // var scaleX = objects[i].scaleX; // var scaleY = objects[i].scaleY; // var left = objects[i].left; // var top = objects[i].top; // var tempScaleX = scaleX * factor; // var tempScaleY = scaleY * factor; // var tempLeft = left * factor; // var tempTop = top * factor; // objects[i].scaleX = tempScaleX; // objects[i].scaleY = tempScaleY; // objects[i].left = tempLeft; // objects[i].top = tempTop; // objects[i].setCoords(); // } // canvas.renderAll(); // canvas.calcOffset(); // }, //阻止右键默认行为 preventYj () { $(document).contextmenu(function (ev) { if (ev.preventDefault) { ev.preventDefault(); } else { window.event.returnValue = false; } }) }, getTanDeg (tan) { var result = Math.atan(tan) / (Math.PI / 180); result = parseInt(result); return result; }, //自定义批改序号从新排序 setArrIndex (str, end, list) { for (var i = 0; i < list.length; i++) { if (end.index > list[i].index && list[i].index > str.index) { list[i].index = list[i].index + 1 } if (end.id == list[i].id) { list[i].index = str.index + 1 } } list = list.sort((a, b) => { return a.index - b.index }); return list; }, //自定义批改序号从新排序 setArrIndex2 (str, end, list) { //序号2和4 理论就是3和4调换地位 if (str.index < end.index) { list[str.index] = list.splice(end.index - 1, 1, list[str.index])[0]; for (var i = 0; i < list.length; i++) { list[i].index = i + 1 } } else { list[end.index - 1].index = str.index for (var i = 0; i < list.length; i++) { if (str.index > list[i].index && list[i].index > end.index) { list[i].index = list[i].index - 1 } } list[str.index - 1].index = str.index - 1 list = list.sort((a, b) => { return a.index - b.index }); } return list; }, compare (pro) { return function (obj1, obj2) { var val1 = obj1[pro]; var val2 = obj2[pro]; if (val1 < val2) { //正序 return 1; } else if (val1 > val2) { return -1; } else { return 0; } } }, isMouseoeut (x, y) { let that = this var a = -15 let cdiv = document.getElementById("canvasZone") var X1 = that.getOffsetLeft(cdiv) - a var Y1 = that.getOffsetTop(cdiv) - a var X2 = that.getOffsetLeft(cdiv) + cdiv.offsetWidth + a var Y2 = that.getOffsetTop(cdiv) + cdiv.offsetHeight + a if (x < X2 && x > X1 && y < Y2 && y > Y1) { return true } else { return false } }, groupAdd (list, canvas) { //console.log('旧式分组') /* x.y示意左上角点 */ var x1 = -50, y1 = -50, width = 100, height = 100; let x = list.x - list.width / 2 let y = list.y - list.height / 2 let u = 'M ' + x + ' ' + y + ' L ' + (x + 10) + ' ' + y + ' L ' + x + ' ' + (y + 10) + ' z' var path2 = new fabric.Path(u); //左上角三角形 path2.set({ left: this.face == true ? (-(list.width / 2)) : (list.width / 2), left: this.showFace == true ? (-(list.width / 2)) : (list.width / 2), top: -(list.height / 2), fill: '#dadcdb', //填充的色彩 opacity: list.boxStatus == 1 ? 0.3 : 1, strokeWidth: 1, angle: this.face == true ? 0 : 90, angle: this.showFace == true ? 0 : 90, }) var t = list.index == 0 ? '' : (list.slotId ? list.slotId : 0) + "_" + (list.portId ? list.portId : 0) + "_" + list.index //文字 // console.log(this.face); var text2 = new fabric.Text(t, { angle: -list.rotationAngle, fontSize: 12, originX: 'center', originY: 'center', fill: '#fff', left: this.face == true ? (-(list.width / 2) + 20) : (list.width / 2 - 20), left: this.showFace == true ? (-(list.width / 2) + 20) : (list.width / 2 - 20), top: -(list.height / 2) + 20, }); //中心点 var circle2 = new fabric.Circle({ originX: "center", originY: "center", radius: 4, //圆形半径 fill: '#000', //填充的色彩 stroke: this.setColor[list.portId] ? this.setColor[list.portId] : '#fff', // 边框色彩 selectable: false, evented: false, hoverCursor: "pointer",//鼠标指针形式 strokeWidth: 2 // 边框大小 }); //矩形 var rect2 = new fabric.Rect({ width: list.width, height: list.height, originX: 'center', originY: 'center', fill: "rgba(0,153,255,0.20)",//"#1C445E", stroke: '#136094', // 边框色彩 strokeWidth: 2, // 边框大小 borderColor: "#0099FF", //选中边框色 cornerStyle: "circle", // 手柄形态 正方形 rect||圆 circle cornerColor: "#0099FF", //手柄背景色 cornerStrokeColor: "#0099FF", //手柄框边框 centeredRotation: true, portId: list.portId, slotId: list.slotId, isSwitch: list.isSwitch, }); var group2 = new fabric.Group([rect2, circle2, text2, path2], { left: list.x, top: list.y, width: list.width, height: list.height, originX: 'center', originY: 'center', isCheckTo: true, //有这个字段示意单选,没有多选 networkPort: list.networkPort,//网口 index: list.index,//序号 groupId: 'box', groupIdd: list.groupId, id: list.id, angle: list.rotationAngle, centeredRotation: true, fill: "#0099FF",//"#1C445E", stroke: '#0099FF', // 边框色彩 strokeWidth: 2, // 边框大小 borderColor: "#0099FF", //选中边框色 cornerStyle: "circle", // 手柄形态 正方形 rect||圆 circle cornerColor: "#0099FF", //手柄背景色 cornerStrokeColor: "#0099FF", //手柄框边框 huadongbs: list.huadongbs || false, boxFileId: list.boxFileId, portId: list.portId, slotId: list.slotId, isSwitch: list.isSwitch, //scaleX: this.canvasZoom, //scaleY: this.canvasZoom }); return group2 } },};</script>

July 27, 2021 · 9 min · jiezi

关于fabric:进阶篇一Fabric-20-手动生成CA证书搭建Fabric网络Raft协议多orderer节点

本文不会在从0开始搭建这个那个网络,咱们会在<<Hyperledger Fabric 2.0 手动生成CA证书搭建Fabric网络-Raft协定>>的根底上来改良,有上文中单orderer节点改成多节点共识。 本次将orderer改为三个节点, 本人须要更多节点的能够本人依据机会状况进行减少,步骤和办法雷同。 一、orderer节点用户注册(TLS)在向TLS注册用户是,有以前注册单用户改成注册多用户(三个节点、orderer1-org0,orderer2-org0,orderer3-org0)https://0.0.0.0:7052为TLS CA 地址, fabric-ca-client register -d --id.name orderer1-org0 --id.secret ordererPW --id.type orderer-u https://0.0.0.0:7052 --tls.certfiles /tmp/hyperledger/fabric-ca-tls/crypto/ca-cert.pemfabric-ca-client register -d --id.name orderer2-org0 --id.secret ordererPW --id.type orderer -u https://0.0.0.0:7052 --tls.certfiles /tmp/hyperledger/fabric-ca-tls/crypto/ca-cert.pemfabric-ca-client register -d --id.name orderer3-org0 --id.secret ordererPW --id.type orderer -u https://0.0.0.0:7052 --tls.certfiles /tmp/hyperledger/fabric-ca-tls/crypto/ca-cert.pem二、org0注册用户同样须要注册三个节点用户 export FABRIC_CA_CLIENT_TLS_CERTFILES=/data/hyperledger/org0/ca/crypto/ca-cert.pemexport FABRIC_CA_CLIENT_HOME=/data/hyperledger/org0/ca/adminfabric-ca-client enroll -d -u https://org0-admin:org0-adminpw@0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#注册order1用户fabric-ca-client register -d --id.name orderer1-org0 --id.secret ordererpw --id.type orderer --id.attrs '"hf.Registrar.Roles=orderer"' -u https://0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#注册order2用户fabric-ca-client register -d --id.name orderer2-org0 --id.secret ordererpw --id.type orderer --id.attrs '"hf.Registrar.Roles=orderer"' -u https://0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#注册order3用户fabric-ca-client register -d --id.name orderer3-org0 --id.secret ordererpw --id.type orderer --id.attrs '"hf.Registrar.Roles=orderer"' -u https://0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pemfabric-ca-client register -d --id.name admin-org0 --id.secret org0adminpw --id.type admin --id.attrs "hf.Registrar.Roles=client,hf.Registrar.Attributes=*,hf.Revoker=true,hf.GenCRL=true,admin=true:ecert,abac.init=true:ecert" -u https://0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem三、生成oerders MSP证书mkdir -p /tmp/hyperledger/org0/orderers/assets/ca/cp /tmp/hyperledger/org0/ca/crypto/ca-cert.pem /tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_HOME=/tmp/hyperledger/org0/orderers/orderer1-org0#orderer1 msp证书export FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=mspfabric-ca-client enroll -u https://orderer1-org0:ordererpw@0.0.0.0:7053 -M /tmp/hyperledger/org0/orderers/orderer1-org0/msp --csr.hosts orderer1-org0 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#orderer2 msp证书export FABRIC_CA_CLIENT_HOME=/tmp/hyperledger/org0/orderers/orderer2-org0export FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=mspfabric-ca-client enroll -u https://orderer2-org0:ordererpw@0.0.0.0:7053 -M /tmp/hyperledger/org0/orderers/orderer2-org0/msp --csr.hosts orderer2-org0 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#orderer3 msp证书export FABRIC_CA_CLIENT_HOME=/tmp/hyperledger/org0/orderers/orderer3-org0export FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=mspfabric-ca-client enroll -u https://orderer3-org0:ordererpw@0.0.0.0:7053 -M /tmp/hyperledger/org0/orderers/orderer3-org0/msp --csr.hosts orderer3-org0 --tls.certfiles /tmp/hyperledger/org0/ca/crypto/ca-cert.pem#admin msp证书export FABRIC_CA_CLIENT_HOME=/tmp/hyperledger/org0/adminexport FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=mspfabric-ca-client enroll -d -u https://admin-org0:org0adminpw@0.0.0.0:7053 --tls.certfiles /tmp/hyperledger/org0/orderers/assets/ca/org0-ca-cert.pem四、生成oerders tls-ca证书mkdir /tmp/hyperledger/org0/orderers/assets/tls-ca/cp /tmp/hyperledger/fabric-ca-tls/crypto/ca-cert.pem /tmp/hyperledger/org0/orderers/assets/tls-ca/tls-ca-cert.pemexport FABRIC_CA_CLIENT_MSPDIR=tls-mspexport FABRIC_CA_CLIENT_TLS_CERTFILES=/tmp/hyperledger/org0/orderers/assets/tls-ca/tls-ca-cert.pemfabric-ca-client enroll -u https://orderer1-org0:ordererPW@0.0.0.0:7052 -M /tmp/hyperledger/org0/orderers/orderer1-org0/tls-msp --enrollment.profile tls --csr.hosts orderer1-org0 --tls.certfiles /data/hyperledger/org0/orderers/tls-ca-cert.pemfabric-ca-client enroll -u https://orderer2-org0:ordererPW@0.0.0.0:7052 -M /tmp/hyperledger/org0/orderers/orderer2-org0/tls-msp --enrollment.profile tls --csr.hosts orderer2-org0 --tls.certfiles /data/hyperledger/org0/orderers/tls-ca-cert.pemfabric-ca-client enroll -u https://orderer3-org0:ordererPW@0.0.0.0:7052 -M /tmp/hyperledger/org0/orderers/orderer3-org0/tls-msp --enrollment.profile tls --csr.hosts orderer3-org0 --tls.certfiles /data/hyperledger/org0/orderers/tls-ca-cert.pem#批改keystore名称mv /tmp/hyperledger/org0/orderers/orderer1-org0/tls-msp/keystore/*_sk /tmp/hyperledger/org0/orderers/orderer1-org0/tls-msp/keystore/key.pemmv /tmp/hyperledger/org0/orderers/orderer2-org0/tls-msp/keystore/*_sk /tmp/hyperledger/org0/orderers/orderer2-org0/tls-msp/keystore/key.pemmv /tmp/hyperledger/org0/orderers/orderer3-org0/tls-msp/keystore/*_sk /tmp/hyperledger/org0/orderers/orderer3-org0/tls-msp/keystore/key.pem#生成admincerts目录mkdir /tmp/hyperledger/org0/orderers/orderer1-org0/msp/admincertscp /tmp/hyperledger/org0/admin/msp/signcerts/cert.pem /data/hyperledger/org0/orderers/orderer1-org0/msp/admincerts/orderer-admin-cert.pemmkdir /tmp/hyperledger/org0/orderers/orderer2-org0/msp/admincertscp /tmp/hyperledger/org0/admin/msp/signcerts/cert.pem /data/hyperledger/org0/orderers/orderer2-org0/msp/admincerts/orderer-admin-cert.pemmkdir /tmp/hyperledger/org0/orderers/orderer3-org0/msp/admincertscp /tmp/hyperledger/org0/admin/msp/signcerts/cert.pem /data/hyperledger/org0/orderers/orderer3-org0/msp/admincerts/orderer-admin-cert.pem⚠️: 同理在每个orderer节点msp上面增加config.yaml文件 ...

August 14, 2020 · 2 min · jiezi

动态海报营销FabricJs方案

简介Fabric.js是一个可以简化Canvas程序编写的库。 Fabric.js为Canvas提供所缺少的对象模型, svg parser, 交互和一整套其他不可或缺的工具。Fabric.js可以做很多事情,如下: 在Canvas上创建、填充图形(包括图片、文字、规则图形和复杂路径组成图形)。给图形填充渐变颜色。组合图形(包括组合图形、图形文字、图片等)。设置图形动画集用户交互。生成JSON, SVG数据等。生成Canvas对象自带拖拉拽功能。使用教程安装npm 安装 npm install fabric --savecdn引用 <script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>// 貌似国外相对较慢可以在https://www.bootcdn.cn/fabric... 找到更快的CDN来源 在使用前,先看下我做的总体效果如下: 初始化创建了一个基本的画布 <canvas id="canvas" width="350" height="200"></canvas>const card = new fabric.Canvas('canvas') // ...这里可以写canvas对象的一些配置,后面将会介绍// 如果<canvas>标签没设置宽高,可以通过js动态设置card.setWidth(350)card.setHeight(200)对画布的交互常用监听事件如下: mouse:down:鼠标按下时mouse:move:鼠标移动时mouse:up:鼠标抬起时 var canvas = new fabric.Canvas('canvas'); canvas.on('mouse:down', function(options) { console.log(options.e.clientX, options.e.clientY) })监听画布对象事件以便“上下一步”的神操作以下为常用的事件: object:added 添加图层object:modified 编辑图层object:removed 移除图层selection:created 初次选中图层selection:updated 图层选择变化selection:cleared 清空图层选中 下面是原文,更多参考__fabricjs官网事件__: So which other events are available in Fabric? Well, from mouse-level ones there are "mouse:down", "mouse:move", and "mouse:up". From generic ones, there are "after:render". Then there are selection-related events: "before:selection:cleared", "selection:created", "selection:cleared". And finally, object ones: "object:modified", "object:selected", "object:moving", "object:scaling", "object:rotating", "object:added", and "object:removed"设置画布背景// 读取图片地址,设置画布背景fabric.Image.fromURL('xx/xx/bg.jpg', (img) => { img.set({ // 通过scale来设置图片大小,这里设置和画布一样大 scaleX: card.width / img.width, scaleY: card.height / img.height, }); // 设置背景 card.setBackgroundImage(img, card.renderAll.bind(card)); card.renderAll();});向画布添加图层对象fabric.js提供了很多对象,除了基本的 Rect,Circle,Line,Ellipse,Polygon,Polyline,Triangle对象外,还有如 Image,Textbox,Group等更高级的对象,这些都是继承自Fabric的Object对象。 ...

October 14, 2019 · 2 min · jiezi

Ubuntu-1804下-Hyperledger-Fabric-10-的搭建

请大家按照步骤进行,避免不必要的错误。 1.查看 apt sourcesudo vi /etc/apt/sources.list如果看到是http://cn.xxxxx之类的,那么就不用换的。但是如果其中是http://us.xxxxxx之类的,那么就是外国的。需要更换源,通过以下命令进行批量更换。 :%s/us./cn./g更换完成后输入 :wq 保存退出。之后更新源。 sudo apt-get update然后安装ssh sudo apt-get install ssh2.安装GO语言下载安装最新的go 下载、安装wget https://storage.googleapis.com/golang/go1.11.linux-amd64.tar.gz如果出现443连接错误,可采用以下方法。进入 https://golang.org/dl/ 选择最新的Linux版本下载到本地文件夹 下载之后,进入下载目录,输入以下命令进行解压安装,(我的目录名为:下载) cd 下载tar -zxvf go1.11.linux-amd64.tar.gz -C /usr/local需要注意:下载的go版本不同,需要更改版本号安装完成后,可以进入 /usr/local 下看到go文件夹。 配置环境变量编辑当前用户的环境变量,可以使用vi编辑器或gedit命令。 sudo gedit ~/.profile在文件的末尾加入以下内容 export PATH=$PATH:/usr/local/go/bin export GOROOT=/usr/local/go export GOPATH=$HOME/go export PATH=$PATH:$HOME/go/bin编辑保存退出后,执行以下命令使得环境变量生效 source ~/.profile输入命令查看GO版本 go version把go的目录GOPATH设置为当前用户的文件夹下,所以记得创建go文件夹 cd ~mkdir go 3.安装Docker需要提前准备安装curl,命令如下 sudo apt-get install curl1.安装Docker安装Docker也会遇到外国网络慢的问题,幸好国内有很好的镜像,推荐DaoClound,安装Docker的命令是: sudo curl -sSL https://get.daocloud.io/docker | sh如果安装失败,可尝试下面的命令 sudo curl -sSl https://get.docker.com/ | sh 安装完成后,运行以下脚本将当前用户添加到Docker的组中 ...

August 7, 2019 · 1 min · jiezi

使用Hyperledger-Fabric和Composer实现区块链应用程序

目前无法绕过技术领域的是区块链话题。但除了加密货币之外,还有更多有趣的应用程序可以带来许多激动人心的软件生态系统。这也适用于Hyperledger项目,该项目提供了一个非常模块化的区块链框架。让我们看看使用Hyperledger Fabric和Composer实现区块链应用程序是多么容易。 关于项目HyperledgerHyperledger是一个umbrella项目的名称,在该项目下开源区块链方法和工具是协同开发的。它由Linux基金会于2015年推出,并享有IBM,英特尔和富士通等软件巨头以及大型社区的热烈参与。Hyperledger的GitHub存储库目前比以往更加活跃。任何人都可以参与开发。 在Hyperledger中,不仅开发了单个区块链框架(或平台)。相反,重点是并行采用多种方法,创造协同效应,可重复使用的组件和灵活性。从Hyperledger概念的角度来看,区块链网络与比特币或以太网等加密货币的代表无法比较。相反,Hyperledger网络的节点分布在参与组织中,这使得私有,许可或联盟区块链网络特别有趣。首先,我们可以忘记公共区块链的工作证明,股权证明和其他共识机制。所涉及的组织从应用程序业务价值和所涉及的信任中作为联合体验证彼此的交易和利益。这也很大程度上解决了可扩展性问题(我们从比特币网络中了解到)并且可以实现高交易吞吐量。 项目Hyperledger的不同区块链方法是Fabric,Burrow,Iroha,Indy和Sawtooth。私有,许可和联合区块链可以与所有这些区块链一起开发,但每种实现都遵循不同的方法。 我们将在本文中详细介绍Fabric,因为它拥有最活跃的社区,并且是最灵活的变体。由于其强大的模块化,fabric是普遍可用的。 “你可以将Hyperledger Fabric视为类似于Apache Web Server”,Linux基金会Hyperledger执行董事Brian Behlendorf说。其他方法更多用于在有限的环境中实施特殊情况。 Hyperledger Fabric ——灵活的区块链应用平台使用Fabric作为平台,可以开发完全独立的分布式分类帐解决方案。Fabric包含可以尽可能自由实现的概念。区块链网络的基础是对所需组织结构的建模。每个参与者都有固定的身份,可以通过颁发的证书来识别自己。除了身份验证之外,还包括授权。使用这种基于角色的系统,可以获得许可区块链中隐私和机密性的灵活方面。对于证书和参与者的管理,可以使用结构证书颁发机构(1.0版之前的成员服务提供者)。 资产的定义(要在区块链上管理的项目)完全取决于区块链应用程序。这些资产,例如来自汽车行业的引擎块由JSON和/或二进制格式的键值对模型定义。 链代码的概念旨在基于资产及其所有者实现业务逻辑。这可用于实现Go,Java或Node.js等语言中的规则,这些规则定义读取权限或资产修改。执行链代码功能可以读取和返回资产和/或创建和修改资产并将它们存储在本地分类帐数据库中。在节点上的本地持久性更改之后,将更改提交给网络(“认可”)并在其他组织接受后插入到区块链中。在以太坊或其他公共区块链平台的背景下,可以将链码与智能合约进行比较。 通道用于实现隐私领域。在最简单的场景中,整个链代码部署在所有参与者加入的单个通道上。但是,为了创建封装区域并仅允许选定的参与者在其中进行通信,可以配置具有受限参与者组的通道。每个通道可以部署不同的链代码,从而可以实现功能隔离。此外,可以使用AES部分或完全加密通道中的通信。 结果,在每个通道中维护一个分布式分类帐,这可以被想象为链接交易的现金簿。每个参与者为他们所属的每个通道保留一份分类帐副本。这为网络中的每个现有信道创建了区块链数据结构。与区块链一样,交易存储在块中,这些块在单个连接列表中成为加密链。 但是,为了向客户端应用程序提供分类帐数据的单独视图,甚至可以执行针对网络的复杂读取请求。由于使用了像CouchDB这样的面向文档的数据库,这是可能的。这为连接到Fabric网络的客户端提供了灵活的数据访问。 使用Composer添加更简单的概念Hyperledger-Composer是Hyperledger生态系统中的工具之一。你可以将其视为Fabric的框架。如果你想开发,构建和管理Fabric网络,那么即使不是强制性的,也是实用的。它引入了基于Fabric的进一步概念,以提供精美的抽象概念。 除资产外,还可以在Composer建模语言中定义网络参与者,交易和事件的方案。每种交易类型的流都通过JavaScript代码在简单的API上实现。访问控制文件可用于限制参与者对某些资源的访问权限。可以在Composer Query Language中定义对分类帐中数据的常用查询,这是一种类似SQL的语言。 然后,必须将所有必需文件打包到.bna文件中的BND(业务网络定义)。然后,可以将此存档安装在现有Fabric网络上。BND的源代码当然可以在我们首选的编辑器中进行本地开发和测试,因此可以通过Git进行版本控制。对于原型设计和演示目的,有Composer Playground。这提供了一个现代,清晰且直观可用的Web界面,可访问Composer CLI的本地配置。使用Playground,你可以轻松创建,安装,测试,编辑,导入和导出BND。 在Composer Playground中,你可以以用户友好的方式安装,修改和测试新的业务网络,而无需先前的样本区块链应用知识(例如车辆生命周期,汽车拍卖或农场动物跟踪)。在设置工具之后,可以在本地完成相同的操作,这样我们就可以在短时间玩游戏后离开托管游乐场。这个游乐场非常适合使用原型验证想法并了解底层的Composer和Fabric模型。 使用案例:引擎块的供应链跟踪为了使用Hyperledger-Fabric和Composer实现私有区块链网络,以汽车行业的发动机组跟踪为例。在这种情况下,有制造商和经销商作为网络参与者。发动机及其安装的车辆显示为资产。制造商和经销商的公司被引入并被识别为网络中的组织。 Fabric链代码应提供以下功能: 1.生产具有唯一序列号的发动机缸体。2.生产后将发动机缸体传送给经销商。3.跟踪车辆的序列号。4.将发动机缸体安装到注册车辆中。下一步是安装所需的工具和设置项目。 开发环境设置和项目创建首先,需要安装文档中列出的Fabric的所有要求。然后我们安装Composer和Composer及其相关工具本身的要求。 然后,最好让自己熟悉新环境。如果我们完全按照上一个链接的说明操作,则fabric-tools现在位于我们的主目录中。通过描述的脚本,我们可以在Docker-Compose中启动一个简单的Fabric网络,获得对等管理员访问权限并停止并再次删除它。首先,我们下载1.1版的Docker镜像并启动网络: export FABRIC_VERSION=hlfv11 && ./downloadFabric.sh && ./startFabric.sh在网络运行时,composer-playground web-UI可以通过composer-playground启动。它使用composer-cli的所有托管配置并访问正在运行的Fabric网络。从现在开始,我们将Fabric视为可配置的平台/基础架构,其状态通过合适的工具进行更改。我们不直接使用Fabric概念开发链代码,权限或任何模型,因为Composer提供了更多优势。 实施功能现在我们在我们选择的目录中创建我们的BND项目。对于Yeoman(使用模板设置项目的代码生成器,如Maven Archtypes),有一个模板(hyperledger-composer:businessnetwork。但是,我已经准备了一个存储库,我们现在也可以使用JavaScript ES6和一些很好的工具。我们应该从开始分支“初始”开始。master分支具有最终版本和工作版本。我们首先克隆存储库的初始分支。 git clone -b initial git@github.com:jverhoelen/fabric-composer-engine-supplychain.git现在我们在我们选择的编辑器中打开文件夹。Visual Studio Code非常适合Composer,因为它具有可安装的语法高亮扩展。稍作修改后你会发现它是一个NPM项目,所以我们从npm install开始安装所有依赖项。使用npm test我们可以运行单元测试,使用npm run lint我们可以测试代码样式,并且使用npm run createArchive我们可以创建the.bna文件,我们以打包格式完成业务网络定义。让我们马上试试看是否一切正常。 然后我们熟悉项目结构。lib文件夹包含实现交易处理器功能的JS文件。当然,我们想测试这个业务逻辑并将我们的单元测试存储在test/文件夹中。模型定义(参与者,资产,交易等)在models/中。 我们想首先为所需的区块链网络建模。为此,我们删除模型文件的内容,并在第一行为其指定一个新的命名空间: namespace org.acme.enginesupplychain我们为参与者制造商和经销商建模,并使用Composer建模语言的继承。我们还希望每个参与者除了姓名外还有一个可选地址。我们将这些属性放入一个概念中: participant Member identified by memberId { o String memberId o String name o Address address optional} participant Manufacturer extends Member {} participant Merchant extends Member {} concept Address { o String country o String city o String street o String streetNo}然后我们介绍我们网络的资产:引擎块和稍后安装引擎的汽车。在这里,我们了解资产和参与者可以互相参考。引用始终指向任何类型的现有资源。我们以小“o”开头的属性总是存在于资源本身中。 ...

May 22, 2019 · 3 min · jiezi

如何编写一个企业级区块链Hyperledger-Fabric开源框架

Convector(a.k.a Convector Smart Contracts)是为企业区块链框架构建的JavaScript开发框架。它增强了开发体验,同时帮助开发人员创建更强大,更安全的智能合约系统。它通过链代码和后端一直到前端,允许开发人员以库的形式重用相同的代码库。它基于模型/控制器模式,支持Hyperledger Fabric,并沿着Fabric精心设计的模式本地运行。 这篇博客文章介绍了该项目的历史,并重点介绍了沿途开发的挑战和解决方案。 当我们开始研究Tellus时,一切都开始了,Tellus是一个无代码交易设计师,用于在Hyperledger Fabric区块链上运行。那时我们有一堆Golang智能合约。 我们对开发者体验(DX)的第一印象并不是那么好。有两种方法:init和invoke,除了在invoke方法上放置if条件并使用其中一个参数指示调用的方法之外,没有其他方法可以添加新方法。所有参数都是位置传递的字符串,需要手动解析复杂参数,并且无法在本地测试它。 在项目开始时,Fabric 1.1增加了对Javascript链代码的支持。我们决定尝试一下,希望改善开发人员的体验。不幸的是,它遵循Golang链式代码中的相同模式,你仍然需要在日常逻辑中做一些肮脏的工作。我们一直在寻找更好的解决方案,并发现了一篇关于TheLedger的库的帖子,该文章在Typescript中制作Fabric链接代码,它真正改善了原始Javascript的内容。 在我们的智能合约从Golang迁移到Javascript期间出现了一种模式。大多数时候函数按以下顺序执行: 1.解析参数。2.做一些断言。3.执行更改。4.保存更改。这导致了关于项目计划的一个基本问题:智能合约是否应该快速迁移,或者应该花更多的时间来确定模式并使其足够灵活以适应多个业务案例。这一切都始于项目的./src/utils/。 /** @module @worldsibu/convector-examples-token */import * as yup from ‘yup’;import { ConvectorModel, ReadOnly, Required, Validate} from ‘@worldsibu/convector-core-model’;export class Token extends ConvectorModel { @ReadOnly() public readonly type = ‘io.worldsibu.examples.token’; @ReadOnly() @Required() @Validate(yup.object()) public balances: { [key: string]: number }; @ReadOnly() @Required() @Validate(yup.number().moreThan(0)) public totalSupply: number; @ReadOnly() @Required() @Validate(yup.string()) public name: string; @ReadOnly() @Required() @Validate(yup.string()) public symbol: string;}对流模型Fabric对区块链中存储的数据形状没有限制。你基本上有一个键值映射,其中两个都是字符串,这意味着你可以序列化和存储任何复杂的对象。我们拆开模型以在代码中重用它们。我们刚刚通过了所有必要的参数。 ...

April 25, 2019 · 1 min · jiezi

configtxyaml中文详解

configtx.yaml是Hyperledger Fabric区块链网络运维工具configtxgen用于生成通道创世块或通道交易的配置文件,configtx.yaml的内容直接决定了所生成的创世区块的内容。本文将给出configtx.yaml的详细中文说明。 如果需要快速掌握Fabric区块链的链码与应用开发,推荐访问汇智网的在线互动教程: Fabric区块链Java开发详解Fabric区块链NodeJS开发详解Capabilities / 通道能力配置Capabilities段用来定义fabric网络的能力。这是版本v1.0.0引入的一个新的配置段,当与版本v1.0.x的对等节点与排序节点混合组网时不可使用。 Capabilities段定义了fabric程序要加入网络所必须支持的特性。例如,如果添加了一个新的MSP类型,那么更新的程序可能会根据该类型识别并验证签名,但是老版本的程序就没有办法验证这些交易。这可能导致不同版本的fabric程序中维护的世界状态不一致。 因此,通过定义通道的能力,就明确了不满足该能力要求的fabric程序,将无法处理交易,除非升级到新的版本。对于v1.0.x的程序而言,如果在Capabilities段定义了任何能力,即使声明不需要支持这些能力,都会导致其有意崩溃。 Capabilities: # Global配置同时应用于排序节点和对等节点,并且必须被两种节点同时支持。 # 将该配置项设置为ture表明要求节点具备该能力 Global: &ChannelCapabilities V1_3: true # Orderer配置仅应用于排序节点,不需考虑对等节点的升级。将该配置项 # 设置为true表明要求排序节点具备该能力 Orderer: &OrdererCapabilities V1_1: true # Application配置仅应用于对等网络,不需考虑排序节点的升级。将该配置项 # 设置为true表明要求对等节点具备该能力 Application: &ApplicationCapabilities V1_3: trueOrganizations / 组织机构配置Organizations配置段用来定义组织机构实体,以便在后续配置中引用。例如,下面的配置文件中,定义了三个机构,可以分别使用ExampleCom、Org1ExampleCom和Org2ExampleCom引用其配置: Organizations: - &ExampleCom Name: ExampleCom ID: example.com AdminPrincipal: Role.ADMIN MSPDir: ./ordererOrganizations/example.com/msp Policies: Readers: Type: Signature Rule: OR('example.com.member') Writers: Type: Signature Rule: OR('example.com.member') Admins: Type: Signature Rule: OR('example.com.admin') Endorsement: Type: Signature Rule: OR('example.com.member') - &Org1ExampleCom Name: Org1ExampleCom ID: org1.example.com MSPDir: ./peerOrganizations/org1.example.com/msp AdminPrincipal: Role.ADMIN AnchorPeers: - Host: peer0.org1.example.com Port: 7051 Policies: Readers: Type: Signature Rule: OR('org1.example.com.member') Writers: Type: Signature Rule: OR('org1.example.com.member') Admins: Type: Signature Rule: OR('org1.example.com.admin') Endorsement: Type: Signature Rule: OR('org1.example.com.member') - &Org2ExampleCom Name: Org2ExampleCom ID: org2.example.com MSPDir: ./peerOrganizations/org2.example.com/msp AdminPrincipal: Role.ADMIN AnchorPeers: - Host: peer0.org2.example.com Port: 7051 Policies: Readers: Type: Signature Rule: OR('org2.example.com.member') Writers: Type: Signature Rule: OR('org2.example.com.member') Admins: Type: Signature Rule: OR('org2.example.com.admin') Endorsement: Type: Signature Rule: OR('org2.example.com.member')Orderer / 排序节点配置Orderer配置段用来定义要编码写入创世区块或通道交易的排序节点参数。 ...

April 25, 2019 · 4 min · jiezi

Ubuntu 18 部署 Hyperledger Fabric 1.4

安装 sshsudo apt-get updatesudo apt-get install ssh安装 Go下载Go源码下载 选择对应的平台下载。准备在下载的位置打开 terminal 。安装sudo tar -zxvf goxxxxx.tar.gz -C /usr/local, 建议 /usr/local 位置安装。配置sudo gedit /etc/profile, 追加以下配置到环境变量。export GOROOT=/usr/local/goexport GOPATH=~/code/gosave and exit.测试source /etc/profile 立即适应新环境输入 go version,成功查看版本信息杂表示配置成功。安装 Docker-CE前置工作sudo apt-get updatesudo apt-get install apt-transport-https ca-certificates curl software-properties-commoncurl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -sudo apt-get update安装 Dockersudo apt-get install docker-ce将当前用户添加到 Docker Group(支持不使用 sudo 执行 docker 命令)sudo usermod -aG docker bey测试docker run hello-world,正确输出结果如下:Hello from Docker!This message shows that your installation appears to be working correctly.To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the “hello-world” image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bashShare images, automate workflows, and more with a free Docker ID: https://hub.docker.com/For more examples and ideas, visit: https://docs.docker.com/get-started/安装 Docker-Compose下载最先版本的 Docker Composesudo curl -L https://github.com/docker/compose/releases/download/1.24.0-rc1/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-compose给二进制文件添加执行权sudo chmod +x /usr/local/bin/docker-compose查看版本docker-compose -v下载 fabric 及其镜像go get可以的话,直接 go get 获取 go get github.com/hyperledger/fabric,如果 go get 命令无法执行,再试试 Gitgit clone创建目录 mkdir -p $GOPATH/src/github.com/hyperledger/,进入目录 cd $GOPATH/src/github.com/hyperledger/克隆 fabric git clone https://github.com/hyperledger/fabric.git,下载完成后,进入 fabric 文件夹切换 1.4 版本(可选)git checkout v1.4.0生成 fabric-tools下载 fabric-samplecd $GOPATH/src/github.com/hyperledger/fabric/scripts./bootstrap.sh该脚本运行时间较长,主要是在下载 fabrice 各个组件的 docker 镜像将 fabric-tools 复制到 usr/local/bin 目录cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/binsudo cp -r . /usr/local/bin这样就可以到处使用 fabric-tools 了。测试cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network./byfn.sh down./byfn.sh up看到如下信息表示部署成功,恭喜!========= All GOOD, BYFN execution completed =========== _____ _ _ ____ | | | \ | | | _ \ | | | | | | | | | | | | |\ | | || | |_____| || _| |____/ ...

April 9, 2019 · 2 min · jiezi

用VSCode和IBM Hyperledger Fabric 区块链扩展开发智能合约

了解使用IBM Blockchain Platform的VSCode扩展来简化开发,测试和部署智能合约的过程。完成本教程后,你将了解如何使用VSCode在本地Hyperledger Fabric网络上快速开发,演示和部署区块链应用程序。本教程假设你对Hyperledger Fabric有一些基本的了解。学习目标安装IBM Blockchain Platform VSCode扩展。创建一个新的JavaScript智能合约。打包智能合约。创建,探索和了解Hyperledger Fabric网络。在本地Hyperledger Fabric实例上部署智能合约。使用Node.js SDK与已部署的智能合约包进行交互。先决条件你需要安装以下内容才能使用扩展程序:node v8.x或更高版本以及npm v5.x或更高版本。Yeoman(yo) v2.x。Docker版本v17.06.2-ce或更高版本。Docker Compose v1.14.0或更高版本。VSCode 1.28.2或更高版本。如果你使用的是Windows,则还必须确保以下内容:你的Windows版本支持Hyper-V和Docker:Windows 10 Enterprise,Pro或具有1607 Anniversary更新或更高版本的教育版。Docker for Windows配置为使用Linux容器(这是默认设置)。你已经从windows-build-tools安装了适用于Windows的C ++ Build Tools。你已从Win32 OpenSSL安装了OpenSSL v1.0.2安装正常版本,而不是标记为light的版本。在32位系统上将Win32版本安装到C:OpenSSL-Win32中。在64位系统上将Win64版本安装到C:OpenSSL-Win64中。你可以通过从终端运行以下命令来检查已安装的版本:node –versionnpm –versionyo –versiondocker –versiondocker-compose –version预计的时间安装必备组件后,大约需要30-45分钟才能完成。步骤:1.开始2.创建一个新的智能合约项目3.修改智能合约4.打包智能合约5.安装智能合约6.实例化智能合约7.导出连接详细信息8.提交交易9.更新智能合约10.提交更多交易11.查询分类帐12.测试合约1.开始你需要做的第一件事是安装IBM Blockchain Platform VSCode扩展。为此,你需要安装最新版本的VSCode;要查看你是否拥有最新的VSCode扩展,请转到代码>检查更新(Code > Check for Updates)。如果此时VSCode崩溃(我遇到了),则可能意味着你没有最新版本。如果你的VSCode崩溃,请查看下面的故障排除部分。否则,请更新你的VSCode,完成后,单击屏幕左侧边栏中的扩展名。在顶部,在扩展市场中搜索IBM Blockchain Platform。单击Install,然后单击reload。现在你应该全部使用扩展!2.创建一个新的智能合约项目要创建智能合约项目:1.单击新下载的IBM Blockchain Platform扩展。它应该是左侧边栏底部的一直延伸。2.接下来,使用键盘快捷键Shift+CMD+P调出命令pallete。从下拉列表中选择IBM Blockchain Platform:Create Smart Contract Project。3.点击下拉列表中的JavaScript。4.单击新建文件夹New Folder,然后将项目命名为所需名称。我将我的名字命名为demoContract。5.单击创建Creat,然后Open刚刚创建的新文件夹。接下来,从下拉列表中单击添加到工作区Add to WrokSpace。6.完成扩展打包合约后,你可以打开lib/my-contract.js文件以查看智能合约代码框架。不错的工作!3.修改智能合约在lib/my-contract.js文件中,继续复制并粘贴以下代码:‘use strict’;const { Contract } = require(‘fabric-contract-api’);class MyContract extends Contract { //update ledger with a greeting to show that the function was called async instantiate(ctx) { let greeting = { text: ‘Instantiate was called!’ }; await ctx.stub.putState(‘GREETING’, Buffer.from(JSON.stringify(greeting))); } //take argument and create a greeting object to be updated to the ledger async transaction1(ctx, arg1) { console.info(’transaction1’, arg1); let greeting = { text: arg1 }; await ctx.stub.putState(‘GREETING’, Buffer.from(JSON.stringify(greeting))); return JSON.stringify(greeting); }}module.exports = MyContract;注意:.gifs可能与上面的智能合约不完全匹配,但这是你现在应该在lib/my-contract.js文件中应该拥有的那个!让我们来看看你刚刚定义的函数。实例化函数创建一个greeting对象,然后使用密钥GREETING将其存储在分类帐中。transaction1函数采用Hyperledger Fabric上下文和一个参数arg1,该参数用于存储用户定义的问候语。ctx.stub.putState方法用于记录分类帐上的greeting,然后返回该对象。保存文件然后继续!4.打包智能合约现在你已经创建了智能合约并了解了你已定义的功能,现在可以将其打包,以便你可以将其安装在节点设备上。使用Shift+CMD+P打开命令pallete并选择包智能合约。在左侧边栏中,单击IBM Blockchain Platform图标(它看起来像一个正方形)。在左上角,你将看到所有智能合约包。如果一切顺利,你应该看到demoContract@0.0.1。5.安装智能合约好的,你已经完成超过一半了。现在是有趣的部分!让我们在节点上安装这份合约!为此,你必须首先连接到Hyperledger Fabric网络。VSCode扩展附带的网络非常适合开发,它为开发和测试合约提供了最少的资源占用。以下Docker容器在本地计算机上启动,每个容器在网络中具有不同的角色:Orderer,Certificate Authority,CouchDB和Peer。要启动网络,请单击编辑器左侧的IBM Blockchain Platform扩展。这是一个看起来像正方形的图标。1.单击扩展后,你应该在编辑器的左侧看到LOCAL FABRIC OPS。在LOCAL FABRIC OPS右侧,你应该看到一个三点符号。单击该按钮,然后单击启动Fabric运行时Start Fabric Runtime。你的扩展程序现在将提供将充当网络中节点的Docker容器。配置完成后,你应该会看到LOCAL FABRIC OPS下的智能合约Smart Contracts部分。2.在智能合约Smart Contracts下,单击+install。3.接下来,扩展程序将询问你在哪个节点上安装智能合约。选择peer0.org1.examplee.com。4.扩展程序将询问你要安装哪个软件包:选择demoContract@0.0.1。如果一切顺利,你应该会在右下角看到通知:已成功安装在节点peer0.org1.example.com上就是这样!不错的工作!6.实例化智能合约这是真正的考验,你的智能合约是否会正确实例化?我们来看看……1.在智能合约Smart Contracts下,你将看到一个显示实例化的部分。单击实例化+ Instantiate。2.然后,扩展将询问你在哪个频道实例化智能合约,选择mychannel。3.然后,扩展将询问你实例化哪个合约和版本,选择demoContract@0.0.1。4.然后,扩展将询问你要调用哪个函数,输入instantiate。5.接下来,它会询问你的参数。没有,所以只需按回车即可。扩展将执行一些工作,然后在右下角,你应该看到合约已成功实例化。万岁!7.导出连接详细信息此时,你需要开始与Fabric实例进行更密切的交互。你需要向证书颁发机构证明你可以在网络上创建数字身份。这是通过向证书颁发机构显示你的证书和私钥来完成的。1.在本教程的后面,我们将查询网络。为此,我们需要一些脚本。在你的智能合约目录之外克隆此Github Repo,以获取查询网络所需的必要脚本。$ git clone https://github.com/horeaporutiu/VSCodeTutorialBlockchain.git2.右键单击VSCode中智能合约目录下的空白区域,然后选择将文件夹添加到工作区Add folder to workspace,将此文件夹导入VSCode工作区。找到最近克隆的文件夹VSCodeTutorialBlockchain并双击它。3.在VSCode中,单击左侧栏中的IBM Blockchain Platform扩展。4.在LOCAL FABRIC OPS下点击Nodes。右键单击peer0.org1.example.com节点。选择导出连接细节Export Connection Details。5.扩展程序将询问将连接配置文件保存到哪个文件夹。选择VSCodeTutorialBlockchain目录。如果一切顺利,你应该看到类似的东西:Successfully exported connection details to /Users/Horea.Porutiu@ibm.com/Workdir/VSCodeTutorialBlockchain/local_fabric8.提交交易好的,所以你已经实例化你的合约,把我们的密钥输出到我们的钱包里,那么现在呢? 那么,现在是时候实际调用智能合约中的功能了!为此,你可以使用VSCode扩展。1.在LOCAL FABRIC OPS下你应该看到FABRIC GATEWAYS。2.单击local_fabric,然后单击Admin@org1.example.com。3.如果一切顺利,你应该会看到一条通知,其中显示正在连接到fabricConnecting to local_fabric。4.接下来,在FABRIC GATEWAYS和Channels下你应该看到我的mychannel。单击以展开它。然后展开demoContract@0.0.1。你应该看到两个函数,instantiate和transaction1。5.右键单击transaction1,然后选择提交交易submit transaction。对于参数,请输入’hello’。不错的工作!你刚刚成功向Fabric网络提交了一笔交易,并更新了分类帐!9.更新智能合约在上一步中,你使用putState API更新了分类帐,并传入了密钥和值。key恰好是greeting,值也赋予了对象。{ text: ‘hello’}你应该学习的最后一件事是如何查询,如何从分类帐中检索数据。你将通过使用getState API执行此操作,该API接收密钥并返回与该密钥关联的值(如果找到它)。让我们为demoContract添加一个查询功能。1.将以下代码复制并粘贴到lib/my-contract.js文件中:‘use strict’;const { Contract } = require(‘fabric-contract-api’);class MyContract extends Contract { //update ledger with a greeting async instantiate(ctx) { let greeting = { text: ‘Instantiate was called!’ }; await ctx.stub.putState(‘GREETING’, Buffer.from(JSON.stringify(greeting))); } //add a member along with their email, name, address, and number该代码添加了一个addMember函数,该函数接收来自用户的参数,如电子邮件,姓名,地址和电话号码,并将该数据作为键值对保存在分类帐中。此代码还添加了查询功能; 这个函数接受一个参数,这是查找的关键。该函数返回与给定键关联的值(如果有)。2.更新package.json文件,使包含版本号的第3行现在读取: “version”: “0.0.2”,保存文件。3.要在LOCAL FABRIC OPS下将你现有的智能合约升级到新版本。展开实例化,直到你看到demoContract@0.0.1。接下来,右键单击demoContract并选择Upgrade Smart Contract。4.扩展程序将询问使用哪个版本执行升级。选择demoContract。5.扩展程序将询问哪个节点安装智能合约,请选择peer0.org1.example.com。6.扩展程序将询问要调用的函数。输入实例化instantiate。7.扩展名将询问要传递的参数。将其留空,然后按Enter键。经过一些繁重的计算(以及一点点时间),如果一切顺利,你应该在右下角收到一条通知说成功升级智能合约Successfully upgraded smart contract。10.提交更多交易现在你已经更新了智能合约,请在FABRIC GATEWAYS下查看并展开频道Channels。接下来,展开mychannel,你应该看到demoContract@0.0.2。1.接下来,展开demoContract@0.0.2以查看已更新智能合约my-contract.js的函数,即instantiate,addMember和query。2.右键单击addMember,然后单击Submit Transaction。对于参数,请复制并粘贴以下内容:ginny@ibm.com, Ginny Rometty, Wall Street NY, 1234567890在输出中,你应该看到以下内容:Submitting transaction addMember with args Ginny Rometty, Wall Street NY, 1234567890, ginny@ibm.com让我们再添加一个成员,重复此步骤,但是对于参数,请复制并粘贴以下内容:arvind@ibm.com, Arvind Krishna, Broadway Street NY, 1231231111不错的工作。 我们差不多完成了!11.查询分类帐而现在,你们一直都在等待…让我们真正看到写在分类账上的内容!为此,我们将使用VSCodeTutorialBlockchain文件夹中的query.js文件。1.查看VSCodeTutorialBlockchain目录中的query.js文件。它与invoke.js文件非常相似,只是它有一个主要区别:let response = await contract.evaluateTransaction(‘query’, ‘GREETING’);主要区别在于,在此文件中,你将使用evaluateTransaction API,它不会将交易发送到ordering服务。因此,它不会更新分类帐。这是非常重要的。在invoke.js文件中,你将交易提交到ordering服务,这些交易都将写入分类帐,但在query.js文件中,你不会更新分类帐。2.使用VSCode中的终端导航到VSCodeTutorialBlockchain文件夹。从那里,使用以下命令安装所需的依赖项:VSCodeTutorialBlockchain $ npm install3.接下来,使用以下命令运行query.js:VSCodeTutorialBlockchain$ node query.js你应该看到下面的输出:Connected to Fabric gateway.{ text: ‘Instantiate was called!’ }Disconnect from Fabric gateway.done4.接下来,查询Ginny Rometty。更改以下行:let response = await contract.evaluateTransaction(‘query’, ‘GREETING’);对此:let response = await contract.evaluateTransaction(‘query’, ‘ginny@ibm.com’);你应该看到下面的输出:VSCodeTutorialBlockchain$ node query.jsConnected to Fabric gateway.{“address”:" Wall Street NY",“email”:“ginny@ibm.com”,“name”:" Ginny Rometty",“number”:" 1234567890"}Disconnect from Fabric gateway.done5.最后,查询Arvind。修改请求如下:let response = await contract.evaluateTransaction(‘query’, ‘arvind@ibm.com’);除了Arvind的数据外,输出应该类似于上面的输出。12.测试合约测试功能是IBM Blockchain扩展的一项功能,可以通过UI完成。单击左侧的IBM Blockchain Platform扩展图标。在FABRIC GATEWAYS下,在频道Channels下展开mychannel,右键单击最新的智能合约demoContract@0.0.2,然后选择Generate Smart Contract Tests。扩展程序将询问你生成测试文件的语言。选择JavaScript。生成测试完成扩展后,你可以从demoContract目录运行npm test,也可以从MyContract-demoContract@0.0.2.test.js文件中单击VSCode UI中的运行测试按钮,如gif所示。总结干得好!你学习了如何使用Hyperledger的最新API创建,打包,安装,实例化和调用智能合约。此时,你可以专注于开发智能合约并更新my-contract.js文件,因为你知道已经处理了区块链的网络方面。你还可以使用VSCode,Node.js和Docker成功调用和更新分类帐。如果有错误,请拜托我,请对这篇文章发表评论,我会修复它们。非常感谢你阅读本教程。我希望你喜欢它!Horea Blockchain出来了!======================================================================分享一些比特币、以太坊、EOS、Fabric等区块链相关的交互式在线编程实战教程:java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。c#比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在C#代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是C#工程师不可多得的比特币开发学习课程。java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。ERC721以太坊通证实战,课程以一个数字艺术品创作与分享DApp的实战开发为主线,深入讲解以太坊非同质化通证的概念、标准与开发方案。内容包含ERC-721标准的自主实现,讲解OpenZeppelin合约代码库二次开发,实战项目采用Truffle,IPFS,实现了通证以及去中心化的通证交易所。C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。EOS入门教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。深入浅出玩转EOS钱包开发,本课程以手机EOS钱包的完整开发过程为主线,深入学习EOS区块链应用开发,课程内容即涵盖账户、计算资源、智能合约、动作与交易等EOS区块链的核心概念,同时也讲解如何使用eosjs和eosjs-ecc开发包访问EOS区块链,以及如何在React前端应用中集成对EOS区块链的支持。课程内容深入浅出,非常适合前端工程师深入学习EOS区块链应用开发。Hyperledger Fabric 区块链开发详解,本课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、nodejs链码与应用开发的操作实践,是Nodejs工程师学习Fabric区块链开发的最佳选择。Hyperledger Fabric java 区块链开发详解,课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、java链码与应用开发的操作实践,是java工程师学习Fabric区块链开发的最佳选择。tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。汇智网原创翻译,转载请标明出处。这里是Hyperledger Fabric和VSCode的IBM区块链扩展开发智能合约 ...

April 4, 2019 · 2 min · jiezi

Hyperledger Fabric 区块链开发详解

Hyperledger是一个旨在推动区块链跨行业应用的开源项目,由Linux基金会在2015年12月主导发起该项目,成员包括金融、银行、物联网、供应链、制造和科技等多个行业的领头羊,托管了众多面向企业的区块链开源框架和工具。Hyperledger及Fabric项目概述Hyperledger Fabric(后文简称Fabric)是其中发展最好的一个企业级区块链平台,最初由Digital Asset和IBM贡献,目前已经应用于沃尔玛的食物溯源链(Foodtrust)和马士基的物流跟踪链(TradeLens)中,代表了当下企业级区块链应用的最高水平。可以认为Fabric是一种联盟链(Consortium Blockchain)平台,它适合构建跨越多个企业边界的去中心化应用。由于Fabric项目的目标是应用于相对可信的企业联盟环境,因此其设计思路与比特币、以太坊等公链平台有明显的差异。Fabric借鉴了区块链的数据结构,但引入了相当多的身份验证与权限控制机制,以及数据隐私保护机制,以适应企业级应用的要求。同时由于企业联盟环境要比完全开放的公链环境可控,因此Fabric没有强调其共识体系对拜占庭容错的实现,允许使用 非拜占庭容错算法建立共识,从而可以达到相当实用的交易吞吐量。Fabric的定位与特点毫无疑问,Fabric是受到比特币的启发而诞生的,因此它借鉴了比特币、以太坊这些公链中的一些核心特性,例如采用不可篡改的区块链结构来保存数据、采用非对称加密技术来进行身份识别 与认证、支持智能合约等等。但是Fabric定位于企业级的分布式账本技术(DLT - Distributed Ledger Technology)平台,它的主要目的是为跨越多个企业边界的活动提供不可篡改的分布式记账平台。例如在食物溯源应用中,为了让消费者可以了解到所购买食物是否安全,就必须将从农场到加工商、分销商、 零售商乃至监管机构等各个环节的检验与放行信息记录到区块链上,以保证溯源信息的透明与可信。因此Fabric是一种联盟链(Consortium Blockchain),它适合在多个企业间实现分布式记账,这一定位使Fabric的实现与以太坊这样的公链有了明显的差异:分布式账本 vs. 区块链分布式账本是比区块链更加宽泛的概念,可以认为区块链只是分布式账本的一种实现技术,其他的分布式账本实现还包括哈希图等。去中心化 vs. 分布式Fabric淡化了去中心化(Decentralized),而以分布式(Distributed)代替,这一思路带来了系统设计与实现上的巨大影响。例如,在Fabric中,采用中心化的CA机制来发放证书,只有持有有效证书的节点和用户才可以访问区块链上的账本数据。因此Fabric是许可制/Permissioned的区块链,这与不需要许可/Permissionless的以太坊这样的公链形成了鲜明的对比。拜占庭容错 vs. 崩溃容错由于采用许可机制,Fabric也淡化了对不可信(Trustless)环境下共识达成的依赖性,而假设联盟链中的企业有可能是值得信赖的,因此并不依赖于工作量证明这样的拜占庭容错算法,虽然Fabric模块化的设计可以支持引入不同的共识算法实现,但目前的产品化方案是Kafka共识,它显然是不能对抗拜占庭错误的,不过对不可信环境支持的淡化处理有利于提高交易的吞吐量,这对于企 业级应用也是有益的。数据隐私保护在另一方面,Fabric强化了隐私保护能力。例如,Fabric支持在同一套企业网络上建立多个不同的通道/Channel,每一个通道都有自己的区块链和访问控制,彼此互不影响,这有利于复用基础设施,例如不同企业间的销售部门可以建立一个通道来分享市场数据,而这些企业间的 研发部门可以建立另一个通道来分享技术数据。Fabric并不是唯一的联盟链解决方案,但目前可以说是最复杂的企业联盟链实现,这种复杂性源于设计者对应用场景的假设和推演,以及对Fabric广泛适用性的考量,这是我们在学习过程中需要换位思考的一点。课程内容概述本课程适合nodejs开发人员快速掌握超级账本Fabric区块链的设计思路、 核心概念、网络搭建、链码及应用开发等知识点,课程主要内容简述如下:第一章、课程概述简介Fabric项目来源、定位特点、适用场景以及其与公链平台的重要区别。第二章、初识Fabric创建一个最小CA,搭建一个最小Farbic网络,开发一个最小Fabric链码,实现一个最小Fabric应用,从零开始学习并掌握Farbic中的核心概念、设计思路、实用工具与开发模型。第三章、身份与权限管理机制深入学习Fabric中的身份验证机制与权限管理机制,理解证书、成员服务提供器、 策略、访问控制清单等核心概念并掌握其创建、部署和使用方法。第四章、通道配置与更新深入学习Fabric的通道配置初始化与更新流程、相关数据结构以及配置工具的操作方法。第五章、链码开发进阶学习理解链码运行机制、掌握状态历史跟踪、富查询、Contract API等链码开发进阶知识。第六章、应用开发进阶学习掌握通道事件监听、Network API等应用开发进阶知识。希望尽快学习课程的请访问:Hyperledger Fabric Node.js 区块链开发详解Hyperledger Fabric java 区块链开发详解

March 29, 2019 · 1 min · jiezi

基于Hyperledger Fabric交易系统帐户的钱包模型的java Chaincode实例

这是Hyperledger Fabric Java Chaincode的教程。还有Go和NodeJS Chaincodes,我们将来可能会讨论它们。此外,我采用基于帐户的钱包模型作为示例,我们将使用Hyperledger Fabric构建你的第一个网络(BYFN,build your first network),作为我们的测试环境(v1.4网络)。如果你不知道如何启动BYFN网络,我也会提供步骤,不用担心。但是如果你想了解BYFN是如何工作的,你可以参考:1.Hyperledger Fabric官方BYFN教程2.我之前关于BYFN的文章基于帐户的钱包模型基于帐户的钱包模型是交易系统的实现之一,一般而言系统中存在一些钱包,并且每个钱包包含可用于转账的一些值或代币。当然,实现的细节有很多变化,例如代币交换和多代币功能。特征在Java Chaincode中,我们将实现:1.用户钱包创建。2.用户钱包查询。3.钱包代币转账(即从一个钱包发送钱或代币到另一个钱包)。[可选] Hyperledger Fabric中有两个数据库选项用于保存超级账本的world state:LevelDB和CouchDB,在本教程中,为了简单起见,我将使用LevelDB。[可选]在上面,world state(或全局状态)不是超级账本本身,而是与超级账本分开,虽然它是派生的,可以随时从超级账本中恢复。此外,世界状态存储在数据库中以表示超级账本,使得这些节点不需要总是搜索超级账本以进行数据检索,并且可以更快地从数据库中检索数据(状态)。[可选]在我的负载测试和一些关于Hyperledger Fabric性能的论文中,LevelDB的性能优于CouchDB。但与LevelDB中的简单键值查询相比,CouchDB可以支持可用于构建更复杂查询的丰富查询。IDE——Java Chaincode开发工具我们使用IntelliJ IDEA。此外,你需要JDK。请安装它们。当然,如果你有自己的Java IDE,也可以使用它。但在本教程中,我们使用IntelliJ。第1步,准备开发让我们打开IntelliJ。在IntelliJ中创建新项目Create New Project:选择左边的Gradle,然后:输入你的GroupId和ArtifactId。就我而言,我使用java_account_model_cc。接下来:然后现在,你应该配置自己的项目位置。就我而言,我使用/Desktop/java_account_model_cc。单击完成Finish。1.1 settings.gradle在左侧的项目文件中,你应该看到settings.gradle。让我们双击打开它:输入以下内容:rootProject.name = ‘fabric-chaincode-gradle'1.2 build.gradle在左侧的项目文件面板中,可以看到build.gradle。让我们双击打开它:然后,输入以下内容:plugins { id ‘com.github.johnrengelman.shadow’ version ‘2.0.3’ id ‘java’}group ‘org.hyperledger.fabric-chaincode-java’version ‘1.0-SNAPSHOT’sourceCompatibility = 1.8repositories { mavenLocal() mavenCentral()}dependencies { compile group: ‘org.hyperledger.fabric-chaincode-java’, name: ‘fabric-chaincode-shim’, version: ‘1.+’ compile group: ‘com.fasterxml.jackson.core’, name: ‘jackson-databind’, version: ‘2.9.6’ testCompile group: ‘junit’, name: ‘junit’, version: ‘4.12’}shadowJar { baseName = ‘chaincode’ version = null classifier = null manifest { attributes ‘Main-Class’: ‘org.hyperledger.fabric.chaincode.AccountBasedChaincode’ }}如果IntelliJ右下角有一个需要导入的Gradle项目Gradle project needs to be imported的弹出窗口,请选择导入更改Import Changes。1.3 Chaincode文件在左侧的项目文件面板中,在src>main>java下,右键单击它并选择New>Java Class:在Name字段中输入org.hyperledger.fabric.chaincode.AccountBasedChaincode:然后,应该看到以下内容:上面的AccountBasedChaincode(.java)是我们在Java中编写Chaincode的地方。第2步——需求分析在我们开始编码之前,让我们组织我们需要编码的内容。如特性部分所述,在Java Chaincode中,我们将实现:1.用户钱包创建2.用户钱包查询3.钱包代币转账(即从一个钱包向另一个钱包汇款)从上面这个简单的要求,我们需要有以下类:1.钱包类2.Chaincode类——拥有Chaincode我们的Chaincode应该提供以下功能:1.创建一个钱包。2.将代币从一个钱包转账到另一个钱包。3.获取(查询)钱包。4.Init函数,在实例化Chaincode时调用。5.Invoke函数,当用户想要调用函数(1)(2)或(3)时调用。Init函数必须在Chaincode中实现,并且每当我们实例化或升级Chaincode时都会自动调用。通常,它用于初始化区块链中的一些数据。Invoke函数用于接收所有用户函数调用,然后根据Invoke调用(调用)相应的函数(1)(2)或(3)。它就像一个路由器 ,将传入的请求路由到不同的路径。第3步——钱包类现在,我们创建并编写Wallet类。在org.hyperledger.fabric.chaincode下创建一个新包:调用模型包Models,然后确定:应该可以看到:在Models包下,创建一个新的Java类并将其命名为Wallet。(这次我没有详细说明,让大家自己尝试)现在我们为wallet类编码:package org.hyperledger.fabric.chaincode.Models;public class Wallet { private String walletId; private Double tokenAmount; public Wallet(String walletId, Double tokenAmount) { this.walletId = walletId; this.tokenAmount = tokenAmount; } private Wallet() {} public String getWalletId() { return walletId; } public Double getTokenAmount() { return tokenAmount; } public void setWalletId(String walletId) { this.walletId = walletId; } public void setTokenAmount(Double tokenAmount) { this.tokenAmount = tokenAmount; }}钱包具有用于识别特定钱包的wallet id和用于指定钱包拥有多少代币的数量。请注意,在生产案例中,Wallet类应该更复杂。例如,你可能对tokenAmount使用BigDecimal数据类型而不是Double。此外,在我们的例子中,我们在整个交易系统中只支持一种代币类型(即只有一种代币)。第4步——Chaincode类package org.hyperledger.fabric.chaincode;import java.util.List;import org.hyperledger.fabric.chaincode.Models.Wallet;import org.hyperledger.fabric.shim.ChaincodeBase;import org.hyperledger.fabric.shim.ChaincodeStub;import com.fasterxml.jackson.databind.ObjectMapper;public class AccountBasedChaincode extends ChaincodeBase { private class ChaincodeResponse { public String message; public String code; public boolean OK; public ChaincodeResponse(String message, String code, boolean OK) { this.code = code; this.message = message; this.OK = OK; } } private String responseError(String errorMessage, String code) { try { return (new ObjectMapper()).writeValueAsString(new ChaincodeResponse(errorMessage, code, false)); } catch (Throwable e) { return “{"code":’” + code + “’, "message":’” + e.getMessage() + " AND " + errorMessage + “’, "OK":” + false + “}”; } } private String responseSuccess(String successMessage) { try { return (new ObjectMapper()).writeValueAsString(new ChaincodeResponse(successMessage, “”, true)); } catch (Throwable e) { return “{"message":’” + e.getMessage() + " BUT " + successMessage + " (NO COMMIT)’, "OK":" + false + “}”; } } private String responseSuccessObject(String object) { return “{"message":” + object + “, "OK":” + true + “}”; } private boolean checkString(String str) { if (str.trim().length() <= 0 || str == null) return false; return true; } @Override public Response init(ChaincodeStub stub) { return newSuccessResponse(responseSuccess(“Init”)); } @Override public Response invoke(ChaincodeStub stub) { String func = stub.getFunction(); List<String> params = stub.getParameters(); if (func.equals(“createWallet”)) return createWallet(stub, params); else if (func.equals(“getWallet”)) return getWallet(stub, params); else if (func.equals(“transfer”)) return transfer(stub, params); return newErrorResponse(responseError(“Unsupported method”, “”)); } private Response createWallet(ChaincodeStub stub, List<String> args) { if (args.size() != 2) return newErrorResponse(responseError(“Incorrect number of arguments, expecting 2”, “”)); String walletId = args.get(0); String tokenAmount = args.get(1); if (!checkString(walletId) || !checkString(tokenAmount)) return newErrorResponse(responseError(“Invalid argument(s)”, “”)); double tokenAmountDouble = 0.0; try { tokenAmountDouble = Double.parseDouble(tokenAmount); if(tokenAmountDouble < 0.0) return newErrorResponse(responseError(“Invalid token amount”, “”)); } catch (NumberFormatException e) { return newErrorResponse(responseError(“parseInt error”, “”)); } Wallet wallet = new Wallet(walletId, tokenAmountDouble); try { if(checkString(stub.getStringState(walletId))) return newErrorResponse(responseError(“Existent wallet”, “”)); stub.putState(walletId, (new ObjectMapper()).writeValueAsBytes(wallet)); return newSuccessResponse(responseSuccess(“Wallet created”)); } catch (Throwable e) { return newErrorResponse(responseError(e.getMessage(), “”)); } } private Response getWallet(ChaincodeStub stub, List<String> args) { if (args.size() != 1) return newErrorResponse(responseError(“Incorrect number of arguments, expecting 1”, “”)); String walletId = args.get(0); if (!checkString(walletId)) return newErrorResponse(responseError(“Invalid argument”, “”)); try { String walletString = stub.getStringState(walletId); if(!checkString(walletString)) return newErrorResponse(responseError(“Nonexistent wallet”, “”)); return newSuccessResponse((new ObjectMapper()).writeValueAsBytes(responseSuccessObject(walletString))); } catch(Throwable e){ return newErrorResponse(responseError(e.getMessage(), “”)); } } private Response transfer(ChaincodeStub stub, List<String> args) { if (args.size() != 3) return newErrorResponse(responseError(“Incorrect number of arguments, expecting 3”, “”)); String fromWalletId = args.get(0); String toWalletId = args.get(1); String tokenAmount = args.get(2); if (!checkString(fromWalletId) || !checkString(toWalletId) || !checkString(tokenAmount)) return newErrorResponse(responseError(“Invalid argument(s)”, “”)); if(fromWalletId.equals(toWalletId)) return newErrorResponse(responseError(“From-wallet is same as to-wallet”, “”)); double tokenAmountDouble = 0.0; try { tokenAmountDouble = Double.parseDouble(tokenAmount); if(tokenAmountDouble < 0.0) return newErrorResponse(responseError(“Invalid token amount”, “”)); } catch (NumberFormatException e) { return newErrorResponse(responseError(“parseDouble error”, “”)); } try { String fromWalletString = stub.getStringState(fromWalletId); if(!checkString(fromWalletString)) return newErrorResponse(responseError(“Nonexistent from-wallet”, “”)); String toWalletString = stub.getStringState(toWalletId); if(!checkString(toWalletString)) return newErrorResponse(responseError(“Nonexistent to-wallet”, “”)); ObjectMapper objectMapper = new ObjectMapper(); Wallet fromWallet = objectMapper.readValue(fromWalletString, Wallet.class); Wallet toWallet = objectMapper.readValue(toWalletString, Wallet.class); if(fromWallet.getTokenAmount() < tokenAmountDouble) return newErrorResponse(responseError(“Token amount not enough”, “”)); fromWallet.setTokenAmount(fromWallet.getTokenAmount() - tokenAmountDouble); toWallet.setTokenAmount(toWallet.getTokenAmount() + tokenAmountDouble); stub.putState(fromWalletId, objectMapper.writeValueAsBytes(fromWallet)); stub.putState(toWalletId, objectMapper.writeValueAsBytes(toWallet)); return newSuccessResponse(responseSuccess(“Transferred”)); } catch(Throwable e){ return newErrorResponse(responseError(e.getMessage(), “”)); } } public static void main(String[] args) { new AccountBasedChaincode().start(args); }}请注意,在生产案例中,代码应与我的不同。这些代码主要用于演示或教程目的。第5步——在BYFN中运行Chaincode5.1 安装相关项目我们在本教程中使用Hyperledger Fabric v1.4。首先,你可以按照官方说明安装相关项目:1.安装依赖项目2.从Hyperledger Fabric安装示例,程序和docker镜像5.2 Chaincode准备然后,让我们切换到这个目录(假设你完成了上面安装相关项目部分,你应该拥有所有需要的文件和目录):cd fabric-samples/chaincode/chaincode_example02/mv java java_01mkdir java现在,将项目目录中的以下突出显示的文件复制到fabric-samples/chaincode/chaincode_example02/java/:5.3 建立网络cd ../../first-network./byfn.sh up -l java运行此脚本后,可能需要等待片刻……如果你看到以下错误(而不是其他错误),那就OKAY,继续执行下一步骤!!!!!!!!!!!!!!! Query result on peer0.org1 is INVALID !!!!!!!!!!!!!!!!================== ERROR !!! FAILED to execute End-2-End Scenario ==================另外,在运行上面的命令之前,请记住启动Docker。如果你做错了什么,可以运行以下命令关闭网络,然后重新启动:./byfn.sh down./byfn.sh up -l java现在,我们测试我们的Chaincode是否有效。5.4 访问Cli有一个自动创建的cli Docker容器,它是一个控制节点的命令行界面。让我们访问cli:docker exec -it cli bash然后,设置某些程序使用的环境变量:export CHANNEL_NAME=mychannelexport CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_ADDRESS=peer0.org1.example.com:7051export CORE_PEER_LOCALMSPID=“Org1MSP"export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt你可以复制所有这些,然后粘贴到你的终端并按enter。这些环境变量用于让一些Hyperledger Fabric程序知道我们需要使用peer0.org1.example.com:7051来调用Chaincode函数。现在,我们创建了两个带有钱包ID的钱包,tom和sam:peer chaincode invoke -o orderer.example.com:7050 –tls true –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc –peerAddresses peer0.org1.example.com:7051 –tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt –peerAddresses peer0.org2.example.com:7051 –tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c ‘{“Args”:[“createWallet”,“tom”,“100”]}‘peer chaincode invoke -o orderer.example.com:7050 –tls true –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc –peerAddresses peer0.org1.example.com:7051 –tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt –peerAddresses peer0.org2.example.com:7051 –tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c ‘{“Args”:[“createWallet”,“sam”,“100”]}‘运行上面的每个命令后,你应该在终端中看到类似的内容:2019-02-09 16:56:55.617 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 message:”{"message":"Wallet created","code":"","OK":true}" 现在,我们获得上面创建的两个钱包来验证它们是否存在于区块链中:peer chaincode query -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“getWallet”,“tom”]}‘peer chaincode query -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“getWallet”,“sam”]}‘运行上面的每个命令后,您应该在终端中看到类似的内容:"{"message":{"walletId":"tom","tokenAmount":100.0}, "OK":true}""{"message":{"walletId":"sam","tokenAmount":100.0}, "OK":true}“在上面,我们可以看到之前创建的两个钱包可以被查询。他们都有100个代币。接下来,我们进行转账交易,让我们将10个代币从tom钱包转移到sam钱包:peer chaincode invoke -o orderer.example.com:7050 –tls true –cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc –peerAddresses peer0.org1.example.com:7051 –tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt -c ‘{“Args”:[“transfer”,“tom”,“sam”,“10”]}‘最后,让我们再次验证两个钱包:peer chaincode query -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“getWallet”,“tom”]}‘peer chaincode query -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“getWallet”,“sam”]}‘你能看到下面的结果:”{"message":{"walletId":"tom","tokenAmount":90.0}, "OK":true}""{"message":{"walletId":"sam","tokenAmount":110.0}, "OK":true}“请注意,现在Tom的钱包仍然是90个令牌,而Sam的钱包有110个令牌,交易已完成并写入区块链超级账本中。第6步——清理exit./byfn.sh down然后,删除目录fabric-samples/chaincode/chaincode_example02/java并将目录java_01重命名为java。谢谢!如果你喜欢我的内容,请关注我学习最新内容!======================================================================分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、帐户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。ERC721以太坊通证实战,课程以一个数字艺术品创作与分享DApp的实战开发为主线,深入讲解以太坊非同质化通证的概念、标准与开发方案。内容包含ERC-721标准的自主实现,讲解OpenZeppelin合约代码库二次开发,实战项目采用Truffle,IPFS,实现了通证以及去中心化的通证交易所。C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括帐户管理、状态与交易、智能合约开发与交互、过滤器和交易等。java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。汇智网原创翻译,转载请标明出处。这里是原文通过Java Chaincode实例学习交易系统中基于Hyperledger Fabric帐户的钱包模型 ...

February 26, 2019 · 4 min · jiezi

手把手教你走进Hyperledger Fabric

现在,Blockchain是业内新的热门话题。但是,寻找良好的资源来学习这项引人入胜的技术并不是一件容易的事。为了让其他人更容易学习,我开始在区块链和分布式分类帐技术(DLT)平台领域开展一系列工作。我将尽力涵盖每一步都需要掌握这些技术。首先,我从Hyperledger Fabric开始。Hyperledger Fabric是Hyperledger旗下的项目之一。Hyperledger是一个分布式分类账解决方案的平台,以模块化架构为基础,提供高度的安全性,弹性,灵活性和可扩展性。让我们从第一步开始一步一步实践:首先,我们必须学习如何安装Hyperledger Fabric的先决条件:安装cURL。安装Go语言。安装Docker和Docker Compose。安装Git。安装Pip在Ubuntu LTS 16.0.4上安装Hyperledger Fabric完成先决条件后,我们将继续执行以下操作:1.在Hyperledger Fabric上构建和部署你的第一个网络2.在Hyperledger Fabric上构建和部署演示示例Fabcar我们正在使用Ubuntu LTS 16.04进行本手动教程:第1步按Ctrl+Alt+T快捷键打开一个终端。$ sudo su输入你的密码$ cd第2步: 安装 Google golang$ cd $HOME/ && wget https://storage.googleapis.com/golang/go1.8.1.linux-amd64.tar.gz$ tar -xvf go1.8.1.linux-amd64.tar.gz设置go的路径$ mkdir $HOME/gopath$ export GOPATH=$HOME/gopath$ export GOROOT=$HOME/go$ export PATH=$PATH:$GOROOT/bin$ go version第3步: 安装 libltdl-dev$ apt-get install libltdl-dev第4步: 安装 docker-­ce$ wget https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker­-ce_17.06.0ce­-0ubuntu_amd64.deb$ dpkg ­i docker-­ce_17.06.0ce-­0ubuntu_amd64.deb$ docker -­ -­version注意:上述方法只是利用Hyperledger Fabric项目发布到Docker Hub的Docker镜像。$ docker run hello­-world第5步:安装 python-­pip$ apt-­get install python­-pip$ pip ­- -­version第6步:安装 docker­-compose$ pip install docker­-compose$ docker­-compose ­- -­version第7步:安装 git$ apt­-get install git$ git ­-­ -version第8步:安装 curl$ apt-­get install curl$ curl ­- -version第9步:安装 node.js and npm$ curl ­sL https://deb.nodesource.com/setup_8.x | sudo ­-E bash ­-$ node -­ -­version$ npm ­- -version第10步:从github克隆fabric示例$ git clone https://github.com/hyperledger/fabric-­samples.git第11步:进入fabric-samples目录并安装特定于平台的二进制文件$ cd fabric-­samples$ curl -­sSL https://goo.gl/byy2Qj | bash -­s 1.0.5$ docker images如果一切顺利,你将在屏幕上看到上述输出。第12步:要查看下载二进制文件,请从终端执行以下操作:$ cd bin$ ls第13步:进入first-network目录$ cd ../$ cd first-network$ ls第14步:为你的first network生成所需的证书和镜像$ ./byfn.sh -m generate第15步:要查看生成证书,请使用以下命令:$ ls$ cd crypto-config$ ls第16步:使用以下命令创建第一个网络:$ cd ../$ ./byfn.sh -m up使用Hyperledger Fabric创建第一个网络后,您将看到上述消息。第17步:使用以下命令检查生成的映像和运行容器:$ docker images$ docker ps第18步:关闭创建的网络执行以下命令:$ ./byfn.sh -m down第19步:可以使用以下方法检查已删除创建的镜像:$ docker images我们使用Hyperledger Fabric成功创建了第一个网络。现在让我们尝试另一个例子。第20步:移动到fabcar目录$ cd ../$ ls$ cd fabcar第21步:使用以下命令安装node模块$ sudo npm install第22步:使用以下命令安装grpc模块以与Hyperledger Fabric进行通信:$ sudo npm install grpc第23步:通过执行以下命令启动fabcar的Hyperledger Fabric网络:$ ./startFabric.sh第24步:要首先注册用户,你必须注册一个管理员,以帮助其他用户注册Fabcar的Hyperledger Fabric网络。$ node enrollAdmin.js你可以使用以下命令找到admin的私钥和公钥:$ ls$ cd hfc-key-store/$ ls第25步:注册用户以查询和调用fabcar网络(As Hyperledger Fabric是一个经过许可的区块链,这就是为什么我们首先必须使用其证书注册用户)$ cd ../$ node registerUser.js第26步:使用以下命令查询Fabcar网络(访问分类帐状态)$ node query.js第27步:现在让我们尝试在Hyperledger Fabric之上为我们的Fabcar应用程序提交新记录$ gedit invoke.js在上面的文件中进行以下更改以创建新记录:第28步:现在使用以下命令调用交易。(要在分类帐状态中进行任何更改,我们必须调用函数)$ Ctrl + c$ node invoke.js第29步:查询分类帐以使用以下内容查找你所做的更改$ node query.js恭喜所有人成功运行Fabcar演示。在下一部分中,我将介绍这两个例子的技术细节。敬请期待更多的更新!======================================================================分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。ERC721以太坊通证实战,课程以一个数字艺术品创作与分享DApp的实战开发为主线,深入讲解以太坊非同质化通证的概念、标准与开发方案。内容包含ERC-721标准的自主实现,讲解OpenZeppelin合约代码库二次开发,实战项目采用Truffle,IPFS,实现了通证以及去中心化的通证交易所。C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。汇智网原创翻译,转载请标明出处。这里是原文手把手教你走进Hyperledger Fabric ...

February 25, 2019 · 1 min · jiezi

使用Fabric.js玩转H5 Canvas

前言之前使用这个框架写过一个卡片DIY的项目,中间遇到很多问题都只能通过google或github issues才能解决,国内资料较少,所以才想写这篇文章来简单的做下总结,希望可以帮到其他人哈。附上个人项目地址:vue-card-diy 欢迎star~ ✨什么是Fabric.js?Fabric.js 是一个强大的H5 canvas框架,在原生canvas之上提供了交互式对象模型,通过简洁的api就可以在画布上进行丰富的操作。该框架是个开源项目,项目地址: githubFabric.js有什么功能?使用Fabric.js,你可以在画布上创建和填充对象; 比如简单的几何形状 - 矩形,圆形,椭圆形,多边形,自定义图片或由数百或数千个简单路径组成的更复杂的形状。 另外,还可以使用鼠标缩放,移动和旋转这些对象; 修改它们的属性 - 颜色,透明度,z-index等。也可以将画布上的对象进行组合。下面我将会介绍我常用的功能以及场景,更多功能可以参考 官方文档安装npm安装npm install fabric –save通过cdn引用<script src=“http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>初始化首先在html页面中写一个350 x 200的canvas标签, 这里不写宽高也行,后面可以通过js来设置宽高<canvas id=“canvas” width=“350” height=“200”></canvas>初始化fabric的canvas对象,创建一个卡片(后面都用card表示画布对象)const card = new fabric.Canvas(‘canvas’) // …这里可以写canvas对象的一些配置,后面将会介绍// 如果<canvas>标签没设置宽高,可以通过js动态设置card.setWidth(350)card.setHeight(200)就是这么简单,这样就创建了一个基本的画布。开始花样操作监听画布上的事件官方提供了很多事件,以下为常用的事件:object:added 添加图层object:modified 编辑图层object:removed 移除图层selection:created 初次选中图层selection:updated 图层选择变化selection:cleared 清空图层选中// 在canvas对象初始化后,通过以下方式监听// 比如监听画布的图层编辑事件card.on(‘object:modified’, (e) => { console.log(e.target) // e.target为当前编辑的Object // …旋转,缩放,移动等编辑图层的操作都监听到 // 所以如果有撤销/恢复的场景,这里可以保存编辑状态});设置画布背景// 读取图片地址,设置画布背景fabric.Image.fromURL(‘xx/xx/bg.jpg’, (img) => { img.set({ // 通过scale来设置图片大小,这里设置和画布一样大 scaleX: card.width / img.width, scaleY: card.height / img.height, }); // 设置背景 card.setBackgroundImage(img, card.renderAll.bind(card)); card.renderAll();});如果要设置画布的背景颜色,可以在canvas初始化时设置const card = new fabric.Canvas(‘canvas’, { backgroundColor: ‘blue’ // 画布背景色为蓝色});// 或者card.backgroundColor = ‘blue’;// 或者card.setBackgroundColor(‘blue’);向画布添加图层对象fabric.js提供了很多对象,除了基本的 Rect,Circle,Line,Ellipse,Polygon,Polyline,Triangle对象外,还有如 Image,Textbox,Group等更高级的对象,这些都是继承自Fabric的Object对象。下面我就介绍如何添加图片和文字,其他对象大同小异/*** 如何向画布添加一个Image对象?/// 方式一(通过img元素添加)const imgElement = document.getElementById(‘my-image’);const imgInstance = new fabric.Image(imgElement, { left: 100, // 图片相对画布的左侧距离 top: 100, // 图片相对画布的顶部距离 angle: 30, // 图片旋转角度 opacity: 0.85, // 图片透明度 // 这里可以通过scaleX和scaleY来设置图片绘制后的大小,这里为原来大小的一半 scaleX: 0.5, scaleY: 0.5});// 添加对象后, 如下图card.add(imgInstance);// 方式二(通过图片路径添加)fabric.Image.fromURL(‘xx/xx/vue-logo.png’, (img) => { img.set({ hasControls: false, // 是否开启图层的控件 borderColor: ‘orange’, // 图层控件边框的颜色 }); // 添加对象后, 如下图 canvas.add(img);});/** 如何向画布添加一个Textbox对象?*/const textbox = new fabric.Textbox(‘这是一段文字’, { left: 50, top: 50, width: 150, fontSize: 20, // 字体大小 fontWeight: 800, // 字体粗细 // fill: ‘red’, // 字体颜色 // fontStyle: ‘italic’, // 斜体 // fontFamily: ‘Delicious’, // 设置字体 // stroke: ‘green’, // 描边颜色 // strokeWidth: 3, // 描边宽度 hasControls: false, borderColor: ‘orange’, editingBorderColor: ‘blue’ // 点击文字进入编辑状态时的边框颜色});// 添加文字后,如下图card.add(textbox);获取当前选中的图层对象// 方式一this.selectedObj = card.getActiveObject(); // 返回当前画布中被选中的图层 // 方式二card.on(‘selection:created’, (e) => { // 选中图层事件触发时,动态更新赋值 this.selectedObj = e.target})旋转图层// 顺时针90°旋转const currAngle = this.selectedObj.angle; // 当前图层的角度const angle = currAngle === 360 ? 90 :currAngle + 90;this.selectedObj.rotate(angle);// 如果是通过滑块的方式控制旋转// this.selectedObj.rotate(slideValue);// 所有图层的操作之后,都需要调用这个方法card.renderAll()翻转图层// 水平翻转,同理垂直翻转改为scaleY属性this.selectedObj.set({ scaleX: -this.selectedObj.scaleX,})card.renderAll()移除图层card.remove(this.selectedObj) // 传入需要移除的objectcard.renderAll()控制画布上的图层层级向画布添加图层,默认是依次往上叠加,但是当你选中一个图层进入active状态时,该图层会默认置于顶层,如果像禁止选中图层时指定,可以:// 在画布初始化后设置card.preserveObjectStacking = true // 禁止选中图层时自定置于顶部设置之后,我选中vue logo就是这个样子,不会置顶。如何上移和下移图层?// 上移图层this.selectedObj.bringForward();// 下移图层this.selectedObj.sendBackwards();// 也可以使用canvas对象的moveTo方法,移至图层到指定位置card.moveTo(object, index);画布状态记录框架提供了如 toJSON 和 loadFromJSON 方法,作用分别为导出当前画布的json信息,加载json画布信息来还原画布状态。// 导出当前画布信息const currState = card.toJSON(); // 导出的Json如下图// 加载画布信息card.loadFromJSON(lastState, () => { card.renderAll();});将画布导出成图片const dataURL = card.toDataURL({ format: ‘jpeg’, // jpeg或png quality: 0.8 // 图片质量,仅jpeg时可用 // 截取指定位置和大小 //left: 100, //top: 100, //width: 200, //height: 200});Fabric.js的基本介绍就到这里,这个框架很强大,还有很多功能可以去试试,欢迎大家评论交流哈!如转载本文请注明文章作者及出处! ...

February 3, 2019 · 2 min · jiezi

区块链与分布式超级帐本技术(Hyperledger Fabric或R3 Corda)

与分布式超级账本技术(如Hyperledger Fabric或R3 Corda)相比,以太坊区块链保持了相似性和差异性。在对区块链和分布式超级账本平台进行有根据的评估及其为企业带来的价值时,根据平台的核心功能和特征对平台进行分类是有用的。由于区块链源自密码学和数据配置的原则,某些功能可以在协调的数据库系统中复制,而其他功能仅在真正的区块链环境中可行。在本文中,我们将评估面向平台的主要企业的基本业务功能,包括以太网,Hyperledger Fabric和R3 Corda,无论是通过传统的分布式系统还是通过现代的区块链基础系统,都可以从软件获取其影响的位置以及系统的整体优化方式进行评估。图1:基础技术的划分特别是,我们将重点关注三个关键功能领域:数据协调——如何在利益相关者之间更好地分配和分配系统内的信息和信任。加密经济内部激励层——如何构建系统,以便基于经济激励来激励不同的利益相关者和用户,以确保系统的功能,例如。博弈论与机制设计。融入资产的数字商品化——系统如何融入数字商品经济。在一些名义上的特征中,这被称为代币经济。区块链的主要目标:企业希望通过这项技术实现什么目标?像以太坊这样的区块链与他们的分布式对手有类似的目标。确定企业希望使用区块链技术实现目标的目标可能是一种具有挑战性的方法,因为像1990年代的互联网一样,企业还不知道如何概念化强大工具的使用。类似地,今天已知区块链技术能够实例化各种功能,但是如何将这些功能构建到业务解决方案中需要对底层能力的进一步见解和评估。探索的三个主要轴:数据的处理和协调,可信和不可变记录以及资产的数字化。足够广泛,可以封装区块链的主要可用性,同时允许将这些功能进一步推断到业务场景中。通过讨论这三个方面,可以揭示商业实体为什么要使用该技术背后的含义。高效的信息处理和协调如果改进的分布式系统设计或数据库协调是协议或平台的唯一目的,那么区块链可能不一定是所需要的。区块链平台传统上促进了更好的数据协调和分布式共识机制的概念,其中数据通过技术平台得到促进和传递。虽然有用,但通过更好地协调中央数据库或改进的分布式系统设计,可以获得这些所需功能特征的重要部分。在此调查中,有必要确定平台和协议尝试优化现有数据协调功能与实施新区块链功能的程度。区块链的设计不仅仅是高级数据协调。产品和交易的不可变/可信记录关于我们为什么需要区块链的原始论文围绕着数字化信任的概念。ConsenSys的Andrew Keys推出的一个主题是“随着互联网导致信息数字化,区块链导致信任和协议的数字化。”这篇有意义的论文体现了区块链希望实现的精神,同时也为其铺平了道路。另一条路。附加变量是值的数字化。当值附加到系统中实现的信任时,某些对齐结构和激励机制将影响和激励系统内的正确行为,从而形成一个强大的平台。通常情况下,在设计系统时,不可变性与信任同义使用,即因为系统是不可变的,所以可信的是坏事不会逍遥法外。虽然在我们的平台协议评估中,重要的是还要评估可信系统如何实施的机制,以确保可以有益于平台用户的业务模型(通过加密经济学进一步探索)。资产数字化商品和资产的数字化被认为是大多数区块链或分布式账本平台的主要目标。如果企业正在寻找资产的数字化,则分布式分类帐或数据库协调能够提供一些功能,但应充分考虑这些数字商品的可访问性。因为协调数据库基本上是通过传统软件范例集中运行或分布在交易对手的一个或多个子组之间,所以数字化的级别可以基于数字化平台提供的自由度来限制。虽然数字化商品的概念听起来像一个简单的过程,但不同的激励动态和围绕商品如房地产,人类关注甚至电力等数字化的经济推理需要考虑哪种类型的平台将对数字化负责。供应商平台确实展示了“供应商锁定”的程度,并且在各种情况下依赖于集中管理的平台。如果依赖于封闭的专有系统,并且这些资产扩散到数字生态系统或市场,它们与经济激励层的相互作用水平相当有限,那么通过分布式分类帐系统也可以使用诸如标题系统和供应链等记录和注册表。如果基于封闭的轨道将会严重发育不良。充分利用开放市场能够提供的各种方面的自由市场系统对于在不断发展的数字生态系统中促进真正的数字商品是必要的。评估数据库协调特征数据库协调:特征虽然已经在不变性,安全性,可伸缩性,可管理性和性能等特性方面对这些平台的功能进行了深入分析,但通过了解构建体系结构的基础,可以确定更多内容。已经发明并实现了许多工具,用于在分布式系统内进行适当的数据协调。一个例子就是强调像Hadoop这样的工具以及这个生态系统中的各种集合,包括Spark,Hive和Zookeeper。对这些产品的依赖表明了分布式系统工具和协议的高度集成。进一步的相似之处可以在诸如Tendermint之类的协议中显示,这是一种BPFT共识引擎,其设计具有与Apache Zookeeper等工具类似的功能。在内部,还有一些event sourcing databases的研究,可以复制协调数据共享系统所需的几个功能。通过评估Apache Kafka等工具以及数据流服务如何在企业环境中实现显着的吞吐量水平,我们可以根据对这些数据库协调和优化的不同依赖程度划分区块链和分布式分类帐之间的功能差异。基础概念方面的工具。包括Plasma在内的以太坊的实现正在利用MapReduce等工具在UTXO和基于帐户的模型之上增强某些映射功能,同时还将组件简化为merkle证明,尽管重要的是要认识到协议的基础层仍然依赖于以太坊作为根区块链。通过分解这些细节,可以获得有关如何最好地评估这些软件平台的技术特征的进一步见解。数据协调:平台比较IBM Fabric通过深入研究Fabric架构,可以确定该平台已经创建了一个复杂的开发环境,专注于基于软件架构的详细配置实现卓越的吞吐量,以在分布式系统环境中实现最佳性能。客户端和分布式签署对等节点网络之间的链代码的移动以及交易机制和满足认可策略的收据的转移在封闭系统中是有效的,而在私有信道内传播交易的gossip(八卦)协议允许协调大数据集。虽然基础设施稳健且能力强,但应该考虑如何设计架构以允许多边协调结构的思考过程,其中最终可能存在难以管理的网络中涉及的通道因素。图2:Hyperledger Fabric架构此图演示了Fabric的一些体系结构配置,以及如何将组件组织到专为高级信息处理和最大事务吞吐量而设计的系统中。主要思想是渠道为在平台内移动交易提供了机会。 在查看体系结构时,订购服务节点(OSN)的功能用于记录Apache Kafka订购服务中的交易。在数据流生态系统中,Kafka是一个功能强大的工具,具有将各种形式的事务附加到单独的Kafka集群并最终分区的功能。在此设置中,数据能够跨群集分布,以形成分布式存储平台,该平台可以记录在其键/上下文中“状态”的Fabric定义内有时称为“块”或blob的数据结构/值存储配置。在该软件框架内承认的概念是该生态系统中的所有参与者和数据结构都是本机的,因为它们主要与该软件生态系统中的其他用户一起运行。图3:Apache Kafka资料来源:Apache KafkaFabric实际上采用了部署类型的子结构来部署某些散列链接数据存储,但应该认识到散列的配置不遵循从比特币或以太坊派生的区块链系统附属的原始架构设计。虽然数据blob被批处理并且经历传递事件以最终创建交易的哈希链接,但是必须理解该过程不一定将数据转换为系统状态的修改。相反,这些块的配置方式是信息存储在具有不同哈希实例的数据库类型结构中。在Fabric生态系统中,交付事件称为块,而链代码通过部署事件最终保护订购服务结构的链分区内的数据。该系统的数据结构和模块的配置能够允许分布式数据库体系结构所期望的事务吞吐量,尽管应该承认,资产代码协调仍然是一个尚未完全解决的挑战作为资产和价值的Fabric生态系统不一定具有可在分类帐内协调的数字表示。R3 CordaR3 Corda建立在一个不要求区块链的环境之上,而是一个分布式的数据库,利用各种形式的结构重构来构建一个主要由银行和其他机构用于其流程的系统。该平台大量借用比特币交易中使用的UTXO模型,其中状态由一系列输入和输出定义,输入的变化重新配置可以决定输出的状态。R3 Corda架构框架依赖于节点结构,该结构依赖于称为公证人的子模块,这些子模块有助于维护网络的有效性,类似于抽象共识功能的其他平台中的验证器结构。节点附带有关系数据库,这些数据库附加在数据结构中,允许使用SQL进行查询。交易通信在称为流的子协议中受到限制。这些流程与IBM Fabric中的通道体系结构相当,其中只有交易的各方能够访问信息。类经历转换,导致称为光纤或协同例程的状态机。该体系结构依赖于与子流通信的流以及与在平台范围内具有预定义功能的流库交互。此外,Corda中还有一个自包含的身份层,允许在整个网络中进行不同程度的访问控制。虽然R3 Corda公开声明它不打算成为区块链,但应该考虑到将分布式数据库的概念重新配置到去中心化数据库确实非常依赖于传统的数据库系统。虽然系统围绕新颖的数据结构和分布式系统如何组织的不同组成进行架构,但该平台确实考虑了数据分配,并且确实找到了各种方法来优化数据分发系统的功能。需要记住的一点是,由于系统仅限于特定体系结构范围内的数据协调的某些方面,因此,由于未对原始设计实施模块化和互操作性,因此牺牲了与实际区块链系统的集成。图4:R3 Corda工作流程图详细信息:Corda中的交易工作流以及如何通过系统移动输入状态和输出状态以及如何将文档附加到工作流过程中。以太坊以太坊生态系统由私人区块链和公共区块链生态系统组合而成。公共链没有任何接近数据协调上下文中描述的吞吐量和数据处理能力,因此不应基于这些能力进行评估。在评估以太坊的这一方面时,最有意义的是合成以太坊私有实例的网络拓扑的不同细微差别。以太坊黄皮书坚定地规定了关于构成以太坊的一系列规范以及代码库的技术细节。由于严格遵守该协议的蓝图,以太坊以及联盟实施的forks确实类似于构建该技术的原始基板。实际上,无论是在工作量证明,股权证明还是资产证明中,相同的规范都是连续的,因为协议被认为是相同的以太坊虚拟机(EVM)规范的后代。修改的体系结构仍与原始EVM明确校准。Quorum等平台的主要变化包括改变共识机制,修改全球根状态以适应私人和公共状态,改变Patricia Merkle tries 状态以及处理私人交易的其他模块。该架构允许该软件维护原始以太坊配置的沿袭和数据结构,同时通过更改提供增加的交易吞吐量。除了Quorum提供的改进的数据交易优化之外,通过Plasma,Truebit和Cosmos等工具协调和集成公共以太坊环境的能力为协议提供了额外的可扩展性。通过对像Plasma这样的工具的技术评估以及在Casper中获得共识的格式,很明显,MapReduce和Abstract Rewrite Systems等数据库管理工具将在以太坊中实现。在Plasma中,MapReduce是组装基于帐户的系统和多线设置的位图-UTXO承诺结构的协调的不可或缺的一部分。通过防欺诈机制设计和保真债券激励结构的组合,使用根链,等离子链和子链之间的相互作用的协调交易处理范例有助于满足块扣除和质量提取表面之间的动态。它还允许使用来自Casper或Truebit等系统的机制来填充进一步的加密经济结构,以便根据空间中普遍存在的数据可用性问题来镜像擦除编码中使用的概念。对于多链体系结构,以太坊将能够将分布式数据库系统的数据库协调和吞吐量功能与实际区块链的公共链兼容功能相结合。数据库协调:结论关于数据库协调能力范围的可行结论将是IBM拥有卓越的数据库管理工具集,因为依赖于传统数据库和分布式系统软件架构,基于整体单片设计和构建Fabric的大量资源密集型流程。R3 Corda还在进一步定义其功能,同时通过比特币协议私密重新配置细微差别,为银行和金融机构提供多种协调服务。Ethereum虽然是为公共链兼容性而设计的,但它没有IBM Fabric的原始数据库处理功能,尽管它在Fabric可用的企业用例的可伸缩性环境中确实具有某些协调原理图。以太坊和互补客户的私人实例可以作为构建更大系统的架构构建块,基于模块化设计,坚持相对基于unix的理念。与以太坊相关的代码库旨在与Fabric等数据库平台的交易吞吐量功能相媲美,同时允许Corda和Fabric中不存在的功能,但也可以跨平台探索互补关系。主要的区分因素可以从后续因素的评估中进一步阐明。区块链平台的加密经济配置软件平台内部的密码经济子系统需要各种机制设计和博弈论配置,以激励参与者以最佳方式行事,既有利于自身利益,又有利于生态系统。将区块链生态系统与分布式分类账设计的数据库系统区分开来的核心原则是能够将机制设计用作经济激励层,确保信任和合作的正确分配,使系统的行为方式有利于实现分散的共识。用户以及安全。依赖于“反向博弈论”设计的这些系统的主要目标是在子系统中创建主导策略,从而产生激励的均衡结构,进一步增强整个系统的整体完整性。密码经济机制设计的例子等离子和真实比特Plasma的设计旨在为以太坊网络带来可扩展性和多链功能。通过提供其上多个以太坊谱系的区块链可以相互通信的催化剂,Plasma充当私有区块链和公共区块链网络之间的可行桥梁。从进一步分析可以看出,Plasma为以太坊网络提供了可扩展性和可用性。虽然要了解等离子体的有效性,但了解等离子体设计的机制非常重要。通过所谓的欺诈证据实现了大量的互操作性。通过配置区块链,使得派生的子区块链(或子区块链)仍然可以基于MapReduce函数的计算可靠地验证事务,可以通过最小化的信任来实现可伸缩性。围绕等离子体设计了一种机制,以便在发现故障链时允许所谓的质量存在。这些与错误操作有关的情况与数据可用性的不一致和阻止预扣攻击有关。通过允许通过交替配置相互关联的链来惩罚邪恶活动的机制,生态系统希望实例化实体如何相互作用的内聚平衡。等离子体具有相当大的影响力,来自一个名为Truebit的密集加密经济激励结构的平台,旨在提高以太坊网络的离链计算能力。通过围绕验证游戏设计Truebit系统,其中整体共识机制的解决方案可以被验证者挑战,如果他们识别出一个邪恶的交易对手则获得奖励,创建系统的内部加密经济“检查和平衡”以激励占主导地位行为公平的策略。由于Plasma通过TrueBit的影响专注于创建多链互操作性网络,因此系统的内部实施对于实现信息和共识保真度至关重要。如下图所示,涉及Truebit并衍生到Plasma中的加密经济游戏包括求解器和挑战者之间的平衡相互作用,以验证最终在链上验证的计算的正确性。挑战者被激励不断挑战,因为强制错误可以保证如果正确解决支付。图5:加密经济设计以太坊Casper股权证明机制密码经济激励层的一个例子也可以在以太坊通过Casper的实现过渡到股权证明共识机制的证据中看到。虽然工作量证明有自己的内化游戏理论激励结构,以阻止参与者征用网络,但是向股权证明的过渡甚至还有进一步的内部结构,以阻止参与者在遇到货币时模仿或试图创建区块链的替代实例。staking协议创建了一个拜占庭容错环境,其中Ether将被绑定到共识机制中。这意味着个人将受到忠诚的约束,以在系统内表现得光荣。如果攻击者计划在共识机制中模仿或试图控制,那么与“slasher算法”相关的各种协议将破坏以太网持有者或攻击者的联系,因此惩罚他们的邪恶行为。在惩罚背后的机制设计中,被破坏的以太网的数量始终被编程为与攻击者希望获得的数量成比例,其中所达到的均衡是攻击者首先不想破坏系统的地方。Cosmos和TendermintCosmos还在建立一个依赖于Tendermint共识机制的生态系统,该机制在很大程度上依赖于拜占庭容错算法。该平台依赖于与比特币网络中的矿工具有类似角色的验证器。验证器具有称为Atoms的标记代币,用于通过依赖于绑定验证器生成的信任的股权证明机制来保护网络。生态系统中的参与者之间的相互作用也表示游戏理论结构,其中如果发现违反协议,验证者可能丢失其代币或授权给他们的代币。由于该系统内利益相关者的这种保税存款设计,共识机制允许一种保护网络的激励机制。此安全设计允许应用程序区块链接口(ABCI),区块链间通信协议(IBC)以及Cosmos集线器和区域之间的不同交互的正常运行。R3 Corda和IBM Fabric需要注意的一个重要注意事项是,R3 Corda和Hyperledger Fabric在其软件架构中没有实例化这些加密经济激励层。由于软件体系结构是基于分布式数据库聚焦范例进行基础设计的,因此它们最初并非设计用于在整个框架内结合本机加密货币层。由于软件设计的这种固有差异,它们尚未经过校准,无法参与多链生态系统,在这些生态系统中存在与多个区块链的互操作性和协调性。由于系统的结构考虑了最大吞吐量,因此基于这些系统的初始构建,忽略了包含公共区块链主网的区块链的可互操作网络拓扑的架构布局。为什么需要加密经济机制设计?人们可能会问为什么在软件设计中需要加密经济基础设施层。这种范式创造的是一个新的信任和不变性层,可以存在于计算环境中而不依赖于集中式实体。几十年来,我们一直在特定的客户端服务器和数据库架构中构建软件。像IBM,Intel和Oracle这样的公司已经完善了这个模型以及在初始创建之后创建的系统和子系统,这些模型仍然在分布式系统架构以及新标记的分布式分类帐系统中使用。虽然这些系统仍然集中在各个方面,无论是通过中央实体还是类似卡特尔的财团结构,其中激励措施是基于对集中实体的固有依赖而不是真正的激励结构来确保系统的正常运行。图6:客户端服务器模型去中心化系统允许在软件环境中实现某些目标的可行替代途径。在这种交换中突出显示的主要权衡是信任与执行。因为大型集中式系统更受信任,所以它被认为能够更好地执行。虽然区块链系统希望灌输的是系统的特征,在这种系统中,信任和价值可以在不依赖大型集中化实体的情况下重新分配。在系统设计的某些方面支持的一个想法是,为了优化系统,还必须对子系统进行子优化。这意味着必须协调和架构系统的协调,以便内部子系统在整个更大的生态系统中也具有利益或激励机制,以进一步实现合作目标。通过为整体环境的优化创建加密经济博弈理论方法,可以创建计算机科学和经济模型的汇合,从而允许创建可以在数字经济中设想的新软件架构。基于对数字经济的这种愿景,应该认识到,使用可以互操作的私有区块链和公共区块链的组合将创建一个可行的数字生态系统,在这个生态系统中可以出现各种商业和商业关系层,并在在传统技术配置中是可能的。融入区块链代币经济出于本次调查的目的,有必要定义标记化的概念。该概念借鉴了企业或实体能够根据我们生态系统中目前存在的某些数字标准创建各种形式的资产,商品和服务的可替代或非可替代表示的概念。虽然代币经济仍在发展,但重要的是区分第一波产品最初会有各种各样的失败和缺陷需要时间和迭代来完善。即使资产,金融产品,能源和数字注意力的标记化都是可行的商业模式,它们实施的确切动态需要额外的功能和访问层,只能随着时间的推移而改进。成功的代币经济将是由游戏理论机制设计和区块链创新中的重大发展和发现所创造的结果。正如Josh Stark关于加密经济学的文章所述,表现出最强可用性标志的标记是否构成了整体业务的经济学和博弈论设计中的必要组成部分。如果企业可以将其生态系统的各个方面数字化或标记化,那么可以创建的产品线将以指数方式扩展,超出我们传统的交换实物,金融资产,商品或技术服务的方式。通过创建标记化资产可以实现的数字媒体,重要的发展可以从新的生态系统发展而来。在观察区块链工具的生态系统时,很明显,以太坊实际上是可以建立代币经济的基础。如果代币经济模型能够结合私有区块链,可扩展性解决方案和ZK-Snarks等隐私工具的功能,数字资产的整体标记化将使我们的经济模型受限于当前的能力,因为组织可行性。实现区块链的业务目标为了实现区块链的上述业务目标,我们必须评估需要服务的各种途径。在概述详细说明所述模型的功能的图表时,以太坊能够为分布式数据库协调方案以及附加功能提供服务,而R3 Corda和IBM Fabric尚未选择触及这些功能层。在业务用例的背景下,我们覆盖了在现实世界业务场景之上讨论的不同功能,以更好地理解平台的功能。图7:功能摘要有效分配信息从功能上讲,从分布式系统的数据库协调和利用的角度来看,产品类似地匹配。事实上,R3 Corda,IBM Fabric和以太坊的企业版本具有分布式信息分配功能,可以通过不同的访问控制层和联盟的治理配置来促进信息的分配。虽然每个平台在其软件架构配置方面都不同,但每个平台都能够在有效的信息分配和协调上执行必要的性能。可信的不可变信息在大量这些技术的背景下,不变性在某种程度上被用作信任的同义概念。在评估不变性特征时,必须理解在利用基于Apache的数据流工具(如Kafka)的生态系统中,存在允许对数据进行读/写访问的固有功能。因此,由于系统设计中的一些选择,IBM Fabric的不变性方面有些受限。对于R3 Corda的基于UTXO模型的系统,不变性方面在系统的整体范围内保持不同。由于他们系统的整体分布式分类帐设计,他们已经建立了可以在整个平台上展示的某些信任方面。在以太坊上下文中建立的信任和不变性层都是在Patricia Merkle Tries的公共区块链派生状态根的子协议中概念化的。由于生态系统内核心软件范例的这种保留以及与公共链的可行连接,以太坊区块链和以太坊的相关推导能够充分证实不变性。随着资产开始数字化,从这种不变性获得的信任最终可以附加到新的价值体系。资产数字化应该认识到,IBM Fabric实际上能够在名义意义上创建数字资产,因为资产的数字化是从产品的注册表导出为数字格式的。虽然Fabric上资产的数字化会导致资产只能在使用Fabric的系统上运行。这相当于如果创建电子邮件客户端只能与使用完全相同的电子邮件客户端的人来回发送电子邮件,这与我们当前世界中存在的大量电子邮件客户端可以一起互操作的情况不同。R3 Corda具有类似的不一致性,因为R3平台的用户将被限制在其整体环境中与R3之外的其他平台进行交互,从而造成一些供应商锁定。因为R3 Corda主要关注银行客户,所以有可能有一个虽然应该注意平台的用户将仅限于使用R3 Corda的机构的银行业务关系,并且无法与不使用供应商平台的交易对手的生态系统无缝互操作。因为以太坊意味着充当类似于Web服务中的HTTP或TCP/IP的底层协议,所以对于只有一个以太坊应用程序的构建者,没有“供应商锁定”的概念。可以通过以太坊区块链的不同方面建立的信任允许全球资产的数字化,这种资产可以在新的经济体系内发生,而不像现有的那样。如果回头参考电子邮件示例,可以将以太坊协议视为与IMAP或POP3类似,作为访问电子邮件的通用协议。以太坊和以太坊派生的协议能够充当区块链基础设施,公司可以在此基础设施上构建数字资产。类似于每个公司在90年代后期使用HTML为网页搭建网站创建网站的方式,每家公司都能够使用以太网智能合约为其服务和产品创建数字经济,这些合约可以创建代币。可通过更广泛的网络访问。前方的路为了拥有足够强大的平台,可以与公共市场互动,系统必须能够满足业务需求,从而实现数据的有效处理,额外的信任分配层以及在发展中的数字经济中代表资产的能力。 很明显,所有三个平台都旨在通过技术进步和技术配置的不同途径实现类似的目标。在未来的道路上,我们必须考虑在这个发展中的生态系统中我们看到经济商业模式在哪里发展,显然基于以太坊的平台在真正融入数字经济方面具有优势,尽管在某些数据交易中存在明显的弱点IBM Fabric和R3 Corda可以擅长的吞吐量功能。由于不同的区块链和分布式账本平台被迭代并超越了我们当前技术时代精神所存在的能力,围绕哪个平台进行构建的决策将严重依赖于方向在我们的生态系统中的用例,我看到不同类型的用例相互分层。本文档的目的并不是说一个平台总体上比另一个平台更好,而是旨在规定这些平台本质上是彼此不同的。以太坊具有某些功能,分布式分类账(如Fabric和Corda)没有,而Fabric和Corda具有以太网目前无法达到相同程度的性能。为了真正实现我们现有系统所需的交互和可扩展性水平,必须在构建和设计协议时考虑所有交互,类似于首次设计互联网的方式。以太坊作为一种协议,能够充当基础技术堆栈,为广泛的生态系统提供服务,涵盖经济环境中的必要因素,但请记住,该平台目前尚未完成,也可能受益于某些固有的功能在DLT同行中。虽然前面的道路将包括尚未完善的技术,但应该检查协议是否最终会复制我们希望在下一代互联网中看到的功能程度,有时最明显的解决方案不是只关注一项技术。======================================================================分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。汇智网原创翻译,转载请标明出处。这里是区块链与分布式超级帐本技术(Hyperledger Fabric或R3 Corda)

January 8, 2019 · 1 min · jiezi

Hyperledger Fabric Node.js 智能合约即链码开发

Hyperledger Fabric是一种联盟区块链,Fabric区块链也支持智能合约,被称为链码(Chaincode)。Fabric链码就是一个标准的(运行在docker容器中的)操作系统进程,通过gRPC协议与Fabric节点通信。因此理论上可以使用任何语言开发Fabric链码。目前官方提供了三种开发语言的Fabric链码开发工具包:Go、Java和Node.js,本文将介绍如何使用node.js开发Fabric链码。上汇智网,用互动方式学习以太坊、比特币、EOS、tendermint等更多区块链开发教程。Fabric官方提供了两种开发node.js链码的途径:fabric-shim和fabric-contract-api。使用fabric-shim开发Fabric链码fabric-shim是较底层的链码开发包,它封装了与节点通信的grpc协议。安装方法如下:/fabric-shim-chaincode-demo$ npm install fabric-shimfabric-shim要求链码开发者定义一个实现两个预定义方法的类。Init(stub):初始化链码时节点将调用该方法Invoke(stub):节点将应用对链码的调用转化为对该方法的调用参数stub由节点传入,它提供了访问链上账本的方法,以便读取或更新账本状态。例如,下面的代码实现了一个最小化的node.js链码,每次调用链码都会更新acc0的状态(例如:可以使用这个状态代表账户余额):const shim = require(‘fabric-shim’);class EzChaincode { async Init(stub) { return shim.success(Buffer.from(‘init done!’));//返回success对象 } async Invoke(stub) { let key = ‘acc0’; let oldValue = await stub.getState(key); //读取账本中acc0的状态 let newValue = oldValue + 100; await stub.putState(key, Buffer.from(newValue)); //更新acc0的状态 return shim.success(Buffer.from(‘update done!’));//返回success对象 }};一旦定义好链码,就可以使用shim.start()方法启动链码实例了。例如:const shim = require(‘fabric-shim’);class EzChainCode {…}shim.start(new EzChaincode());这就是一个完整的Fabric链码了!将上面代码保存为demo.js,可以直接用node.js启动:/fabric-shim-chaincode-demo$ node demo.js使用fabric-contract-api开发Fabric链码fabric-shim是一种相对底层的fabric grpc协议封装,它直接把链码接口暴露给开发者,虽然简单直白,但如果要实现相对复杂一点的链码,开发者需要自己在Invoke实现中进行方法路由。fabric-contract-api则是更高层级的封装,开发者直接继承开发包提供的Contract类,就不用费心合约方法路由的问题了。fabric-contrac-api开发方法如下:/fabric-contract-api-demo$ npm install fabric-contract-api使用fabric-contract-api的链码示例代码如下,除了构造函数之外的每个方法都自动称为链码的方法,可供外部应用调用 ://demo.jsconst { Contract } = require(‘fabric-contract-api’);class EzContract extends Contract constructor(){ super(‘EzContract’); } async update(ctx, newValue) { await ctx.stub.putState(‘acc0’, Buffer.from(newValue)); return Buffer.from(‘update done!’); } async remove(ctx) { //….. }};module.exports.contracts = [‘EzContract’];与fabric-shim不同,fabric-contract-api只需要链码导出contracts数组,因此不能直接使用node.js启动链码,而需要使用fabric-chaincode-node程序。例如:/fabric-contract-api-demo$ fabric-chaincode-node demo.js汇智网原创,转载请标明出处。 ...

December 30, 2018 · 1 min · jiezi