[Bitcoin] 楕円曲線:点の加算

class Point:

	def __init__(self, x, y, a, b):
		self.a = a
		self.b = b
		self.x = x
		self.y = y
		if self.x is None and self.y is None:
			return
		if self.y**2 != self.x**3 + a * x + b:
			raise ValueError('({},{}) is not on the curve'.format(x, y))

	def __add__(self, other):
		if self.a != other.a or self.b != other.b:
			raise TypeError('Points {}, {} are not on the same curve'.format(self, other))

		if self.x == other.x and self.y != other.y:
			return self.__class__(None, None, self.a, self.b)

		if self.x is None:
			return other
		if other.x is None:
			return self

	def __eq__(self, other):
		return self.x == other.x and self.y == other.y \
			and self.a == other.a and self.b == other.b

	def __ne__(self, other):
		return not (self == other)

p1 = Point(-1, -1, 5, 7)
p2 = Point(-1, 1, 5, 7)
inf = Point(None, None, 5, 7)
print(p1 + inf)
print(inf + p2)
print(p1 + p2)

$ python3 app.py
<__main__.Point object at 0x7f014fc2fbb0>
<__main__.Point object at 0x7f014fbf07f0>
None

### x1 != x2 の点の加算
P1 = (x1,y1), P2 = (x2, y2), P3 = (x3, y3)
s = (y2 – y1)/(x2 – x1)
x3 = s^2 – x1 – x2
y3 = s(x1 – x3) – y1

x1, y1 = 2, 5
x2, y2 = -1, -1
s = (y2 - y1) / (x2 - x1)
x3 = s**2 - x1 - x2
y3 = s * (x1 - x3) - y1
print(x3, y3)
		if self.x != other.x:
			s = (other.y - self.y) / (other.x - self.x)
			x = s**2 - self.x - other.x
			y = s * (self.x - x) - self.y
			return self.__class__(x, y, self.a, self.b)

### P1 = P2 の時の点の加算
x3 = s^2 – 2×1
y3 = s(x1 – x3) – y1

a, x1, y1 = 5, -1, -1
s = (3 * x1**2 + a) / (2 * y1)
x3 = s**2 - 2*x1
y3 = s * (x1 - x3) - y1
print(x3, y3)
		if self == other:
			s = (3 * self.x**2 + self.a) / (2 * self.y)
			x = s**2 - 2 * self.x
			y = s * (self.x - x) - self.y
			return self.__class__(x, y, self.a, self.b)

		if self == other and self.y == 0 * self.x:
			return self.__class__(None, None, self.a, self.b)

なるほどー

[Bitcoin] 楕円曲線

### 楕円曲線 定義
y^2 = x^3 + ax + b

class Point:

	def __init__(self, x, y, a, b):
		self.a = a
		self.b = b
		self.x = x
		self.y = y
		if self.y**2 != self.x**3 + a * x + b:
			raise ValueError('({},{}) is not on the curve'.format(x, y))

	def __eq__(self, other):
		return self.x == other.x and self.y == other.y \
			and self.a == other.a and self.b == other.b

	def __ne__(self, other):
		return not (self == other)

p1 = Point(-1, -1, 5, 7)
p1 = Point(-1, -2, 5, 7)

一次方程式
y = ax^2 + bx + c

二次方程式
y = ax^3 + bx^2 + cx + d

楕円曲線は左辺がy^2となっている 
x軸に対して対称のグラフ

ビットコインに用いられる楕円曲線はsecp256k1と呼ばれる
y^2 = x^3 + 7

def on_curve(x, y):
	return y**2 == x**3 + 5*x + 7

print(on_curve(2,4))
print(on_curve(-1,-1))
print(on_curve(18,77))
print(on_curve(5,7))

### 点の加算
曲線上の二つの点を演算して、三つ目の点を得る
第三の点をx軸に対して対称にした点が点の加算の解になる
 L 点の加算は容易に予測できない(同一性、可換性、結合性、可逆性)

なるほど、こういうことをやっとるんか

[Bitcoin] モジュロ演算

