golang 实现比特币内核:椭圆曲线有限域的代码实现

让我们开始有限域的代码之旅,进入一个空目录,创建一个名为bitcoin的新文件夹,在bitcoin目录中,再创建一个名为elliptic-curve的新文件夹。在该文件夹中初始化一个新的包,运行以下命令:


go init mod elliptic_curve

然后我们创建一个新文件finite-element,我们将在这里编写有限域元素的代码,将以下代码放入文件中:


package elliptic_curve

import (
	"fmt"
)

type FieldElement struct {
	order uint64 // field的阶
	num   uint64 // 该元素在域中的值
}

func NewFieldElement(order uint64, num uint64) FieldElement {
	/*
		FieldElement的构造函数,相当于Python中的__init__
	*/

	if num >= order || num < 0 {
		err := fmt.Sprintf("Num not in the range from 0 to %d", order)
		panic(err)
	}

	return FieldElement{
		order: order,
		num:   num,
	}
}

func (f FieldElement) String() string {
	// 将对象格式化为可打印的字符串,相当于Python中的__repr__
	return fmt.Sprintf("FieldElement{order: %d, num: %d}", f.order, f.num)
}

func (f FieldElement) EqualTo(other FieldElement) bool {
	/*
		两个域元素在阶和数值相等时才相等
	*/
	return f.order == other.order && f.num == other.num
}

现在我们已经有了有限域元素的基本结构,让我们添加更多的方法。对于域元素有两种操作,一种是“+”即模加法,另一种是“.”即模乘法。让我们看看如何进行加法操作:


func (f *FieldElement) Add(other *FieldElement) *FieldElement {
	if other.order != f.order {
		panic("add need to do on field element with the same order")
	}

	// 记得做模运算
	return NewFieldElement(f.order, (f.num+other.num)%f.order)
}

func (f *FieldElement) Negate() *FieldElement {
	/*
		对于一个域元素a,其负值是域中另一个元素b,使得(a + b) % order= 0
		(注意模数是order),由于域中元素的值小于其阶,我们可以通过order - a得到a的负值。
	*/

	return NewFieldElement(f.order, f.order-f.num)
}

func (f *FieldElement) Substract(other *FieldElement) *FieldElement {
	// 如何实现?
	return nil
}

现在在main.go文件中调用以上代码来检查结果,如下所示:


package main

import (
	ecc "elliptic_curve"
	"fmt"
)

func main() {
	/*
		构建阶为57的域,并进行加减法操作
	*/
	f44 := ecc.NewFieldElement(57, 44)
	f33 := ecc.NewFieldElement(57, 33)
	// 44 + 33 等于 (44+33) % 57 等于 20
	res := f44.Add(f33)
	fmt.Printf("域元素44加上域元素33结果是:%v\n", res)
	// -44是域元素44的负值,即57 - 44 = 13
	fmt.Printf("域元素44的负值是:%v\n", f44.Negate())
}

然后运行以下命令:


go run main.go

如果一切正常,您将看到以下结果:


field element 44 add to field element 33 is : FieldElement{order: 57, num: 20}
negate of field element 44 is : FieldElement{order: 57, num: 37}```

现在我们解决减法的问题,对于域元素a, b,我们希望找到域元素c,使得c = a - b。注意a - b等于a + (-b),而(-b)是b的负值,这意味着c等于a加上b的负值。让我们将其写入代码:


func (f *FieldElement) Subtract(other *FieldElement) *FieldElement {
	// 首先找到other的负值
	// 将其加上other的负值
	return f.Add(other.Negate())
}

现在在main中添加一些代码来运行Subtract函数:


func main() {
    ....
fmt.Printf("域元素44 - 33结果是:%v\n", f44.Substract(f33))
	fmt.Printf("域元素33 - 44结果是:%v\n", f33.Subtract(f44))

	// 检查 (11+33)%57 == 44
	// 检查 (46 + 44) % 57 == 33
	fmt.Printf("检查46 + 44在57模下结果是%d\n", (46+44)%57)
	// 使用域元素检查
	f46 := ecc.NewFieldElement(57, 46)
	fmt.Printf("域元素46 + 44结果是%v\n", f46.Add(f44))
}

运行代码,我们可以得到以下结果:


field element 44 add to field element 33 is : FieldElement{order: 57, num: 20}
negate of field element 44 is : FieldElement{order: 57, num: 37}
field element 44 - 33 is : FieldElement{order: 57, num: 11}
field element 33 - 44 is : FieldElement{order: 57, num: 46}
check 46 + 44 over modulur 57 is 33
field element 46 + 44 is FieldElement{order: 57, num: 33}

我们可以进行一些简单的算术计算,(46+44) % 57的结果确实是33,这意味着我们的代码逻辑是正确的。接下来我们看看如何添加乘法和幂运算操作,即在模数order下的乘法和幂操作,代码如下:


func (f *FieldElement) checkOrder(other *FieldElement) {
	if other.order != f.order {
		panic("add need to do on field element with the same order")
	}
}

func (f *FieldElement) Multiplie(other *FieldElement) *FieldElement {
	f.checkOrder(other)
	// 在模数order下乘法
	return NewFieldElement(f.order, (f.num*other.num)%f.order)
}

func (f *FieldElement) Power(power int64) *FieldElement {
	return NewFieldElement(f.order, uint64(math.Pow(float64(f.num), float64(power)))%f.order)
}

我们运行新增的代码进行测试,在main.go中添加如下代码:


func main() {
...
    fmt.Printf("元素46自身相乘的结果是:%v\n", f46.Multiplie(f46))
    fmt.Printf("元素46的2次幂是%v\n", f46.Power(2))
}

运行结果是:

multiplie element 46 with itself is :FieldElement{order: 57, num: 7}
element 46 with power to 2 is FieldElement{order: 57, num: 7}

可以看到,元素46的自乘等于其2次幂的计算结果。现在是问题时间了,对于阶为19的有限域,随机选择一个元素k,计算{k . 0, k . 1, … k . 18},结果会是什么呢?

让我们用代码来解决这个问题,首先我们需要为域元素添加一个方法,使其可以乘以标量数:


func (f *FieldElement) ScalarMul(val uint64) *FieldElement {
	return NewFieldElement(f.order, (f.num*val)%f.order)
}

现在到main.go中,并用以下代码解决问题:


package main

import (
	ecc "elliptic_curve"
	"fmt"
	"math/rand"
)

func SolveField19MultiplieSet() {
	// 随机选择一个1到18的数
	min := 1
	max := 18
	k := rand.Intn(max-min) + min
	fmt.Printf("随机选择的k是:%d\n", k)
	element := ecc.NewFieldElement(19, uint64(k))
	for i := 0; i < 19; i++ {
		fmt.Printf("元素%d乘以%d的结果是%v\n", k, i, element.ScalarMul(uint64(i)))
	}
}

func main() {
	SolveField19MultiplieSet()
}

如果运行以上代码,您可能会得到以下结果:

element 2 multiplie with 0 is FieldElement{order: 19, num: 0}
element 2 multiplie with 1 is FieldElement{order: 19, num: 2}
element 2 multiplie with 2 is FieldElement{order: 19, num: 4}
element 2 multiplie with 3 is FieldElement{order: 19, num: 6}
element 2 multiplie with 4 is FieldElement{order: 19, num: 8}
element 2 multiplie with 5 is FieldElement{order: 19, num: 10}
element 2 multiplie with 6 is FieldElement{order: 19, num: 12}
element 2 multiplie with 7 is FieldElement{order: 19, num: 14}
element 2 multiplie with 8 is FieldElement{order: 19, num: 16}
element 2 multiplie with 9 is FieldElement{order: 19, num: 18}
element 2 multiplie with 10 is FieldElement{order: 19, num: 1}
element 2 multiplie with 11 is FieldElement{order: 19, num: 3}
element 2 multiplie with 12 is FieldElement{order: 19, num: 5}
element 2 multiplie with 13 is FieldElement{order: 19, num: 7}
element 2 multiplie with 14 is FieldElement{order: 19, num: 9}
element 2 multiplie with 15 is FieldElement{order: 19, num: 11}
element 2 multiplie with 16 is FieldElement{order: 19, num: 13}
element 2 multiplie with 17 is FieldElement{order: 19, num: 15}
element 2 multiplie with 18 is FieldElement{order: 19, num: 17}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/909155.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在 IntelliJ IDEA 中调整 `Ctrl+/` 快捷键生成注释的位置

前言 在使用 IntelliJ IDEA 编写代码时&#xff0c;注释是代码可读性和维护性的重要组成部分。IDEA 提供了快捷键 Ctrl/ 用于快速生成单行注释。然而&#xff0c;默认情况下&#xff0c;使用此快捷键生成的注释会出现在行首&#xff0c;导致注释与代码之间存在较大的空格&…

深入理解对象池 sync.Pool

文章目录 前言应用使用源码走读数据结构Get获取对象Put归还对象poolDeque分析GC时 总结 前言 当多个 goroutine 都需要创建同⼀种对象的时候&#xff0c;如果 goroutine 数量过多&#xff0c;导致对象的创建剧增&#xff0c;进⽽导致 GC 压⼒增大。形成下面的恶性循环&#xf…

项目管理(软设软考高频)

一、进度管理 1.Gantt图 2.PERT图 二、风险管理 三、沟通管理 四、成本管理

在Java中,实现数据库连接通常使用JDBC

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

gradle下载的jar包,源码出现Decompiled .class file, bytecode version

如下是问题截图 问题产生原因&#xff1a; gradle依赖下载只下载了jar包&#xff0c;这导致idea在读取jar包时&#xff0c;需要通过Fernflower技术对jar包进行反编译&#xff0c;而反编译过程中只会保留源码信息&#xff0c;因此注释等额外信息全部丢失 解决方案&#xff1a…

[357]基于springboot的中小型制造企业质量管理系统

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…

SAP(PP生产制造)拆解工单业务处理

1、BOM维护 要拆解的成品或半成品要和原成品、半成品BOM一致 2、创建拆解工单 CO01选择拆解工单的类型&#xff0c;以及填写拆解的物料和拆解工厂 维护工单组件 注意&#xff1a; 1、拆解入库组件的数量需要维护为负数 2、拆解工单投料组件数量维护为正数 3、拆解工单收发…

NavVis LX系列产品典型应用—现有住宅装修改造-沪敖3D

现有住宅装修改造项目的 数据捕捉和测量技术 当Jay Ure着手翻新和美化自己的新家时&#xff0c;他敏锐地发现这是现场测试NavVis VLX的绝佳机会。 为了全面评估&#xff0c;他聘请了一位工程师&#xff0c;采用传统的全站仪技术进行地形测绘。之后&#xff0c;他用移动扫描设…

【初阶数据结构篇】链式结构二叉树(续)

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…

qt QTabWidget详解

1、概述 QTabWidget是Qt框架中的一个控件&#xff0c;它提供了一个标签页式的界面&#xff0c;允许用户在不同的页面&#xff08;或称为标签&#xff09;之间切换。每个页面都可以包含不同的内容&#xff0c;如文本、图像、按钮或其他小部件。QTabWidget非常适合用于创建具有多…

Linux系统基础-多线程超详细讲解(5)_单例模式与线程池

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Linux系统基础-多线程超详细讲解(5)_单例模式与线程池 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&a…

Spark中的宽窄依赖

一、什么是依赖关系 这里通过一张图来解释&#xff1a; result_rdd是由tuple_rdd使用reduceByKey算子得到的&#xff0c; 而tuple_rdd是由word_rdd使用map算子得到的&#xff0c;word_rdd又是由input_rdd使用flatMap算子得到的。它们之间的关系就称为依赖关系&#xff01; 二…

[每周一更]-(第121期):模拟面试|微服务架构面试思路解析

这一系列针对Go面试题整理,仅供参考 文章目录 00|综合服务治理方案:怎么保证微服务应用的高可用?1. **什么是微服务架构?**2. **怎么保证微服务架构的高可用?**3. **怎么判定服务是否已经健康?**4. **如果服务不健康该怎么办?**5. **怎么判定服务已经从不健康状态恢复过…

一体化运维监控管理平台详解:构建高效运维体系

在当今数字化转型的大潮中&#xff0c;IT系统的复杂性和规模不断扩大&#xff0c;运维工作的挑战也随之增加。为了应对这一挑战&#xff0c;我们推出了一体化运维监控管理平台&#xff0c;旨在通过全面、智能的监控手段&#xff0c;提升运维效率&#xff0c;保障业务连续性。本…

FBX福币交易所A股三大指数小幅低开 稀土永磁板块回调

查查配分析11月5日电 周二,A股三大指数小幅低开。沪指开盘跌0.10%报3306.81点,深证成指开盘跌0.09%报10653.20点,创业板指开盘跌0.05%报2184.90点。 FBX福币凭借用户友好的界面和对透明度的承诺,迅速在加密货币市场中崭露头角,成为广大用户信赖的平台。 来源:同花顺iFinD 盘面…

【数据分享】1981-2024年我国逐日平均气温栅格数据(免费获取)

气象数据一直是一个价值很高的数据&#xff0c;它被广泛用于各个领域的研究当中。这其中&#xff0c;又以平均气温数据最为常用&#xff01;之前我们分享过来源于美国国家海洋和大气管理局&#xff08;NOAA&#xff09;下设的国家环境信息中心(NCEI)发布的1929-2024年全球站点的…

云渲染与汽车CGI图像技术优势和劣势

在数字时代&#xff0c;云渲染技术以其独特的优势在汽车CGI图像制作中占据了重要地位。云渲染通过利用云计算的分布式处理能力&#xff0c;将渲染任务分配给云端的服务器集群进行计算&#xff0c;从而实现高效、高质量的渲染效果。 这种技术的优势主要体现在以下几个方面&#…

QT仿QQ聊天项目,第三节,实现主界面(好友列表)

目录 一&#xff0c;主界面示例 二&#xff0c;主界面控件组成 三&#xff0c;好友列表实现 1&#xff0c;好友列表的实现原理 2&#xff0c;实现示例代码 一&#xff0c;主界面示例 二&#xff0c;主界面控件组成 三&#xff0c;好友列表实现 1&#xff0c;好友列表的实现…

20241105编译荣品的Android13并给荣品PRO-RK3566开发板刷机

20241105编译荣品的Android13并给荣品PRO-RK3566开发板刷机 2024/11/5 19:10 荣品SDK版本呢&#xff1a;rk-android13-20240713.tgz cf9cea18d26ad7db31b000a7d13b09c2 rk-android13-20240713.tgz 精简步骤&#xff1a; rootrootrootroot-desktop:~$ cd Android13.0/rootrootr…

KVM虚拟机的冷热迁移

首先了解在KVM&#xff08;Kernel-based Virtual Machine&#xff09;环境中&#xff0c;冷热迁移是指将虚拟机从一台主机迁移到另一台主机的过程&#xff0c;根据虚拟机是否需要停机&#xff0c;迁移分为热迁移和冷迁移&#xff1a; 冷迁移&#xff08;Cold Migration&#x…