四則演算(加算、減算、乗算、除算)について閉じている有限体を作るために利用できる道具がモジュロ演算
モジュロ演算:1つの数を別の数で割った余りの数を求めること
(3 – 16) % 12 = 11
(12 + 843) % 60 = 15
(23 + 97) % 60 = 0

pythonのモジュロ演算

print(7 % 3)
print(-27 % 13) 

$ python3 app.py
1
12

有限体上の加算が閉じていることを確認する必要がある
F19 = {0, 1, 2…18}

F57

prime = 57
print((44+33)%prime)
print((9-29)%prime)
print((17+42+49)%prime)
print((52-30-38)%prime)

### 加算と減算

// 省略
	def __add__(self, other):
		if self.prime != other.prime:
			raise TypeError('Cannot add two numbers in different Fields')
		num = (self.num + other.num) % self.prime
		return self.__class__(num, self.prime)

	def __sub__(self, other):
		if self.prime != other.prime:
			raise TypeError('Cannot subtract two numbers in different Fields')
		num = (self.num - other.num) % self.prime
		return self.__class__(num, self.prime)		

a = FieldElement(7, 13)
b = FieldElement(12, 13)
c = FieldElement(6, 13)
print(a+b==c)

### 乗算とべき乗
べき乗は乗算を繰り返し

prime = 97
print(95*45*31 % prime)
print(17*13*19*44 % prime)
print(17**7 * 77**49 % prime)

乗算

	def __mul__(self, other):
		if self.prime != other.prime:
			raise TypeError('Cannot multiply two numbers in different Fields')
		num = (self.num * other.num) % self.prime
		return self.__class__(num, self.prime)

a = FieldElement(3, 13)
b = FieldElement(12, 13)
c = FieldElement(10, 13)
print(a*b==c)

べき乗

	def __pow__(self, exponent):
		num = (self.num ** exponent) % self.prime
		return self.__class__(num, self.prime)

a = FieldElement(3, 13)
b = FieldElement(1, 13)
print(a**3==b)
for prime in (7, 11, 17, 31):
	print([pow(i, prime-1, prime) for i in range(1, prime)])

### 有限体上の除算

prime = 31
print(3*pow(24, prime-2, prime) % prime)
print(pow(17, prime-4, prime))
print(pow(4, prime-5, prime)*11 % prime)
	def __truediv__(self, other):
		if self.prime != other.prime:
			raise TypeError('Cannot divide two numbers in different Fields')
		num = self.num * pow(other.num, self.prime - 2, self.prime) % self.prime
		return self.__class__(num, self.prime)

いきなり難しいな

[Blockchain] Bitcoinの学習開始

$ sudo apt install python3-virtualenv
$ virtualenv -p python3 .venv
$ .venv/vin/activate
$ . .venv/bin/activate
$ pip3 install -r requirements.txt

// vagrant上でjupyter notebookを起動する
$ jupyter notebook –no-browser –ip=0.0.0.0

ビットコインは相互に依存するコンポーネントが多数存在する
楕円曲線暗号(ECC)が基礎となる
L 署名アルゴリズム、検証アルゴリズム … トランザクションの仕組みの中心
  L シェノア署名、秘匿トランザクションなどの技術

### 有限体
有限の個数からなる集合と演算
集合が閉じている、加法単位元、乗法単位元、加法逆元、乗法逆元

### 有限集合
Fp = {0,1,2,…p-1}
体の位数は素数のべき乗となる

class FieldElement:

	def __init__(self, num, prime):
		if num >= prime or num < 0:
			error = 'Num {} not in field range 0 to {}'.format(
				num, prime - 1)
			raise ValueError(error)
		self.num = num
		self.prime = prime

	def __repr__(self):
		return 'FieldElement_{}({})'.format(self.prime, self.num)

	def __eq__(self, other):
		if other is None:
			return False
		return self.num == other.num and self.prime == other.prime

a = FieldElement(7, 13)
b = FieldElement(6, 13)
print(a==b)
print(a==a)

$ python3 app.py
False
True

[TypeScript] リストの中から指定したテキスト複数を表示したい

– localstorageに値を保持して、指定した順番に表示する
– data.splice(0)で配列の値をゼロにする
index.ts

let msg:HTMLParagraphElement
let table:HTMLTableElement

const tweets:string[] = [
	"テキスト1です",
	"テキスト2です",
	"テキスト3です",
	"テキスト4です",
	"テキスト5です"
]

const message = `<h2><a id="title">Tweet</a></h2>
	<p>これは選択したtweetが順番に表示されます</p>`

const data:string[] = []

function doAction(event:any){
	let id = event.target.dataset.id

	const tweet = tweets[id]
	tweet_data.add(tweet)
	tweet_data.save()
	const data = tweet_data.load()
	let disp = ''
	for(let item of data){
		disp += '<h2>'+ item +'</h2>'
	} 
	msg = document.querySelector('#msg')
	msg.innerHTML = disp
}

function doInitial(){
	data.splice(0)
	localStorage.removeItem('tweet_data')
	msg = document.querySelector('#msg')
	msg.innerHTML = message
}

class TweetData {

	add(tweet:string):void {
		data.push(tweet)
	}

	save():void {
		localStorage.setItem('tweet_data', JSON.stringify(data))
	}
	load():string {
		return JSON.parse(localStorage.getItem('tweet_data'))
	}
}

const tweet_data = new TweetData()

function getHtml(tweets:string[]):void {
	table = document.querySelector('#table')
	let html = '<thead><th>Tweet</th><th>Click</th></thead><tbody>'
	let i:number = 0
	for(let item of tweets) {
		html += '<tr><td>' + item + '</td><td><button class="btn btn-primary" id="btn'+i+'" data-id="' + i +'">Click</button></td></tr>'
		i++
	}
	html + '</tbody>'
	table.innerHTML = html
}


window.addEventListener('load', ()=> {
	msg = document.querySelector('#msg')
	msg.innerHTML = message
	getHtml(tweets)
	for(let i=0; i < tweets.length; i++) {
		document.querySelector('#btn'+i).addEventListener('click', doAction)
	}
	document.querySelector('#initial').addEventListener('click', doInitial)
})

[TypeScript] リストの中から指定したテキストを表示したい

index.ts

let msg:HTMLParagraphElement
let table:HTMLTableElement

const tweets:string[] = [
	"テキスト1です",
	"テキスト2です",
	"テキスト3です",
	"テキスト4です",
	"テキスト5です"
]

const message = `<h2><a id="title">This is message</a></h2>
	<p>これはTypeScriptで表示したコンテンツです。</p>`

function getHtml(tweets:string[]):void {
	table = document.querySelector('#table')
	let html = '<thead><th>Tweet</th></thead><tbody>'
	for(let item of tweets) {
		html += '<tr><td>' + item + '</td></tr>'
	}
	html + '</tbody>'
	table.innerHTML = html
}

window.addEventListener('load', ()=> {
	msg = document.querySelector('#msg')
	msg.innerHTML = message
	getHtml(tweets)
})

### クリックしたテキストを表示
index.ts

let msg:HTMLParagraphElement
let table:HTMLTableElement

const tweets:string[] = [
	"テキスト1です",
	"テキスト2です",
	"テキスト3です",
	"テキスト4です",
	"テキスト5です"
]

const message = `<h2><a id="title">Tweet</a></h2>
	<p>これは選択したtweetが表示されます</p>`

function doAction(event:any){
	let id = event.target.dataset.id

	const tweet = tweets[id]
	const disp = '<h2>'+ tweet +'</h2>'

	msg = document.querySelector('#msg')
	msg.innerHTML = disp
}

function getHtml(tweets:string[]):void {
	table = document.querySelector('#table')
	let html = '<thead><th>Tweet</th><th>Click</th></thead><tbody>'
	let i:number = 0
	for(let item of tweets) {
		html += '<tr><td>' + item + '</td><td><button class="btn btn-primary" id="btn'+i+'" data-id="' + i +'">Click</button></td></tr>'
		i++
	}
	html + '</tbody>'
	table.innerHTML = html
}

window.addEventListener('load', ()=> {
	msg = document.querySelector('#msg')
	msg.innerHTML = message
	getHtml(tweets)
	for(let i=0; i < tweets.length; i++) {
		document.querySelector('#btn'+i).addEventListener('click', doAction)
	}
})

クリックしたテキストを表示なら、割と簡単にできる

[TypeScript] TypeORM

$ npm install sqlite3
$ npm install typeorm
$ npm install @nestjs/typeorm

ormconfig.json

{
	"type": "sqlite",
	"database": "data/database.sqlite3",
	"entities": [
		"dist/entities/**/*.entity.js"
	],
	"migrations": [
		"dist/migrations/**/*.js"
	]
}

app.moudle.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [TypeOrmModule.forRoot()],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

src/entities/mydata.entity.ts

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Mydata {
	@PrimaryGeneratedColumn()
	id: number

	@Column({length: 20})
	name: string

	@Column({length: 100})
	pass: string

	@Column({length: 100, nullable:true})
	mail: string

	@Column()
	age:number
}

### migration
$ npm run build
$ npx typeorm migration:generate -n mydata_migration -d src/migrations
$ npm run build
$ npx typeorm migration:run

$ npx nest generate module mydata
$ npx nest generate service mydata
$ npx nest generate controller mydata

mydata.module.ts

import { Module } from '@nestjs/common';
import { MydataService } from './mydata.service';
import { MydataController } from './mydata.controller';

import { Mydata } from '../entities/mydata.entity' 
import { TypeOrmModule } from '@nestjs/typeorm'

@Module({
  imports: [TypeOrmModule.forFeature([Mydata])],
  providers: [MydataService],
  controllers: [MydataController]
})
export class MydataModule {}

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MydataModule } from './mydata/mydata.module';

@Module({
  imports: [TypeOrmModule.forRoot(), MydataModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

mydata.service.ts

import { Injectable } from '@nestjs/common';

import { Repository } from 'typeorm'
import { InjectRepository } from '@nestjs/typeorm'
import { Mydata } from '../entities/mydata.entity'

@Injectable()
export class MydataService {
	constructor(
		@InjectRepository(Mydata)
		private readonly mydataRepository: Repository<Mydata>
	) {}

	getAll():Promise<Mydata[]>{
		return this.mydataRepository.find()
	}
}

mydata.controller.ts

import { Controller } from '@nestjs/common';
import { MydataService } from './mydata.service'

@Controller('mydata')
export class MydataController {
	constructor(private readonly mydataService: MydataService){}

	@Get('/')
	root():Promise<any[]>{
		return this.mydataService.getAll()
	}
}

[TypeScript] Nest.js

$ sudo npm install @nestjs/cli -g
$ npx nest new nest_app
> npm
$ npm run start:dev
http://192.168.34.10:3000/
hello worldと表示されている

$ npm install ejs

nest-cli.json

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
  	"assets": ["**/*.ejs"]
  }
}

main.ts

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from './app.module';
import { join } from 'path'

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);

  app.useStaticAssets(join(__dirname, '..', 'public'))
  app.setBaseViewsDir(join(__dirname, '..', 'views'))
  app.setViewEngine('ejs')
  
  await app.listen(3000);
}
bootstrap();

views/index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%= title %></title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
</head>
<body>
  <h1 class="bg-primary text-white p-2"><%= header %></h1>
  <div class="container py-2">
  	<h2 class="mb-3"><%= title %></h2>
  	<div class="alert alert-primary">
  		<%= message %>
  	</div>
  </div>
</body>
</html>

src/app.controller.ts

import { Controller, Get, Render } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  @Render('index')
  root(){
  	return {
  		title: 'Nest sample app',
  		header: 'Nest.js',
  		message: 'Hello world!'
  	}
  }
}

index.ejs

<body>
  <h1 class="bg-primary text-white p-2"><%= title %></h1>
  <div class="container py-2">
  	<h2 class="mb-3"><%= msg %></h2>
  	<div class="alert alert-primary">
  		  <form method="post" action="/">
            <div class="mb-2">
              <label>ID:</label>
              <input type="text" name="id" class="form-control">
            </div>
            <div class="mb-2">
              <label>password:</label>
              <input type="password" name="pass" class="form-control">
            </div>
            <div>
              <input type="submit" value="送信" class="btn btn-info">
            </div>
        </form>
  	</div>
  </div>
</body>

src/app.controller.ts

import { Controller, Get, Post, Body, Render } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('/')
  @Render('index')
  root(){
  	return {
  		title: 'Nest app',
  		msg: 'send form:'
  	}
  }

  @Post('/')
  @Render('index')
  send(@Body() form:any){
  	return {
  		title: 'Nest form',
  		msg: JSON.stringify(form)
  	}
  }
}

### Ajax
app.controller.ts

  @Post('/')
  send(@Body() form:any){
  	return form
  }

index.ejs

  <script src="index.js"></script>
</head>
<body>
  <h1 class="bg-primary text-white p-2"><%= title %></h1>
  <div class="container py-2">
  	<h2 class="mb-3"><%= msg %></h2>
  	<div class="alert alert-primary">
            <div class="mb-2">
              <label>ID:</label>
              <input type="text" name="id" class="form-control">
            </div>
            <div class="mb-2">
              <label>password:</label>
              <input type="password" name="pass" class="form-control">
            </div>
            <div>
              <input type="submit" value="送信" class="btn btn-info">
            </div>
  	</div>
  </div>
</body>

public/index.ts

import { Controller, Get, Post, Body, Render } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get('/')
  @Render('index')
  root(){
  	return {
  		title: 'Nest app',
  		msg: 'send form:'
  	}
  }

  @Post('/')
  send(@Body() form:any){
  	return form
  }
}

なんか上手く動いていないような気がするが…

[TypeScript] express

$ sudo npm install -g express-generator
$ npx express -e express_app
$ cd express_app
$ npm install
$ npm run start
http://192.168.34.10:3000/

$ sudo npm install -g express-generator-typescript
$ npx express-generator-typescript express_type_app
$ cd express_type_app
$ npm run start:dev

$ npm install ejs
src/routes/hello.ts

import { Request, Response, Router } from 'express'

const router:Router = Router()

router.get('/', function(req:Request,
		res:Response):void{
	res.render('hello', {
		header:'Hello page',
		title: 'Hello!!',
		msg: 'This is HEllo page!'
	})
})
export default router

src/Server.ts

import helloRouter from './routes/hello'

app.set('view engine', 'ejs')
app.use('/hello', helloRouter)

src/views/hello.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%= title %></title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
</head>
<body>
  <h1 class="bg-primary text-white p-2"><%= header %></h1>
  <div class="container py-2">
  	<h2 class="mb-3"><%= title %></h2>
  	<div class="alert alert-primary">
  		<%= msg %>
  	</div>
  </div>
</body>
</html>

http://192.168.34.10:3000/hello

なかなか凄いわ

[TypeScript] Vue.js

$ sudo npm install -g @vue/cli
$ npm install –save vue-class-component
$ npx vue create vue3_type_app
Manually select features
◯ TypeScript (スペースキーでセットする)
❯ 3.x
❯ ESLint with error prevention only
❯◉ Lint on save
❯ In dedicated config files

App.vue

<template>
  <HelloWorld />
</template>

HelloWorld.vue

<script lang="tsx">
import { VNode } from 'vue'
import { Vue } from 'vue-class-component'

export default class HelloWorld extends Vue {
  msg = "Vue sample."
  val = 1

  doAction():void {
    this.val += 1
  }

  render():VNode {
    return(<div>
      <h1 class="bg-info text-white p-2">{this.msg}</h1>
      <div class="container">
        <h2 class="my-3">number counter.</h2>
        <div class="alert alert-info">
          <h3 onClick={this.doAction}>{this.val} count.</h3>
        </div>
      </div>
    </div>)
  }

}
</script>

node_modules/vue-class-component/lib”‘ has no exported member ‘Vue’.

うーん、上手くいかんな…