Popular New Releases in Blockchain
bitcoin
Bitcoin Core 22.0
go-ethereum
Osun (v1.10.16)
lerna
v4.0.0
openzeppelin-contracts
less.js
v4.1.2
Popular Libraries in Blockchain
by bitcoin c++
63479 MIT
Bitcoin Core integration/staging tree
by ethereum go
35547 LGPL-3.0
Official Go implementation of the Ethereum protocol
by lerna javascript
31453 MIT
:dragon: A tool for managing JavaScript projects with multiple packages.
by OpenZeppelin javascript
17136 MIT
OpenZeppelin Contracts is a library for secure smart contract development.
by bitcoinbook python
16943 NOASSERTION
Mastering Bitcoin 2nd Edition - Programming the Open Blockchain
by less javascript
16769 Apache-2.0
Less. The dynamic stylesheet language.
by ethereum c++
16189 GPL-3.0
Solidity, the Smart Contract Programming Language
by chaozh javascript
15698 Apache-2.0
收集所有区块链(BlockChain)技术开发相关资料,包括Fabric和Ethereum开发资料
by amark javascript
15597 NOASSERTION
An open source cybersecurity protocol for syncing decentralized graph data.
Trending New libraries in Blockchain
by project-serum rust
1899 Apache-2.0
⚓ Solana Sealevel Framework
by tharsis go
1619 LGPL-3.0
Ethermint is a scalable and interoperable Ethereum library, built on Proof-of-Stake with fast-finality using the Cosmos SDK.
by ava-labs go
1535 BSD-3-Clause
Go implementation of an Avalanche node.
by zhuowei rust
1370
C++ `std::unique_ptr` that represents each object as an NFT on the Ethereum blockchain
by binance-chain go
1343 LGPL-3.0
A Binance Smart Chain client based on the go-ethereum fork
by ethereum typescript
1303 MIT
Remix is a browser-based compiler and IDE that enables users to build Ethereum contracts with Solidity language and to debug transactions.
by mobilecoinfoundation rust
1057 NOASSERTION
Private payments for mobile devices.
by AleoHQ rust
1042 GPL-3.0
A Decentralized Operating System for Zero-Knowledge Applications
by dfinity rust
997 NOASSERTION
Internet Computer blockchain source: the client/replica software run by nodes
Top Authors in Blockchain
1
56 Libraries
27989
2
53 Libraries
3514
3
36 Libraries
16280
4
33 Libraries
65831
5
30 Libraries
7536
6
29 Libraries
1415
7
26 Libraries
2014
8
25 Libraries
3119
9
21 Libraries
826
10
20 Libraries
3145
1
56 Libraries
27989
2
53 Libraries
3514
3
36 Libraries
16280
4
33 Libraries
65831
5
30 Libraries
7536
6
29 Libraries
1415
7
26 Libraries
2014
8
25 Libraries
3119
9
21 Libraries
826
10
20 Libraries
3145
Trending Kits in Blockchain
If you knew 2 + 3 = 5, you might have a trillion-dollar idea! Jack Dorsey’s TBD gave us a quick refresher in arithmetic with their Web5 announcement. Well, what is Web 5? Web 2 + Web 3 = Web 5 !!! Is it really worth the hype to create another new buzzword? It could stem from Jack’s criticism of Web 3 funding a few months ago. Web 3 is still evolving and has plenty of room to adapt to evolving ideas. While the market dynamics, funds, and tech titans slug it out to settle on 3, 5, or maybe 4 for a name, the concepts are useful for technologists to review and adopt. Web 5 uses Bitcoin for the monetization layer and blockchain and Web 2 technologies for other areas. So in some sense, it is a blend of Web 2 and Web 3. Both Web 3 and Web 5 aspire to bring in user control over their data and identity. This kandi kit explores the open source libraries across the core Web 5 components of decentralized identifiers, decentralized web node, self-sovereign identity service and self-sovereign identity SDK.
If you’re building a decentralized app, or dApp—and who isn’t these days?—you’ll probably need to integrate with a DAO. Decentralized autonomous organizations, or DAOs, are the future of internet communities. They’re literally transparent computer programs that run on rules established by their members. Imagine that you're part of a community, say, an interest group, and you want to build something together. Now imagine that you could do that over the internet, without ever having to physically meet up or travel. Now imagine that this organization was governed not by a centralized leader, but by its members. Enter decentralized autonomous organizations (DAOs). A DAO is a social organization embodied by rules integrated into a transparent computer program, under the control of organization members. In other words, it's an online community of people who have a shared interest in building something together—and it's controlled entirely by those people. Members come together to build the organization, establish the objectives, and set the rules for funding the DAO mission. The core is establishing rules through community voting: these are established as smart contracts—pieces of code that cannot be changed without approval from members of the community. Some popular DAOs include Raid Guild, Metafactory, Aragon, KyberDAO, Saint Fame, and others. Maybe you want to start a DAO because you have a specific mission in mind that could benefit from an open-source approach, or maybe you're just curious about what's out there. Either way, we're here to help! Here are some open-source libraries that can help you get started building your own applications for some of the more popular DAOs.
Trending Discussions on Blockchain
Why Metamask if web3.js can interact directly with ganache?
Error: Property 'body' cannot be accessed on 'Response?' because it is potentially null
How to send a web3 transaction from a test account of RSKj regtest blockchain node
How can I convert an [u8] hex ascii representation to a u64
The transaction declared chain ID 5777, but the connected node is on 1337
How to locally unit-test Chainlink's Verifiable Random Function?
I want to get the address from mnemonic with the proper derivation path
how to sign a message with ecdsa privatekey using golang?
Flag provided but not defined: -rpc
ParserError: Source file requires different compiler version
QUESTION
Why Metamask if web3.js can interact directly with ganache?
Asked 2022-Mar-30 at 17:55I am new to blockchain app development, I saw a project where ganache accounts are imported into Metamask, then web3.js is used to access and print those accounts and balances on Frontend (user interface).
If web3.js can directly access ganache blockchain accounts and balances, why do we need Metamask in between?
ANSWER
Answered 2022-Feb-08 at 09:11If web3.js can directly acccess ganache blockchain accounts and balances, why we need metamask in between?
In this case, you don't need MetaMask to sign the transaction, as the node (Ganache) holds your private key.
But in a public environment (testnets and mainnet), the node doesn't hold your private key, so you'd need to sign the transaction using MetaMask (or any other tool that holds the private key).
QUESTION
Error: Property 'body' cannot be accessed on 'Response?' because it is potentially null
Asked 2022-Mar-29 at 00:29so I'am trying to learn dart and flutter and everything went well so far. But now I'am stuck at an error which I cannot handle. I coded a function which is supposed to asynchronously return the actual BTC price from https://blockchain.info/ticker.
Only thing it returns is errors:
1Error: Property 'body' cannot be accessed on 'Response?' because it is potentially null.
2 - 'Response' is from 'package:http/src/response.dart' ('/D:/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.4/lib/src/response.dart').
3Try accessing using ?. instead.
4 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
5 ^^^^
6/D:/flutter/packages/flutter/lib/src/widgets/async.dart:242:12: Context: 'data' refers to a property so it couldn't be promoted.
7See http://dart.dev/go/non-promo-property
8 final T? data;
9 ^
10
My Code:
1Error: Property 'body' cannot be accessed on 'Response?' because it is potentially null.
2 - 'Response' is from 'package:http/src/response.dart' ('/D:/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.4/lib/src/response.dart').
3Try accessing using ?. instead.
4 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
5 ^^^^
6/D:/flutter/packages/flutter/lib/src/widgets/async.dart:242:12: Context: 'data' refers to a property so it couldn't be promoted.
7See http://dart.dev/go/non-promo-property
8 final T? data;
9 ^
10import 'dart:convert';
11import 'package:flutter/cupertino.dart';
12import 'package:flutter/material.dart';
13import 'package:http/http.dart' as http;
14
15Future<http.Response> fetchBTCPrice() async {
16 final response = await http.get(Uri.https('blockhain.info', 'ticker'));
17 return response;
18}
19
20Widget buildBTCPrice() {
21 return FutureBuilder<http.Response>(
22 future: fetchBTCPrice(),
23 builder: (context, snapshot) {
24 if (snapshot.hasData) {
25 int? statusCode = snapshot.data?.statusCode;
26 if (statusCode == 200) {
27 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
28 }
29 return Text('$statusCode');
30
31 } else if (snapshot.hasError) {
32 return Text('${snapshot.error}');
33 }
34 return CircularProgressIndicator();
35 },
36 );
37}
38
39class BTCPrice {
40 final double eur;
41 BTCPrice({required this.eur});
42
43 factory BTCPrice.fromJson(Map<String, dynamic> json) {
44 print(json);
45 return BTCPrice(
46 eur: json['eur']['15m']
47 );
48 }
49}
50
Last things to mention: I'am running the application on a Android Emulator powerd by Android Studio; and please feel free to hand over any advice you have (in terms of code improvement), even if it is not fixing my issue.
ANSWER
Answered 2022-Mar-29 at 00:29To get rid of that error you need to use the bang operator to tell the compiler that snapshot.data
won't be null.
1Error: Property 'body' cannot be accessed on 'Response?' because it is potentially null.
2 - 'Response' is from 'package:http/src/response.dart' ('/D:/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.4/lib/src/response.dart').
3Try accessing using ?. instead.
4 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
5 ^^^^
6/D:/flutter/packages/flutter/lib/src/widgets/async.dart:242:12: Context: 'data' refers to a property so it couldn't be promoted.
7See http://dart.dev/go/non-promo-property
8 final T? data;
9 ^
10import 'dart:convert';
11import 'package:flutter/cupertino.dart';
12import 'package:flutter/material.dart';
13import 'package:http/http.dart' as http;
14
15Future<http.Response> fetchBTCPrice() async {
16 final response = await http.get(Uri.https('blockhain.info', 'ticker'));
17 return response;
18}
19
20Widget buildBTCPrice() {
21 return FutureBuilder<http.Response>(
22 future: fetchBTCPrice(),
23 builder: (context, snapshot) {
24 if (snapshot.hasData) {
25 int? statusCode = snapshot.data?.statusCode;
26 if (statusCode == 200) {
27 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
28 }
29 return Text('$statusCode');
30
31 } else if (snapshot.hasError) {
32 return Text('${snapshot.error}');
33 }
34 return CircularProgressIndicator();
35 },
36 );
37}
38
39class BTCPrice {
40 final double eur;
41 BTCPrice({required this.eur});
42
43 factory BTCPrice.fromJson(Map<String, dynamic> json) {
44 print(json);
45 return BTCPrice(
46 eur: json['eur']['15m']
47 );
48 }
49}
50if (statusCode == 200) {
51 return Text(
52 "${BTCPrice.fromJson(jsonDecode(snapshot.data!.body)).eur}"); // adding ! on data
53}
54
The unrelated error you mentioned in your comment:
unexpected character (at character 1) <html><head><title>loading...</title></head><body><script type='text/javasc... ^
would be fixed by changing your GET
request from this
1Error: Property 'body' cannot be accessed on 'Response?' because it is potentially null.
2 - 'Response' is from 'package:http/src/response.dart' ('/D:/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.4/lib/src/response.dart').
3Try accessing using ?. instead.
4 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
5 ^^^^
6/D:/flutter/packages/flutter/lib/src/widgets/async.dart:242:12: Context: 'data' refers to a property so it couldn't be promoted.
7See http://dart.dev/go/non-promo-property
8 final T? data;
9 ^
10import 'dart:convert';
11import 'package:flutter/cupertino.dart';
12import 'package:flutter/material.dart';
13import 'package:http/http.dart' as http;
14
15Future<http.Response> fetchBTCPrice() async {
16 final response = await http.get(Uri.https('blockhain.info', 'ticker'));
17 return response;
18}
19
20Widget buildBTCPrice() {
21 return FutureBuilder<http.Response>(
22 future: fetchBTCPrice(),
23 builder: (context, snapshot) {
24 if (snapshot.hasData) {
25 int? statusCode = snapshot.data?.statusCode;
26 if (statusCode == 200) {
27 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
28 }
29 return Text('$statusCode');
30
31 } else if (snapshot.hasError) {
32 return Text('${snapshot.error}');
33 }
34 return CircularProgressIndicator();
35 },
36 );
37}
38
39class BTCPrice {
40 final double eur;
41 BTCPrice({required this.eur});
42
43 factory BTCPrice.fromJson(Map<String, dynamic> json) {
44 print(json);
45 return BTCPrice(
46 eur: json['eur']['15m']
47 );
48 }
49}
50if (statusCode == 200) {
51 return Text(
52 "${BTCPrice.fromJson(jsonDecode(snapshot.data!.body)).eur}"); // adding ! on data
53}
54final response = await http.get(Uri.https('blockhain.info', 'ticker'));
55
to this
1Error: Property 'body' cannot be accessed on 'Response?' because it is potentially null.
2 - 'Response' is from 'package:http/src/response.dart' ('/D:/flutter/.pub-cache/hosted/pub.dartlang.org/http-0.13.4/lib/src/response.dart').
3Try accessing using ?. instead.
4 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
5 ^^^^
6/D:/flutter/packages/flutter/lib/src/widgets/async.dart:242:12: Context: 'data' refers to a property so it couldn't be promoted.
7See http://dart.dev/go/non-promo-property
8 final T? data;
9 ^
10import 'dart:convert';
11import 'package:flutter/cupertino.dart';
12import 'package:flutter/material.dart';
13import 'package:http/http.dart' as http;
14
15Future<http.Response> fetchBTCPrice() async {
16 final response = await http.get(Uri.https('blockhain.info', 'ticker'));
17 return response;
18}
19
20Widget buildBTCPrice() {
21 return FutureBuilder<http.Response>(
22 future: fetchBTCPrice(),
23 builder: (context, snapshot) {
24 if (snapshot.hasData) {
25 int? statusCode = snapshot.data?.statusCode;
26 if (statusCode == 200) {
27 return Text("${BTCPrice.fromJson(jsonDecode(snapshot.data.body)).eur}");
28 }
29 return Text('$statusCode');
30
31 } else if (snapshot.hasError) {
32 return Text('${snapshot.error}');
33 }
34 return CircularProgressIndicator();
35 },
36 );
37}
38
39class BTCPrice {
40 final double eur;
41 BTCPrice({required this.eur});
42
43 factory BTCPrice.fromJson(Map<String, dynamic> json) {
44 print(json);
45 return BTCPrice(
46 eur: json['eur']['15m']
47 );
48 }
49}
50if (statusCode == 200) {
51 return Text(
52 "${BTCPrice.fromJson(jsonDecode(snapshot.data!.body)).eur}"); // adding ! on data
53}
54final response = await http.get(Uri.https('blockhain.info', 'ticker'));
55final response = await http.get(Uri.parse('https://blockchain.info/ticker'));
56
QUESTION
How to send a web3 transaction from a test account of RSKj regtest blockchain node
Asked 2022-Mar-25 at 10:34I am creating a DApp that connects to a smart contract deployed on a local test RSK blockchain (regtest) run by RSKj Java app. I intend to send transactions via Web3 connected to Metamask. In DApp I am getting the accounts list by sending a Web3 request:
1const accounts = await web3.eth.getAccounts()
2
Further, accounts
will contain:
1const accounts = await web3.eth.getAccounts()
2[
3 '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
4 '0x7986b3DF570230288501EEa3D890bd66948C9B79',
5 '0x0a3aA774752ec2042c46548456c094A76C7F3a79',
6 '0xCF7CDBbB5F7BA79d3ffe74A0bBA13FC0295F6036',
7 '0x39B12C05E8503356E3a7DF0B7B33efA4c054C409',
8 '0xc354D97642FAa06781b76Ffb6786f72cd7746C97',
9 '0xDEBe71E1dE41Fc77C44Df4b6Db940026E31b0e71',
10 '0x7857288e171C6159C5576d1bD9AC40c0c48a771C',
11 '0xa4Dea4d5C954f5FD9e87f0e9752911E83a3D18b3',
12 '0x09a1edA29F664ac8f68106F6567276dF0C65D859',
13 '0xeC4ddeB4380Ad69B3E509BaAd9f158CDF4E4681d'
14]
15
How do I import these accounts (or at least the first one of them) to Metamask in order to send transactions to the smart contract?
ANSWER
Answered 2022-Mar-25 at 10:34The first account from the list is referred as a “cow” seed in this file in RSKj. You can take the corresponding private key from there.
Do the following:
- copy the private key
c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4
, - open your Metamask browser plugin
- select
regtest
network - import the account
- Account icon in the upper right corner
- Import account
- ‘Paste your private key string here:’
- Set the just imported account as an active one
- Enjoy sending your transactions
QUESTION
How can I convert an [u8] hex ascii representation to a u64
Asked 2022-Mar-17 at 10:57I would like to convert my bytes array into a u64.
For example
b"00"
should return 0u64
b"0a"
should return 10u64
I am working on blockchain, so I must find something efficient.
For example, my current function is not efficient at all.
1let number_string = String::from_utf8_lossy(&my_bytes_array)
2 .to_owned()
3 .to_string();
4let number = u64::from_str_radix(&number_string , 16).unwrap();
5
I have also tried
1let number_string = String::from_utf8_lossy(&my_bytes_array)
2 .to_owned()
3 .to_string();
4let number = u64::from_str_radix(&number_string , 16).unwrap();
5let number = u64::from_le_bytes(my_bytes_array);
6
But I got this error mismatched types expected array [u8; 8], found &[u8]
ANSWER
Answered 2022-Mar-16 at 20:21How about?
1let number_string = String::from_utf8_lossy(&my_bytes_array)
2 .to_owned()
3 .to_string();
4let number = u64::from_str_radix(&number_string , 16).unwrap();
5let number = u64::from_le_bytes(my_bytes_array);
6pub fn hex_to_u64(x: &[u8]) -> Option<u64> {
7 let mut result: u64 = 0;
8 for i in x {
9 result *= 16;
10 result += (*i as char).to_digit(16)? as u64;
11 }
12 Some(result)
13}
14
QUESTION
The transaction declared chain ID 5777, but the connected node is on 1337
Asked 2022-Mar-11 at 02:52I am trying to deploy my SimpleStorage.sol contract to a ganache local chain by making a transaction using python. It seems to have trouble connecting to the chain.
1from solcx import compile_standard
2from web3 import Web3
3import json
4import os
5from dotenv import load_dotenv
6
7load_dotenv()
8
9with open("./SimpleStorage.sol", "r") as file:
10 simple_storage_file = file.read()
11
12compiled_sol = compile_standard(
13 {
14 "language": "Solidity",
15 "sources": {"SimpleStorage.sol": {"content": simple_storage_file}},
16 "settings": {
17 "outputSelection": {
18 "*": {"*": ["abi", "metadata", "evm.bytecode", "evm.sourceMap"]}
19 }
20 },
21 },
22 solc_version="0.6.0",
23)
24
25with open("compiled_code.json", "w") as file:
26 json.dump(compiled_sol, file)
27
28
29# get bytecode
30bytecode = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["evm"][
31 "bytecode"
32]["object"]
33
34
35# get ABI
36abi = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["abi"]
37
38# to connect to ganache blockchain
39w3 = Web3(Web3.HTTPProvider("HTTP://127.0.0.1:7545"))
40chain_id = 5777
41my_address = "0xca1EA31e644F13E3E36631382686fD471c62267A"
42private_key = os.getenv("PRIVATE_KEY")
43
44
45# create the contract in python
46
47SimpleStorage = w3.eth.contract(abi=abi, bytecode=bytecode)
48
49# get the latest transaction
50nonce = w3.eth.getTransactionCount(my_address)
51
52# 1. Build a transaction
53# 2. Sign a transaction
54# 3. Send a transaction
55
56
57transaction = SimpleStorage.constructor().buildTransaction(
58 {"chainId": chain_id, "from": my_address, "nonce": nonce}
59)
60print(transaction)
61
62
It seems to be connected to the ganache chain because it prints the nonce, but when I build and try to print the transaction here is the entire traceback call I am receiving
1from solcx import compile_standard
2from web3 import Web3
3import json
4import os
5from dotenv import load_dotenv
6
7load_dotenv()
8
9with open("./SimpleStorage.sol", "r") as file:
10 simple_storage_file = file.read()
11
12compiled_sol = compile_standard(
13 {
14 "language": "Solidity",
15 "sources": {"SimpleStorage.sol": {"content": simple_storage_file}},
16 "settings": {
17 "outputSelection": {
18 "*": {"*": ["abi", "metadata", "evm.bytecode", "evm.sourceMap"]}
19 }
20 },
21 },
22 solc_version="0.6.0",
23)
24
25with open("compiled_code.json", "w") as file:
26 json.dump(compiled_sol, file)
27
28
29# get bytecode
30bytecode = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["evm"][
31 "bytecode"
32]["object"]
33
34
35# get ABI
36abi = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["abi"]
37
38# to connect to ganache blockchain
39w3 = Web3(Web3.HTTPProvider("HTTP://127.0.0.1:7545"))
40chain_id = 5777
41my_address = "0xca1EA31e644F13E3E36631382686fD471c62267A"
42private_key = os.getenv("PRIVATE_KEY")
43
44
45# create the contract in python
46
47SimpleStorage = w3.eth.contract(abi=abi, bytecode=bytecode)
48
49# get the latest transaction
50nonce = w3.eth.getTransactionCount(my_address)
51
52# 1. Build a transaction
53# 2. Sign a transaction
54# 3. Send a transaction
55
56
57transaction = SimpleStorage.constructor().buildTransaction(
58 {"chainId": chain_id, "from": my_address, "nonce": nonce}
59)
60print(transaction)
61
62Traceback (most recent call last):
63File "C:\Users\evens\demos\web3_py_simple_storage\deploy.py", line
6452, in <module>
65transaction = SimpleStorage.constructor().buildTransaction(
66File "C:\Python310\lib\site-packages\eth_utils\decorators.py", line
6718, in _wrapper
68return self.method(obj, *args, **kwargs)
69File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
70packages\web3\contract.py", line 684, in buildTransaction
71return fill_transaction_defaults(self.web3, built_transaction)
72File "cytoolz/functoolz.pyx", line 250, in
73cytoolz.functoolz.curry.__call__
74return self.func(*args, **kwargs)
75File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
76packages\web3\_utils\transactions.py", line 114, in
77fill_transaction_defaults
78default_val = default_getter(web3, transaction)
79File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
80packages\web3\_utils\transactions.py", line 60, in <lambda>
81'gas': lambda web3, tx: web3.eth.estimate_gas(tx),
82File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
83packages\web3\eth.py", line 820, in estimate_gas
84return self._estimate_gas(transaction, block_identifier)
85File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
86packages\web3\module.py", line 57, in caller
87result = w3.manager.request_blocking(method_str,
88File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
89packages\web3\manager.py", line 197, in request_blocking
90response = self._make_request(method, params)
91File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
92packages\web3\manager.py", line 150, in _make_request
93return request_func(method, params)
94File "cytoolz/functoolz.pyx", line 250, in
95cytoolz.functoolz.curry.__call__
96return self.func(*args, **kwargs)
97File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
98packages\web3\middleware\formatting.py", line 76, in
99apply_formatters
100response = make_request(method, params)
101File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
102packages\web3\middleware\gas_price_strategy.py", line 90, in
103middleware
104return make_request(method, params)
105File "cytoolz/functoolz.pyx", line 250, in
106cytoolz.functoolz.curry.__call__
107return self.func(*args, **kwargs)
108File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
109packages\web3\middleware\formatting.py", line 74, in
110apply_formatters
111response = make_request(method, formatted_params)
112File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
113packages\web3\middleware\attrdict.py", line 33, in middleware
114response = make_request(method, params)
115File "cytoolz/functoolz.pyx", line 250, in
116cytoolz.functoolz.curry.__call__
117return self.func(*args, **kwargs)
118File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
119packages\web3\middleware\formatting.py", line 74, in
120apply_formatters
121response = make_request(method, formatted_params)
122File "cytoolz/functoolz.pyx", line 250, in
123cytoolz.functoolz.curry.__call__
124return self.func(*args, **kwargs)
125File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
126packages\web3\middleware\formatting.py", line 73, in
127apply_formatters
128formatted_params = formatter(params)
129File "cytoolz/functoolz.pyx", line 503, in
130cytoolz.functoolz.Compose.__call__
131ret = PyObject_Call(self.first, args, kwargs)
132File "cytoolz/functoolz.pyx", line 250, in
133cytoolz.functoolz.curry.__call__
134return self.func(*args, **kwargs)
135File "C:\Python310\lib\site-packages\eth_utils\decorators.py", line
13691, in wrapper
137return ReturnType(result) # type: ignore
138File "C:\Python310\lib\site-packages\eth_utils\applicators.py", line
13922, in apply_formatter_at_index
140yield formatter(item)
141File "cytoolz/functoolz.pyx", line 250, in
142cytoolz.functoolz.curry.__call__
143File "cytoolz/functoolz.pyx", line 250, in
144cytoolz.functoolz.curry.__call__
145return self.func(*args, **kwargs)
146File "C:\Python310\lib\site-packages\eth_utils\applicators.py", line
14772, in apply_formatter_if
148return formatter(value)
149File "cytoolz/functoolz.pyx", line 250, in
150cytoolz.functoolz.curry.__call__
151return self.func(*args, **kwargs)
152File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
153packages\web3\middleware\validation.py", line 57, in
154validate_chain_id
155raise ValidationError(
156web3.exceptions.ValidationError: The transaction declared chain ID
1575777, but the connected node is on 1337
158
ANSWER
Answered 2022-Jan-17 at 18:17Had this issue myself, apparently it's some sort of Ganache CLI error but the simplest fix I could find was to change the network id in Ganache through settings>server to 1337. It restarts the session so you'd then need to change the address and private key variable.
If it's the same tutorial I'm doing, you're likely to come unstuck after this... the code for transaction should be:
1from solcx import compile_standard
2from web3 import Web3
3import json
4import os
5from dotenv import load_dotenv
6
7load_dotenv()
8
9with open("./SimpleStorage.sol", "r") as file:
10 simple_storage_file = file.read()
11
12compiled_sol = compile_standard(
13 {
14 "language": "Solidity",
15 "sources": {"SimpleStorage.sol": {"content": simple_storage_file}},
16 "settings": {
17 "outputSelection": {
18 "*": {"*": ["abi", "metadata", "evm.bytecode", "evm.sourceMap"]}
19 }
20 },
21 },
22 solc_version="0.6.0",
23)
24
25with open("compiled_code.json", "w") as file:
26 json.dump(compiled_sol, file)
27
28
29# get bytecode
30bytecode = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["evm"][
31 "bytecode"
32]["object"]
33
34
35# get ABI
36abi = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["abi"]
37
38# to connect to ganache blockchain
39w3 = Web3(Web3.HTTPProvider("HTTP://127.0.0.1:7545"))
40chain_id = 5777
41my_address = "0xca1EA31e644F13E3E36631382686fD471c62267A"
42private_key = os.getenv("PRIVATE_KEY")
43
44
45# create the contract in python
46
47SimpleStorage = w3.eth.contract(abi=abi, bytecode=bytecode)
48
49# get the latest transaction
50nonce = w3.eth.getTransactionCount(my_address)
51
52# 1. Build a transaction
53# 2. Sign a transaction
54# 3. Send a transaction
55
56
57transaction = SimpleStorage.constructor().buildTransaction(
58 {"chainId": chain_id, "from": my_address, "nonce": nonce}
59)
60print(transaction)
61
62Traceback (most recent call last):
63File "C:\Users\evens\demos\web3_py_simple_storage\deploy.py", line
6452, in <module>
65transaction = SimpleStorage.constructor().buildTransaction(
66File "C:\Python310\lib\site-packages\eth_utils\decorators.py", line
6718, in _wrapper
68return self.method(obj, *args, **kwargs)
69File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
70packages\web3\contract.py", line 684, in buildTransaction
71return fill_transaction_defaults(self.web3, built_transaction)
72File "cytoolz/functoolz.pyx", line 250, in
73cytoolz.functoolz.curry.__call__
74return self.func(*args, **kwargs)
75File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
76packages\web3\_utils\transactions.py", line 114, in
77fill_transaction_defaults
78default_val = default_getter(web3, transaction)
79File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
80packages\web3\_utils\transactions.py", line 60, in <lambda>
81'gas': lambda web3, tx: web3.eth.estimate_gas(tx),
82File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
83packages\web3\eth.py", line 820, in estimate_gas
84return self._estimate_gas(transaction, block_identifier)
85File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
86packages\web3\module.py", line 57, in caller
87result = w3.manager.request_blocking(method_str,
88File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
89packages\web3\manager.py", line 197, in request_blocking
90response = self._make_request(method, params)
91File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
92packages\web3\manager.py", line 150, in _make_request
93return request_func(method, params)
94File "cytoolz/functoolz.pyx", line 250, in
95cytoolz.functoolz.curry.__call__
96return self.func(*args, **kwargs)
97File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
98packages\web3\middleware\formatting.py", line 76, in
99apply_formatters
100response = make_request(method, params)
101File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
102packages\web3\middleware\gas_price_strategy.py", line 90, in
103middleware
104return make_request(method, params)
105File "cytoolz/functoolz.pyx", line 250, in
106cytoolz.functoolz.curry.__call__
107return self.func(*args, **kwargs)
108File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
109packages\web3\middleware\formatting.py", line 74, in
110apply_formatters
111response = make_request(method, formatted_params)
112File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
113packages\web3\middleware\attrdict.py", line 33, in middleware
114response = make_request(method, params)
115File "cytoolz/functoolz.pyx", line 250, in
116cytoolz.functoolz.curry.__call__
117return self.func(*args, **kwargs)
118File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
119packages\web3\middleware\formatting.py", line 74, in
120apply_formatters
121response = make_request(method, formatted_params)
122File "cytoolz/functoolz.pyx", line 250, in
123cytoolz.functoolz.curry.__call__
124return self.func(*args, **kwargs)
125File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
126packages\web3\middleware\formatting.py", line 73, in
127apply_formatters
128formatted_params = formatter(params)
129File "cytoolz/functoolz.pyx", line 503, in
130cytoolz.functoolz.Compose.__call__
131ret = PyObject_Call(self.first, args, kwargs)
132File "cytoolz/functoolz.pyx", line 250, in
133cytoolz.functoolz.curry.__call__
134return self.func(*args, **kwargs)
135File "C:\Python310\lib\site-packages\eth_utils\decorators.py", line
13691, in wrapper
137return ReturnType(result) # type: ignore
138File "C:\Python310\lib\site-packages\eth_utils\applicators.py", line
13922, in apply_formatter_at_index
140yield formatter(item)
141File "cytoolz/functoolz.pyx", line 250, in
142cytoolz.functoolz.curry.__call__
143File "cytoolz/functoolz.pyx", line 250, in
144cytoolz.functoolz.curry.__call__
145return self.func(*args, **kwargs)
146File "C:\Python310\lib\site-packages\eth_utils\applicators.py", line
14772, in apply_formatter_if
148return formatter(value)
149File "cytoolz/functoolz.pyx", line 250, in
150cytoolz.functoolz.curry.__call__
151return self.func(*args, **kwargs)
152File "C:\Users\evens\AppData\Roaming\Python\Python310\site-
153packages\web3\middleware\validation.py", line 57, in
154validate_chain_id
155raise ValidationError(
156web3.exceptions.ValidationError: The transaction declared chain ID
1575777, but the connected node is on 1337
158transaction =
159 SimpleStorage.constructor().buildTransaction( {
160 "gasPrice": w3.eth.gas_price,
161 "chainId": chain_id,
162 "from": my_address,
163 "nonce": nonce,
164})
165print(transaction)
166
Otherwise you get a value error if you don't set the gasPrice
QUESTION
How to locally unit-test Chainlink's Verifiable Random Function?
Asked 2022-Mar-08 at 04:12While trying to set up a basic self-hosted unit testing environment (and CI) that tests this Chainlink VRF random number contract, I am experiencing slight difficulties in how to simulate any relevant blockchains/testnets locally.
For example, I found this repository that tests Chainlinks VRF. However, for default deployment it suggests/requires a free KOVAN_RPC_URL
e.g. from Infura's site and even for "local deployment" it suggests/requires a free MAINNET_RPC_URL
from e.g. Alchemy's site.
I adopted a unit test environment from the waffle framework which is described as:
Filestructure1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10
AmIRichAlready.sol
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34
The RandomNumberConsumer.sol
filecontent is already on stackexange over here.
AmIRichAlready.test.ts
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78
mocha.opts
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82
package.json
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109
tsconfig.json
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109{
110 "compilerOptions": {
111 "declaration": true,
112 "esModuleInterop": true,
113 "lib": [
114 "ES2018"
115 ],
116 "module": "CommonJS",
117 "moduleResolution": "node",
118 "outDir": "dist",
119 "resolveJsonModule": true,
120 "skipLibCheck": true,
121 "strict": true,
122 "target": "ES2018"
123 }
124
125 // custom test in vrfContract
126 it('Tests if a random number is returned', async () => {
127 expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128 });
129}
130
waffle.json
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109{
110 "compilerOptions": {
111 "declaration": true,
112 "esModuleInterop": true,
113 "lib": [
114 "ES2018"
115 ],
116 "module": "CommonJS",
117 "moduleResolution": "node",
118 "outDir": "dist",
119 "resolveJsonModule": true,
120 "skipLibCheck": true,
121 "strict": true,
122 "target": "ES2018"
123 }
124
125 // custom test in vrfContract
126 it('Tests if a random number is returned', async () => {
127 expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128 });
129}
130{
131 "compilerType": "solcjs",
132 "compilerVersion": "0.6.2",
133 "sourceDirectory": "./src",
134 "outputDirectory": "./build"
135}
136
The yarn.lock
file content is a bit large, and it's auto-generated, so you can find it on the Waffle framework repository. Similarly, the package.json
can be found here, in the same repository.
One can also simply clone the repo with the specified filestructure here, and run the tests with the following commands:
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109{
110 "compilerOptions": {
111 "declaration": true,
112 "esModuleInterop": true,
113 "lib": [
114 "ES2018"
115 ],
116 "module": "CommonJS",
117 "moduleResolution": "node",
118 "outDir": "dist",
119 "resolveJsonModule": true,
120 "skipLibCheck": true,
121 "strict": true,
122 "target": "ES2018"
123 }
124
125 // custom test in vrfContract
126 it('Tests if a random number is returned', async () => {
127 expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128 });
129}
130{
131 "compilerType": "solcjs",
132 "compilerVersion": "0.6.2",
133 "sourceDirectory": "./src",
134 "outputDirectory": "./build"
135}
136git clone git@github.com:a-t-2/chainlink.git
137git clone git@github.com:a-t-2/test_vrf3.git
138cd test_vrf3
139sudo apt install npm
140npm install
141npm audit fix
142npm install --save-dev ethereum-waffle
143npm install @openzeppelin/contracts -D
144npm i chai -D
145npm i mocha -D
146rm -r build
147npx waffle
148npx mocha
149npm test
150
This will test the AmIRichAlready.sol
file and output:
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109{
110 "compilerOptions": {
111 "declaration": true,
112 "esModuleInterop": true,
113 "lib": [
114 "ES2018"
115 ],
116 "module": "CommonJS",
117 "moduleResolution": "node",
118 "outDir": "dist",
119 "resolveJsonModule": true,
120 "skipLibCheck": true,
121 "strict": true,
122 "target": "ES2018"
123 }
124
125 // custom test in vrfContract
126 it('Tests if a random number is returned', async () => {
127 expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128 });
129}
130{
131 "compilerType": "solcjs",
132 "compilerVersion": "0.6.2",
133 "sourceDirectory": "./src",
134 "outputDirectory": "./build"
135}
136git clone git@github.com:a-t-2/chainlink.git
137git clone git@github.com:a-t-2/test_vrf3.git
138cd test_vrf3
139sudo apt install npm
140npm install
141npm audit fix
142npm install --save-dev ethereum-waffle
143npm install @openzeppelin/contracts -D
144npm i chai -D
145npm i mocha -D
146rm -r build
147npx waffle
148npx mocha
149npm test
150 Am I Rich Already
151 ✓ checks if contract called balanceOf with certain wallet on the ERC20 token (249ms)
152 ✓ returns false if the wallet has less than 1000000 coins (190ms)
153 ✓ returns true if the wallet has at least 1000000 coins (159ms)
154 Tests if a random number is returned:
155 Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"RuntimeError","results":{"0x0a0b028de6cf6e8446853a300061305501136cefa5f5eb3e96afd95dbd73dd92":{"error":"revert","program_counter":609,"return":"0x"}},"hashes":["0x0a0b028de6cf6e8446853a300061305501136cefa5f5eb3e96afd95dbd73dd92"],"message":"VM Exception while processing transaction: revert"}, tx={"data":"0xdbdff2c1","to":{},"from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff","gasPrice":{"type":"BigNumber","hex":"0x77359400"},"type":0,"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.4.1)
156 at Logger.makeError (node_modules/@ethersproject/logger/src.ts/index.ts:225:28)
157 at Logger.throwError (node_modules/@ethersproject/logger/src.ts/index.ts:237:20)
158 at /home/name/git/trucol/tested/new_test/test_vrf3/node_modules/@ethersproject/abstract-signer/src.ts/index.ts:301:31
159 at process._tickCallback (internal/process/next_tick.js:68:7)
160
161
162
163 3 passing (4s)
164
Which set of files, file structure and commands do I need to automatically test whether the getRandomNumber()
contract returns an integer if sufficient "gas" is provided, and an error otherwise?
ANSWER
Answered 2021-Sep-09 at 04:35to test locally you need to make use of mocks which can simulate having an oracle network. Because you're working locally, a Chainlink node doesn't know about your local blockchain, so you can't actually do proper VRF requests. Note you can try deploy a local Chainlink node and a local blockchain and have them talk, but it isn't fully supported yet so you may get mixed results. Anyway, as per the hardhat starter kit that you linked, you can set the defaultNetwork to be 'hardhat' in the hardhat.config.js file, then when you deploy and run the integration tests (yarn test-integration), it will use mocks to mock up the VRF node, and to test the requesting of a random number. See the test here, and the mock contracts and linktoken get deployed here
QUESTION
I want to get the address from mnemonic with the proper derivation path
Asked 2022-Feb-23 at 00:41I am very new to blockchain programming and programming in general. I want to generate my SOL address using the mnemonic seed phrase with the derivation path "m/44'/501'/0'/0". I can't find a proper BIP44 module for python where you can specify the derivation path.
ANSWER
Answered 2022-Feb-23 at 00:41After a long search through the internet, I have finally found a way of solving my problem that I want to share with you.
1from bip_utils import *
2
3MNEMONIC = "...12 words phrase..."
4
5seed_bytes = Bip39SeedGenerator(MNEMONIC).Generate("")
6
7bip44_mst_ctx = Bip44.FromSeed(seed_bytes, Bip44Coins.SOLANA)
8
9bip44_acc_ctx = bip44_mst_ctx.Purpose().Coin().Account(0)
10
11bip44_chg_ctx = bip44_acc_ctx.Change(Bip44Changes.CHAIN_EXT)
12
13print(bip44_chg_ctx.PublicKey().ToAddress())
14
This code outputs the first address of your mnemonic. This is only for Sollet and Phantom wallet!
If you are using Solflare you can cut the line bip44_chg_ctx = bip44_acc_ctx.Change(Bip44Changes.CHAIN_EXT)
out!
QUESTION
how to sign a message with ecdsa privatekey using golang?
Asked 2022-Feb-20 at 14:48I am trying to sign a message in go
generated via hd wallet's private key using cosmos sdk. Below is the equivalent implementation in python which generates the signed message / signature as expected when submitted/verified is working properly but unable to get it working wtih Go
implementation. Any inputs for equivalent golang version of the python implementation is much appreciated. Thank you.
Python version uses sha256 , ecdsa but when using the equivalent cyrpto/ecdsa doesn't return valid signature.
Python
1 def test_sign_message(self):
2 """ Tests the ability of the signer to sing message """
3
4 # Loading up the signer object to use for the operation
5 signer: TestSigners = TestSigners.from_mnemonic("blast about old claw current first paste risk involve victory edit current")
6 sample_payload_to_sign = "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842'
7 # print("test".encode("UTF-8").hex())
8 s = signer.sign(sample_payload_to_sign)
9 print(s)
10
11
12from typing import List, Tuple, Dict, Union, Any
13from hdwallet.hdwallet import HDWallet
14from ecdsa.util import sigencode_der
15from ecdsa.curves import SECP256k1
16from ecdsa.keys import SigningKey
17import mnemonic
18import hashlib
19import ecdsa
20
21
22class TestSigners():
23
24 HD_WALLET_PARAMS: Dict[str, Tuple[int, bool]] = {
25 "purpose": (44, True),
26 "coinType": (1022, True),
27 "account": (0, True),
28 "change": (0, False),
29 }
30
31 def __init__(
32 self,
33 seed: Union[bytes, bytearray, str]
34 ) -> None:
35 """ Instantiates a new signer object from the seed phrase
36
37 Args:
38 seed (Union[bytes, bytearray, str]): The seed phrase used to generate the public and
39 private keys.
40 """
41
42 self.seed: Union[bytes, bytearray] = seed if isinstance(seed, (bytes, bytearray)) else bytearray.fromhex(seed)
43
44 @classmethod
45 def from_mnemonic(
46 cls,
47 mnemonic_phrase: Union[str, List[str], Tuple[str]]
48 ) -> 'Signer':
49 """
50 Instantiates a new Signer object from the mnemonic phrase passed.
51
52 Args:
53 mnemonic_phrase (Union[str, :obj:`list` of :obj:`str`, :obj:`tuple` of :obj:`str`):
54 A string, list, or a tuple of the mnemonic phrase. If the argument is passed as an
55 iterable, then it will be joined with a space.
56
57 Returns:
58 Signer: A new signer initalized through the mnemonic phrase.
59 """
60
61 # If the supplied mnemonic phrase is a list then convert it to a string
62 if isinstance(mnemonic_phrase, (list, tuple)):
63 mnemonic_string: str = " ".join(mnemonic_phrase)
64 else:
65 mnemonic_string: str = mnemonic_phrase
66
67 mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
68 (list, tuple)) else mnemonic_phrase
69
70 return cls(mnemonic.Mnemonic.to_seed(mnemonic_string))
71
72 def public_key(
73 self,
74 index: int = 0
75 ) -> str:
76 """
77 Gets the public key for the signer for the specified account index
78
79 Args:
80 index (int): The account index to get the public keys for.
81
82 Returns:
83 str: A string of the public key for the wallet
84 """
85
86 return str(self.hdwallet(index).public_key())
87
88 def private_key(
89 self,
90 index: int = 0
91 ) -> str:
92 """
93 Gets the private key for the signer for the specified account index
94
95 Args:
96 index (int): The account index to get the private keys for.
97
98 Returns:
99 str: A string of the private key for the wallet
100 """
101
102 return str(self.hdwallet(index).private_key())
103
104 def hdwallet(
105 self,
106 index: int = 0
107 ) -> HDWallet:
108 """
109 Creates an HDWallet object suitable for the Radix blockchain with the passed account index.
110
111 Args:
112 index (int): The account index to create the HDWallet object for.
113
114 Returns:
115 HDWallet: An HD wallet object created with the Radix Parameters for a given account
116 index.
117 """
118
119 hdwallet: HDWallet = HDWallet()
120 hdwallet.from_seed(seed=self.seed.hex())
121 for _, values_tuple in self.HD_WALLET_PARAMS.items():
122 value, hardened = values_tuple
123 hdwallet.from_index(value, hardened=hardened)
124 hdwallet.from_index(index, True)
125
126 return hdwallet
127
128 def sign(
129 self,
130 data: str,
131 index: int = 0
132 ) -> str:
133 """
134 Signs the given data using the private keys for the account at the specified account index.
135
136 Arguments:
137 data (str): A string of the data which we wish to sign.
138 index (int): The account index to get the private keys for.
139
140 Returns:
141 str: A string of the signed data
142 """
143
144 signing_key: SigningKey = ecdsa.SigningKey.from_string( # type: ignore
145 string=bytearray.fromhex(self.private_key(index)),
146 curve=SECP256k1,
147 hashfunc=hashlib.sha256
148 )
149
150 return signing_key.sign_digest( # type: ignore
151 digest=bytearray.fromhex(data),
152 sigencode=sigencode_der
153 ).hex()
154
GO ( Not Working )
1 def test_sign_message(self):
2 """ Tests the ability of the signer to sing message """
3
4 # Loading up the signer object to use for the operation
5 signer: TestSigners = TestSigners.from_mnemonic("blast about old claw current first paste risk involve victory edit current")
6 sample_payload_to_sign = "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842'
7 # print("test".encode("UTF-8").hex())
8 s = signer.sign(sample_payload_to_sign)
9 print(s)
10
11
12from typing import List, Tuple, Dict, Union, Any
13from hdwallet.hdwallet import HDWallet
14from ecdsa.util import sigencode_der
15from ecdsa.curves import SECP256k1
16from ecdsa.keys import SigningKey
17import mnemonic
18import hashlib
19import ecdsa
20
21
22class TestSigners():
23
24 HD_WALLET_PARAMS: Dict[str, Tuple[int, bool]] = {
25 "purpose": (44, True),
26 "coinType": (1022, True),
27 "account": (0, True),
28 "change": (0, False),
29 }
30
31 def __init__(
32 self,
33 seed: Union[bytes, bytearray, str]
34 ) -> None:
35 """ Instantiates a new signer object from the seed phrase
36
37 Args:
38 seed (Union[bytes, bytearray, str]): The seed phrase used to generate the public and
39 private keys.
40 """
41
42 self.seed: Union[bytes, bytearray] = seed if isinstance(seed, (bytes, bytearray)) else bytearray.fromhex(seed)
43
44 @classmethod
45 def from_mnemonic(
46 cls,
47 mnemonic_phrase: Union[str, List[str], Tuple[str]]
48 ) -> 'Signer':
49 """
50 Instantiates a new Signer object from the mnemonic phrase passed.
51
52 Args:
53 mnemonic_phrase (Union[str, :obj:`list` of :obj:`str`, :obj:`tuple` of :obj:`str`):
54 A string, list, or a tuple of the mnemonic phrase. If the argument is passed as an
55 iterable, then it will be joined with a space.
56
57 Returns:
58 Signer: A new signer initalized through the mnemonic phrase.
59 """
60
61 # If the supplied mnemonic phrase is a list then convert it to a string
62 if isinstance(mnemonic_phrase, (list, tuple)):
63 mnemonic_string: str = " ".join(mnemonic_phrase)
64 else:
65 mnemonic_string: str = mnemonic_phrase
66
67 mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
68 (list, tuple)) else mnemonic_phrase
69
70 return cls(mnemonic.Mnemonic.to_seed(mnemonic_string))
71
72 def public_key(
73 self,
74 index: int = 0
75 ) -> str:
76 """
77 Gets the public key for the signer for the specified account index
78
79 Args:
80 index (int): The account index to get the public keys for.
81
82 Returns:
83 str: A string of the public key for the wallet
84 """
85
86 return str(self.hdwallet(index).public_key())
87
88 def private_key(
89 self,
90 index: int = 0
91 ) -> str:
92 """
93 Gets the private key for the signer for the specified account index
94
95 Args:
96 index (int): The account index to get the private keys for.
97
98 Returns:
99 str: A string of the private key for the wallet
100 """
101
102 return str(self.hdwallet(index).private_key())
103
104 def hdwallet(
105 self,
106 index: int = 0
107 ) -> HDWallet:
108 """
109 Creates an HDWallet object suitable for the Radix blockchain with the passed account index.
110
111 Args:
112 index (int): The account index to create the HDWallet object for.
113
114 Returns:
115 HDWallet: An HD wallet object created with the Radix Parameters for a given account
116 index.
117 """
118
119 hdwallet: HDWallet = HDWallet()
120 hdwallet.from_seed(seed=self.seed.hex())
121 for _, values_tuple in self.HD_WALLET_PARAMS.items():
122 value, hardened = values_tuple
123 hdwallet.from_index(value, hardened=hardened)
124 hdwallet.from_index(index, True)
125
126 return hdwallet
127
128 def sign(
129 self,
130 data: str,
131 index: int = 0
132 ) -> str:
133 """
134 Signs the given data using the private keys for the account at the specified account index.
135
136 Arguments:
137 data (str): A string of the data which we wish to sign.
138 index (int): The account index to get the private keys for.
139
140 Returns:
141 str: A string of the signed data
142 """
143
144 signing_key: SigningKey = ecdsa.SigningKey.from_string( # type: ignore
145 string=bytearray.fromhex(self.private_key(index)),
146 curve=SECP256k1,
147 hashfunc=hashlib.sha256
148 )
149
150 return signing_key.sign_digest( # type: ignore
151 digest=bytearray.fromhex(data),
152 sigencode=sigencode_der
153 ).hex()
154package main
155
156import (
157 "encoding/hex"
158 "fmt"
159 "log"
160
161 "github.com/cosmos/cosmos-sdk/crypto/hd"
162 "github.com/cosmos/go-bip39"
163 "github.com/decred/dcrd/bech32"
164 "github.com/tendermint/tendermint/crypto/secp256k1"
165)
166
167func main() {
168
169 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
170 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
171
172 master, ch := hd.ComputeMastersFromSeed(seed)
173 path := "m/44'/1022'/0'/0/0'"
174 priv, err := hd.DerivePrivateKeyForPath(master, ch, path)
175 if err != nil {
176 t.Fatal(err)
177 }
178 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/118'/0'/0/0'
179 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 69668f2378b43009b16b5c6eb5e405d9224ca2a326a65a17919e567105fa4e5a
180
181 var privKey = secp256k1.PrivKey(priv)
182 pubKey := privKey.PubKey()
183 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 03de79435cbc8a799efc24cdce7d3b180fb014d5f19949fb8d61de3f21b9f6c1f8
184
185 //str := "test"
186 str := "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842"
187 //hx := hex.EncodeToString([]byte(str))
188 //fmt.Println(hx)
189 sign, err := privKey.Sign([]byte(str))
190 if err != nil {
191 return
192 }
193
194 fmt.Println(hex.EncodeToString(sign))
195}
196
ANSWER
Answered 2022-Feb-20 at 14:48Both codes return hex encoded as private key
1 def test_sign_message(self):
2 """ Tests the ability of the signer to sing message """
3
4 # Loading up the signer object to use for the operation
5 signer: TestSigners = TestSigners.from_mnemonic("blast about old claw current first paste risk involve victory edit current")
6 sample_payload_to_sign = "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842'
7 # print("test".encode("UTF-8").hex())
8 s = signer.sign(sample_payload_to_sign)
9 print(s)
10
11
12from typing import List, Tuple, Dict, Union, Any
13from hdwallet.hdwallet import HDWallet
14from ecdsa.util import sigencode_der
15from ecdsa.curves import SECP256k1
16from ecdsa.keys import SigningKey
17import mnemonic
18import hashlib
19import ecdsa
20
21
22class TestSigners():
23
24 HD_WALLET_PARAMS: Dict[str, Tuple[int, bool]] = {
25 "purpose": (44, True),
26 "coinType": (1022, True),
27 "account": (0, True),
28 "change": (0, False),
29 }
30
31 def __init__(
32 self,
33 seed: Union[bytes, bytearray, str]
34 ) -> None:
35 """ Instantiates a new signer object from the seed phrase
36
37 Args:
38 seed (Union[bytes, bytearray, str]): The seed phrase used to generate the public and
39 private keys.
40 """
41
42 self.seed: Union[bytes, bytearray] = seed if isinstance(seed, (bytes, bytearray)) else bytearray.fromhex(seed)
43
44 @classmethod
45 def from_mnemonic(
46 cls,
47 mnemonic_phrase: Union[str, List[str], Tuple[str]]
48 ) -> 'Signer':
49 """
50 Instantiates a new Signer object from the mnemonic phrase passed.
51
52 Args:
53 mnemonic_phrase (Union[str, :obj:`list` of :obj:`str`, :obj:`tuple` of :obj:`str`):
54 A string, list, or a tuple of the mnemonic phrase. If the argument is passed as an
55 iterable, then it will be joined with a space.
56
57 Returns:
58 Signer: A new signer initalized through the mnemonic phrase.
59 """
60
61 # If the supplied mnemonic phrase is a list then convert it to a string
62 if isinstance(mnemonic_phrase, (list, tuple)):
63 mnemonic_string: str = " ".join(mnemonic_phrase)
64 else:
65 mnemonic_string: str = mnemonic_phrase
66
67 mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
68 (list, tuple)) else mnemonic_phrase
69
70 return cls(mnemonic.Mnemonic.to_seed(mnemonic_string))
71
72 def public_key(
73 self,
74 index: int = 0
75 ) -> str:
76 """
77 Gets the public key for the signer for the specified account index
78
79 Args:
80 index (int): The account index to get the public keys for.
81
82 Returns:
83 str: A string of the public key for the wallet
84 """
85
86 return str(self.hdwallet(index).public_key())
87
88 def private_key(
89 self,
90 index: int = 0
91 ) -> str:
92 """
93 Gets the private key for the signer for the specified account index
94
95 Args:
96 index (int): The account index to get the private keys for.
97
98 Returns:
99 str: A string of the private key for the wallet
100 """
101
102 return str(self.hdwallet(index).private_key())
103
104 def hdwallet(
105 self,
106 index: int = 0
107 ) -> HDWallet:
108 """
109 Creates an HDWallet object suitable for the Radix blockchain with the passed account index.
110
111 Args:
112 index (int): The account index to create the HDWallet object for.
113
114 Returns:
115 HDWallet: An HD wallet object created with the Radix Parameters for a given account
116 index.
117 """
118
119 hdwallet: HDWallet = HDWallet()
120 hdwallet.from_seed(seed=self.seed.hex())
121 for _, values_tuple in self.HD_WALLET_PARAMS.items():
122 value, hardened = values_tuple
123 hdwallet.from_index(value, hardened=hardened)
124 hdwallet.from_index(index, True)
125
126 return hdwallet
127
128 def sign(
129 self,
130 data: str,
131 index: int = 0
132 ) -> str:
133 """
134 Signs the given data using the private keys for the account at the specified account index.
135
136 Arguments:
137 data (str): A string of the data which we wish to sign.
138 index (int): The account index to get the private keys for.
139
140 Returns:
141 str: A string of the signed data
142 """
143
144 signing_key: SigningKey = ecdsa.SigningKey.from_string( # type: ignore
145 string=bytearray.fromhex(self.private_key(index)),
146 curve=SECP256k1,
147 hashfunc=hashlib.sha256
148 )
149
150 return signing_key.sign_digest( # type: ignore
151 digest=bytearray.fromhex(data),
152 sigencode=sigencode_der
153 ).hex()
154package main
155
156import (
157 "encoding/hex"
158 "fmt"
159 "log"
160
161 "github.com/cosmos/cosmos-sdk/crypto/hd"
162 "github.com/cosmos/go-bip39"
163 "github.com/decred/dcrd/bech32"
164 "github.com/tendermint/tendermint/crypto/secp256k1"
165)
166
167func main() {
168
169 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
170 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
171
172 master, ch := hd.ComputeMastersFromSeed(seed)
173 path := "m/44'/1022'/0'/0/0'"
174 priv, err := hd.DerivePrivateKeyForPath(master, ch, path)
175 if err != nil {
176 t.Fatal(err)
177 }
178 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/118'/0'/0/0'
179 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 69668f2378b43009b16b5c6eb5e405d9224ca2a326a65a17919e567105fa4e5a
180
181 var privKey = secp256k1.PrivKey(priv)
182 pubKey := privKey.PubKey()
183 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 03de79435cbc8a799efc24cdce7d3b180fb014d5f19949fb8d61de3f21b9f6c1f8
184
185 //str := "test"
186 str := "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842"
187 //hx := hex.EncodeToString([]byte(str))
188 //fmt.Println(hx)
189 sign, err := privKey.Sign([]byte(str))
190 if err != nil {
191 return
192 }
193
194 fmt.Println(hex.EncodeToString(sign))
195}
19633f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
197
and as compressed public key
1 def test_sign_message(self):
2 """ Tests the ability of the signer to sing message """
3
4 # Loading up the signer object to use for the operation
5 signer: TestSigners = TestSigners.from_mnemonic("blast about old claw current first paste risk involve victory edit current")
6 sample_payload_to_sign = "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842'
7 # print("test".encode("UTF-8").hex())
8 s = signer.sign(sample_payload_to_sign)
9 print(s)
10
11
12from typing import List, Tuple, Dict, Union, Any
13from hdwallet.hdwallet import HDWallet
14from ecdsa.util import sigencode_der
15from ecdsa.curves import SECP256k1
16from ecdsa.keys import SigningKey
17import mnemonic
18import hashlib
19import ecdsa
20
21
22class TestSigners():
23
24 HD_WALLET_PARAMS: Dict[str, Tuple[int, bool]] = {
25 "purpose": (44, True),
26 "coinType": (1022, True),
27 "account": (0, True),
28 "change": (0, False),
29 }
30
31 def __init__(
32 self,
33 seed: Union[bytes, bytearray, str]
34 ) -> None:
35 """ Instantiates a new signer object from the seed phrase
36
37 Args:
38 seed (Union[bytes, bytearray, str]): The seed phrase used to generate the public and
39 private keys.
40 """
41
42 self.seed: Union[bytes, bytearray] = seed if isinstance(seed, (bytes, bytearray)) else bytearray.fromhex(seed)
43
44 @classmethod
45 def from_mnemonic(
46 cls,
47 mnemonic_phrase: Union[str, List[str], Tuple[str]]
48 ) -> 'Signer':
49 """
50 Instantiates a new Signer object from the mnemonic phrase passed.
51
52 Args:
53 mnemonic_phrase (Union[str, :obj:`list` of :obj:`str`, :obj:`tuple` of :obj:`str`):
54 A string, list, or a tuple of the mnemonic phrase. If the argument is passed as an
55 iterable, then it will be joined with a space.
56
57 Returns:
58 Signer: A new signer initalized through the mnemonic phrase.
59 """
60
61 # If the supplied mnemonic phrase is a list then convert it to a string
62 if isinstance(mnemonic_phrase, (list, tuple)):
63 mnemonic_string: str = " ".join(mnemonic_phrase)
64 else:
65 mnemonic_string: str = mnemonic_phrase
66
67 mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
68 (list, tuple)) else mnemonic_phrase
69
70 return cls(mnemonic.Mnemonic.to_seed(mnemonic_string))
71
72 def public_key(
73 self,
74 index: int = 0
75 ) -> str:
76 """
77 Gets the public key for the signer for the specified account index
78
79 Args:
80 index (int): The account index to get the public keys for.
81
82 Returns:
83 str: A string of the public key for the wallet
84 """
85
86 return str(self.hdwallet(index).public_key())
87
88 def private_key(
89 self,
90 index: int = 0
91 ) -> str:
92 """
93 Gets the private key for the signer for the specified account index
94
95 Args:
96 index (int): The account index to get the private keys for.
97
98 Returns:
99 str: A string of the private key for the wallet
100 """
101
102 return str(self.hdwallet(index).private_key())
103
104 def hdwallet(
105 self,
106 index: int = 0
107 ) -> HDWallet:
108 """
109 Creates an HDWallet object suitable for the Radix blockchain with the passed account index.
110
111 Args:
112 index (int): The account index to create the HDWallet object for.
113
114 Returns:
115 HDWallet: An HD wallet object created with the Radix Parameters for a given account
116 index.
117 """
118
119 hdwallet: HDWallet = HDWallet()
120 hdwallet.from_seed(seed=self.seed.hex())
121 for _, values_tuple in self.HD_WALLET_PARAMS.items():
122 value, hardened = values_tuple
123 hdwallet.from_index(value, hardened=hardened)
124 hdwallet.from_index(index, True)
125
126 return hdwallet
127
128 def sign(
129 self,
130 data: str,
131 index: int = 0
132 ) -> str:
133 """
134 Signs the given data using the private keys for the account at the specified account index.
135
136 Arguments:
137 data (str): A string of the data which we wish to sign.
138 index (int): The account index to get the private keys for.
139
140 Returns:
141 str: A string of the signed data
142 """
143
144 signing_key: SigningKey = ecdsa.SigningKey.from_string( # type: ignore
145 string=bytearray.fromhex(self.private_key(index)),
146 curve=SECP256k1,
147 hashfunc=hashlib.sha256
148 )
149
150 return signing_key.sign_digest( # type: ignore
151 digest=bytearray.fromhex(data),
152 sigencode=sigencode_der
153 ).hex()
154package main
155
156import (
157 "encoding/hex"
158 "fmt"
159 "log"
160
161 "github.com/cosmos/cosmos-sdk/crypto/hd"
162 "github.com/cosmos/go-bip39"
163 "github.com/decred/dcrd/bech32"
164 "github.com/tendermint/tendermint/crypto/secp256k1"
165)
166
167func main() {
168
169 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
170 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
171
172 master, ch := hd.ComputeMastersFromSeed(seed)
173 path := "m/44'/1022'/0'/0/0'"
174 priv, err := hd.DerivePrivateKeyForPath(master, ch, path)
175 if err != nil {
176 t.Fatal(err)
177 }
178 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/118'/0'/0/0'
179 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 69668f2378b43009b16b5c6eb5e405d9224ca2a326a65a17919e567105fa4e5a
180
181 var privKey = secp256k1.PrivKey(priv)
182 pubKey := privKey.PubKey()
183 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 03de79435cbc8a799efc24cdce7d3b180fb014d5f19949fb8d61de3f21b9f6c1f8
184
185 //str := "test"
186 str := "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842"
187 //hx := hex.EncodeToString([]byte(str))
188 //fmt.Println(hx)
189 sign, err := privKey.Sign([]byte(str))
190 if err != nil {
191 return
192 }
193
194 fmt.Println(hex.EncodeToString(sign))
195}
19633f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
197026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
198
Since both codes provide the same keys, the issue must be with signing!
As test message for signing the UTF8 encoding of test
is used, whose SHA256 hash is hex encoded 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
.
Remark 1: If a double SHA256 hashing is used as noted in the comment, the SHA256 hash of test
is to be used as test message instead of test
. Apart from that the further processing is the same.
The Python and Go code are currently incompatible because they differ in signing and signature format:
With regard to signing: In the Python code, the hashed message is passed. This is correct because
sign_digest()
does not hash the message (see here), and thus the hashed message is signed.
In contrast,sign()
in the Go code hashes the message (see here), so the message itself must be passed for the processing to be functionally identical to the Python code.With regard to the signature format: the Python code uses the ASN.1/DER format, while the Go code uses the IEEE P1363 format.
Therefore, a conversion from IEEE P1363 to ASN.1/DER must be performed in the Go code:
With this, the fixed Go code is:
1 def test_sign_message(self):
2 """ Tests the ability of the signer to sing message """
3
4 # Loading up the signer object to use for the operation
5 signer: TestSigners = TestSigners.from_mnemonic("blast about old claw current first paste risk involve victory edit current")
6 sample_payload_to_sign = "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842'
7 # print("test".encode("UTF-8").hex())
8 s = signer.sign(sample_payload_to_sign)
9 print(s)
10
11
12from typing import List, Tuple, Dict, Union, Any
13from hdwallet.hdwallet import HDWallet
14from ecdsa.util import sigencode_der
15from ecdsa.curves import SECP256k1
16from ecdsa.keys import SigningKey
17import mnemonic
18import hashlib
19import ecdsa
20
21
22class TestSigners():
23
24 HD_WALLET_PARAMS: Dict[str, Tuple[int, bool]] = {
25 "purpose": (44, True),
26 "coinType": (1022, True),
27 "account": (0, True),
28 "change": (0, False),
29 }
30
31 def __init__(
32 self,
33 seed: Union[bytes, bytearray, str]
34 ) -> None:
35 """ Instantiates a new signer object from the seed phrase
36
37 Args:
38 seed (Union[bytes, bytearray, str]): The seed phrase used to generate the public and
39 private keys.
40 """
41
42 self.seed: Union[bytes, bytearray] = seed if isinstance(seed, (bytes, bytearray)) else bytearray.fromhex(seed)
43
44 @classmethod
45 def from_mnemonic(
46 cls,
47 mnemonic_phrase: Union[str, List[str], Tuple[str]]
48 ) -> 'Signer':
49 """
50 Instantiates a new Signer object from the mnemonic phrase passed.
51
52 Args:
53 mnemonic_phrase (Union[str, :obj:`list` of :obj:`str`, :obj:`tuple` of :obj:`str`):
54 A string, list, or a tuple of the mnemonic phrase. If the argument is passed as an
55 iterable, then it will be joined with a space.
56
57 Returns:
58 Signer: A new signer initalized through the mnemonic phrase.
59 """
60
61 # If the supplied mnemonic phrase is a list then convert it to a string
62 if isinstance(mnemonic_phrase, (list, tuple)):
63 mnemonic_string: str = " ".join(mnemonic_phrase)
64 else:
65 mnemonic_string: str = mnemonic_phrase
66
67 mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
68 (list, tuple)) else mnemonic_phrase
69
70 return cls(mnemonic.Mnemonic.to_seed(mnemonic_string))
71
72 def public_key(
73 self,
74 index: int = 0
75 ) -> str:
76 """
77 Gets the public key for the signer for the specified account index
78
79 Args:
80 index (int): The account index to get the public keys for.
81
82 Returns:
83 str: A string of the public key for the wallet
84 """
85
86 return str(self.hdwallet(index).public_key())
87
88 def private_key(
89 self,
90 index: int = 0
91 ) -> str:
92 """
93 Gets the private key for the signer for the specified account index
94
95 Args:
96 index (int): The account index to get the private keys for.
97
98 Returns:
99 str: A string of the private key for the wallet
100 """
101
102 return str(self.hdwallet(index).private_key())
103
104 def hdwallet(
105 self,
106 index: int = 0
107 ) -> HDWallet:
108 """
109 Creates an HDWallet object suitable for the Radix blockchain with the passed account index.
110
111 Args:
112 index (int): The account index to create the HDWallet object for.
113
114 Returns:
115 HDWallet: An HD wallet object created with the Radix Parameters for a given account
116 index.
117 """
118
119 hdwallet: HDWallet = HDWallet()
120 hdwallet.from_seed(seed=self.seed.hex())
121 for _, values_tuple in self.HD_WALLET_PARAMS.items():
122 value, hardened = values_tuple
123 hdwallet.from_index(value, hardened=hardened)
124 hdwallet.from_index(index, True)
125
126 return hdwallet
127
128 def sign(
129 self,
130 data: str,
131 index: int = 0
132 ) -> str:
133 """
134 Signs the given data using the private keys for the account at the specified account index.
135
136 Arguments:
137 data (str): A string of the data which we wish to sign.
138 index (int): The account index to get the private keys for.
139
140 Returns:
141 str: A string of the signed data
142 """
143
144 signing_key: SigningKey = ecdsa.SigningKey.from_string( # type: ignore
145 string=bytearray.fromhex(self.private_key(index)),
146 curve=SECP256k1,
147 hashfunc=hashlib.sha256
148 )
149
150 return signing_key.sign_digest( # type: ignore
151 digest=bytearray.fromhex(data),
152 sigencode=sigencode_der
153 ).hex()
154package main
155
156import (
157 "encoding/hex"
158 "fmt"
159 "log"
160
161 "github.com/cosmos/cosmos-sdk/crypto/hd"
162 "github.com/cosmos/go-bip39"
163 "github.com/decred/dcrd/bech32"
164 "github.com/tendermint/tendermint/crypto/secp256k1"
165)
166
167func main() {
168
169 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
170 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
171
172 master, ch := hd.ComputeMastersFromSeed(seed)
173 path := "m/44'/1022'/0'/0/0'"
174 priv, err := hd.DerivePrivateKeyForPath(master, ch, path)
175 if err != nil {
176 t.Fatal(err)
177 }
178 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/118'/0'/0/0'
179 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 69668f2378b43009b16b5c6eb5e405d9224ca2a326a65a17919e567105fa4e5a
180
181 var privKey = secp256k1.PrivKey(priv)
182 pubKey := privKey.PubKey()
183 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 03de79435cbc8a799efc24cdce7d3b180fb014d5f19949fb8d61de3f21b9f6c1f8
184
185 //str := "test"
186 str := "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842"
187 //hx := hex.EncodeToString([]byte(str))
188 //fmt.Println(hx)
189 sign, err := privKey.Sign([]byte(str))
190 if err != nil {
191 return
192 }
193
194 fmt.Println(hex.EncodeToString(sign))
195}
19633f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
197026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
198package main
199
200import (
201 "encoding/hex"
202 "fmt"
203
204 "math/big"
205
206 "github.com/cosmos/cosmos-sdk/crypto/hd"
207 "github.com/cosmos/go-bip39"
208 "github.com/tendermint/tendermint/crypto/secp256k1"
209
210 //"github.com/btcsuite/btcd/btcec"
211 "golang.org/x/crypto/cryptobyte"
212 "golang.org/x/crypto/cryptobyte/asn1"
213)
214
215func main() {
216
217 //
218 // Derive private and public key (this part works)
219 //
220 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
221 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
222
223 master, ch := hd.ComputeMastersFromSeed(seed)
224 path := "m/44'/1022'/0'/0/0'"
225 priv, _ := hd.DerivePrivateKeyForPath(master, ch, path)
226 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/1022'/0'/0/0'
227 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 33f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
228
229 var privKey = secp256k1.PrivKey(priv)
230 pubKey := privKey.PubKey()
231 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
232
233 //
234 // Sign (this part needs to be fixed)
235 //
236 data := "test"
237
238 signature, _ := privKey.Sign([]byte(data))
239 fmt.Println(hex.EncodeToString(signature))
240
241 rVal := new(big.Int)
242 rVal.SetBytes(signature[0:32])
243 sVal := new(big.Int)
244 sVal.SetBytes(signature[32:64])
245 var b cryptobyte.Builder
246 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
247 b.AddASN1BigInt(rVal)
248 b.AddASN1BigInt(sVal)
249 })
250 signatureDER, _ := b.Bytes()
251 fmt.Println("Signature, DER: ", hex.EncodeToString(signatureDER))
252
253 /*
254 hash, _ := hex.DecodeString("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08")
255
256 // Sign without hashing
257 privateKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), priv)
258 signature, _ := privateKey.Sign(hash[:])
259
260 // Convert to ASN1/DER
261 rVal := new(big.Int)
262 rVal.SetBytes(signature.R.Bytes())
263 sVal := new(big.Int)
264 sVal.SetBytes(signature.S.Bytes())
265 var b cryptobyte.Builder
266 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
267 b.AddASN1BigInt(rVal)
268 b.AddASN1BigInt(sVal)
269 })
270 signatureDER, _ := b.Bytes()
271 fmt.Println("Signature, DER: ", hex.EncodeToString(signatureDER))
272 */
273}
274
Remark 2: If the original message is not available in the Go code, but only the hash, a function that does not hash is needed for signing.
The tendermint/crypto/secp256k1 package does not support this, but tendermint/crypto/secp256k1 uses internally btcsuite/btcd/btcec which does.
This is implemented in the commented-out code.
The output is:
1 def test_sign_message(self):
2 """ Tests the ability of the signer to sing message """
3
4 # Loading up the signer object to use for the operation
5 signer: TestSigners = TestSigners.from_mnemonic("blast about old claw current first paste risk involve victory edit current")
6 sample_payload_to_sign = "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842'
7 # print("test".encode("UTF-8").hex())
8 s = signer.sign(sample_payload_to_sign)
9 print(s)
10
11
12from typing import List, Tuple, Dict, Union, Any
13from hdwallet.hdwallet import HDWallet
14from ecdsa.util import sigencode_der
15from ecdsa.curves import SECP256k1
16from ecdsa.keys import SigningKey
17import mnemonic
18import hashlib
19import ecdsa
20
21
22class TestSigners():
23
24 HD_WALLET_PARAMS: Dict[str, Tuple[int, bool]] = {
25 "purpose": (44, True),
26 "coinType": (1022, True),
27 "account": (0, True),
28 "change": (0, False),
29 }
30
31 def __init__(
32 self,
33 seed: Union[bytes, bytearray, str]
34 ) -> None:
35 """ Instantiates a new signer object from the seed phrase
36
37 Args:
38 seed (Union[bytes, bytearray, str]): The seed phrase used to generate the public and
39 private keys.
40 """
41
42 self.seed: Union[bytes, bytearray] = seed if isinstance(seed, (bytes, bytearray)) else bytearray.fromhex(seed)
43
44 @classmethod
45 def from_mnemonic(
46 cls,
47 mnemonic_phrase: Union[str, List[str], Tuple[str]]
48 ) -> 'Signer':
49 """
50 Instantiates a new Signer object from the mnemonic phrase passed.
51
52 Args:
53 mnemonic_phrase (Union[str, :obj:`list` of :obj:`str`, :obj:`tuple` of :obj:`str`):
54 A string, list, or a tuple of the mnemonic phrase. If the argument is passed as an
55 iterable, then it will be joined with a space.
56
57 Returns:
58 Signer: A new signer initalized through the mnemonic phrase.
59 """
60
61 # If the supplied mnemonic phrase is a list then convert it to a string
62 if isinstance(mnemonic_phrase, (list, tuple)):
63 mnemonic_string: str = " ".join(mnemonic_phrase)
64 else:
65 mnemonic_string: str = mnemonic_phrase
66
67 mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
68 (list, tuple)) else mnemonic_phrase
69
70 return cls(mnemonic.Mnemonic.to_seed(mnemonic_string))
71
72 def public_key(
73 self,
74 index: int = 0
75 ) -> str:
76 """
77 Gets the public key for the signer for the specified account index
78
79 Args:
80 index (int): The account index to get the public keys for.
81
82 Returns:
83 str: A string of the public key for the wallet
84 """
85
86 return str(self.hdwallet(index).public_key())
87
88 def private_key(
89 self,
90 index: int = 0
91 ) -> str:
92 """
93 Gets the private key for the signer for the specified account index
94
95 Args:
96 index (int): The account index to get the private keys for.
97
98 Returns:
99 str: A string of the private key for the wallet
100 """
101
102 return str(self.hdwallet(index).private_key())
103
104 def hdwallet(
105 self,
106 index: int = 0
107 ) -> HDWallet:
108 """
109 Creates an HDWallet object suitable for the Radix blockchain with the passed account index.
110
111 Args:
112 index (int): The account index to create the HDWallet object for.
113
114 Returns:
115 HDWallet: An HD wallet object created with the Radix Parameters for a given account
116 index.
117 """
118
119 hdwallet: HDWallet = HDWallet()
120 hdwallet.from_seed(seed=self.seed.hex())
121 for _, values_tuple in self.HD_WALLET_PARAMS.items():
122 value, hardened = values_tuple
123 hdwallet.from_index(value, hardened=hardened)
124 hdwallet.from_index(index, True)
125
126 return hdwallet
127
128 def sign(
129 self,
130 data: str,
131 index: int = 0
132 ) -> str:
133 """
134 Signs the given data using the private keys for the account at the specified account index.
135
136 Arguments:
137 data (str): A string of the data which we wish to sign.
138 index (int): The account index to get the private keys for.
139
140 Returns:
141 str: A string of the signed data
142 """
143
144 signing_key: SigningKey = ecdsa.SigningKey.from_string( # type: ignore
145 string=bytearray.fromhex(self.private_key(index)),
146 curve=SECP256k1,
147 hashfunc=hashlib.sha256
148 )
149
150 return signing_key.sign_digest( # type: ignore
151 digest=bytearray.fromhex(data),
152 sigencode=sigencode_der
153 ).hex()
154package main
155
156import (
157 "encoding/hex"
158 "fmt"
159 "log"
160
161 "github.com/cosmos/cosmos-sdk/crypto/hd"
162 "github.com/cosmos/go-bip39"
163 "github.com/decred/dcrd/bech32"
164 "github.com/tendermint/tendermint/crypto/secp256k1"
165)
166
167func main() {
168
169 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
170 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
171
172 master, ch := hd.ComputeMastersFromSeed(seed)
173 path := "m/44'/1022'/0'/0/0'"
174 priv, err := hd.DerivePrivateKeyForPath(master, ch, path)
175 if err != nil {
176 t.Fatal(err)
177 }
178 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/118'/0'/0/0'
179 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 69668f2378b43009b16b5c6eb5e405d9224ca2a326a65a17919e567105fa4e5a
180
181 var privKey = secp256k1.PrivKey(priv)
182 pubKey := privKey.PubKey()
183 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 03de79435cbc8a799efc24cdce7d3b180fb014d5f19949fb8d61de3f21b9f6c1f8
184
185 //str := "test"
186 str := "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842"
187 //hx := hex.EncodeToString([]byte(str))
188 //fmt.Println(hx)
189 sign, err := privKey.Sign([]byte(str))
190 if err != nil {
191 return
192 }
193
194 fmt.Println(hex.EncodeToString(sign))
195}
19633f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
197026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
198package main
199
200import (
201 "encoding/hex"
202 "fmt"
203
204 "math/big"
205
206 "github.com/cosmos/cosmos-sdk/crypto/hd"
207 "github.com/cosmos/go-bip39"
208 "github.com/tendermint/tendermint/crypto/secp256k1"
209
210 //"github.com/btcsuite/btcd/btcec"
211 "golang.org/x/crypto/cryptobyte"
212 "golang.org/x/crypto/cryptobyte/asn1"
213)
214
215func main() {
216
217 //
218 // Derive private and public key (this part works)
219 //
220 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
221 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
222
223 master, ch := hd.ComputeMastersFromSeed(seed)
224 path := "m/44'/1022'/0'/0/0'"
225 priv, _ := hd.DerivePrivateKeyForPath(master, ch, path)
226 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/1022'/0'/0/0'
227 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 33f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
228
229 var privKey = secp256k1.PrivKey(priv)
230 pubKey := privKey.PubKey()
231 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
232
233 //
234 // Sign (this part needs to be fixed)
235 //
236 data := "test"
237
238 signature, _ := privKey.Sign([]byte(data))
239 fmt.Println(hex.EncodeToString(signature))
240
241 rVal := new(big.Int)
242 rVal.SetBytes(signature[0:32])
243 sVal := new(big.Int)
244 sVal.SetBytes(signature[32:64])
245 var b cryptobyte.Builder
246 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
247 b.AddASN1BigInt(rVal)
248 b.AddASN1BigInt(sVal)
249 })
250 signatureDER, _ := b.Bytes()
251 fmt.Println("Signature, DER: ", hex.EncodeToString(signatureDER))
252
253 /*
254 hash, _ := hex.DecodeString("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08")
255
256 // Sign without hashing
257 privateKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), priv)
258 signature, _ := privateKey.Sign(hash[:])
259
260 // Convert to ASN1/DER
261 rVal := new(big.Int)
262 rVal.SetBytes(signature.R.Bytes())
263 sVal := new(big.Int)
264 sVal.SetBytes(signature.S.Bytes())
265 var b cryptobyte.Builder
266 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
267 b.AddASN1BigInt(rVal)
268 b.AddASN1BigInt(sVal)
269 })
270 signatureDER, _ := b.Bytes()
271 fmt.Println("Signature, DER: ", hex.EncodeToString(signatureDER))
272 */
273}
274Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
275Derivation Path: m/44'/1022'/0'/0/0'
276Private Key: 33f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
277Public Key: 026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
27857624717f71fae8b5917cde0f82dfe6c2e2104183ba01c6a1c9f0a8e66d3303e5035b52876d833522aace232c1d231b3aeeff303cf02d1677a240102365ce71b
279Signature, DER: 3044022057624717f71fae8b5917cde0f82dfe6c2e2104183ba01c6a1c9f0a8e66d3303e02205035b52876d833522aace232c1d231b3aeeff303cf02d1677a240102365ce71b
280
Test:
Since the Python code generates a non-deterministic signature, verification by comparing the signatures is not possible.
Instead, a possible test is to check the signatures of both codes with the same verification code.
For this purpose, in the method sign()
of the Python code the lines
1 def test_sign_message(self):
2 """ Tests the ability of the signer to sing message """
3
4 # Loading up the signer object to use for the operation
5 signer: TestSigners = TestSigners.from_mnemonic("blast about old claw current first paste risk involve victory edit current")
6 sample_payload_to_sign = "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842'
7 # print("test".encode("UTF-8").hex())
8 s = signer.sign(sample_payload_to_sign)
9 print(s)
10
11
12from typing import List, Tuple, Dict, Union, Any
13from hdwallet.hdwallet import HDWallet
14from ecdsa.util import sigencode_der
15from ecdsa.curves import SECP256k1
16from ecdsa.keys import SigningKey
17import mnemonic
18import hashlib
19import ecdsa
20
21
22class TestSigners():
23
24 HD_WALLET_PARAMS: Dict[str, Tuple[int, bool]] = {
25 "purpose": (44, True),
26 "coinType": (1022, True),
27 "account": (0, True),
28 "change": (0, False),
29 }
30
31 def __init__(
32 self,
33 seed: Union[bytes, bytearray, str]
34 ) -> None:
35 """ Instantiates a new signer object from the seed phrase
36
37 Args:
38 seed (Union[bytes, bytearray, str]): The seed phrase used to generate the public and
39 private keys.
40 """
41
42 self.seed: Union[bytes, bytearray] = seed if isinstance(seed, (bytes, bytearray)) else bytearray.fromhex(seed)
43
44 @classmethod
45 def from_mnemonic(
46 cls,
47 mnemonic_phrase: Union[str, List[str], Tuple[str]]
48 ) -> 'Signer':
49 """
50 Instantiates a new Signer object from the mnemonic phrase passed.
51
52 Args:
53 mnemonic_phrase (Union[str, :obj:`list` of :obj:`str`, :obj:`tuple` of :obj:`str`):
54 A string, list, or a tuple of the mnemonic phrase. If the argument is passed as an
55 iterable, then it will be joined with a space.
56
57 Returns:
58 Signer: A new signer initalized through the mnemonic phrase.
59 """
60
61 # If the supplied mnemonic phrase is a list then convert it to a string
62 if isinstance(mnemonic_phrase, (list, tuple)):
63 mnemonic_string: str = " ".join(mnemonic_phrase)
64 else:
65 mnemonic_string: str = mnemonic_phrase
66
67 mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
68 (list, tuple)) else mnemonic_phrase
69
70 return cls(mnemonic.Mnemonic.to_seed(mnemonic_string))
71
72 def public_key(
73 self,
74 index: int = 0
75 ) -> str:
76 """
77 Gets the public key for the signer for the specified account index
78
79 Args:
80 index (int): The account index to get the public keys for.
81
82 Returns:
83 str: A string of the public key for the wallet
84 """
85
86 return str(self.hdwallet(index).public_key())
87
88 def private_key(
89 self,
90 index: int = 0
91 ) -> str:
92 """
93 Gets the private key for the signer for the specified account index
94
95 Args:
96 index (int): The account index to get the private keys for.
97
98 Returns:
99 str: A string of the private key for the wallet
100 """
101
102 return str(self.hdwallet(index).private_key())
103
104 def hdwallet(
105 self,
106 index: int = 0
107 ) -> HDWallet:
108 """
109 Creates an HDWallet object suitable for the Radix blockchain with the passed account index.
110
111 Args:
112 index (int): The account index to create the HDWallet object for.
113
114 Returns:
115 HDWallet: An HD wallet object created with the Radix Parameters for a given account
116 index.
117 """
118
119 hdwallet: HDWallet = HDWallet()
120 hdwallet.from_seed(seed=self.seed.hex())
121 for _, values_tuple in self.HD_WALLET_PARAMS.items():
122 value, hardened = values_tuple
123 hdwallet.from_index(value, hardened=hardened)
124 hdwallet.from_index(index, True)
125
126 return hdwallet
127
128 def sign(
129 self,
130 data: str,
131 index: int = 0
132 ) -> str:
133 """
134 Signs the given data using the private keys for the account at the specified account index.
135
136 Arguments:
137 data (str): A string of the data which we wish to sign.
138 index (int): The account index to get the private keys for.
139
140 Returns:
141 str: A string of the signed data
142 """
143
144 signing_key: SigningKey = ecdsa.SigningKey.from_string( # type: ignore
145 string=bytearray.fromhex(self.private_key(index)),
146 curve=SECP256k1,
147 hashfunc=hashlib.sha256
148 )
149
150 return signing_key.sign_digest( # type: ignore
151 digest=bytearray.fromhex(data),
152 sigencode=sigencode_der
153 ).hex()
154package main
155
156import (
157 "encoding/hex"
158 "fmt"
159 "log"
160
161 "github.com/cosmos/cosmos-sdk/crypto/hd"
162 "github.com/cosmos/go-bip39"
163 "github.com/decred/dcrd/bech32"
164 "github.com/tendermint/tendermint/crypto/secp256k1"
165)
166
167func main() {
168
169 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
170 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
171
172 master, ch := hd.ComputeMastersFromSeed(seed)
173 path := "m/44'/1022'/0'/0/0'"
174 priv, err := hd.DerivePrivateKeyForPath(master, ch, path)
175 if err != nil {
176 t.Fatal(err)
177 }
178 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/118'/0'/0/0'
179 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 69668f2378b43009b16b5c6eb5e405d9224ca2a326a65a17919e567105fa4e5a
180
181 var privKey = secp256k1.PrivKey(priv)
182 pubKey := privKey.PubKey()
183 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 03de79435cbc8a799efc24cdce7d3b180fb014d5f19949fb8d61de3f21b9f6c1f8
184
185 //str := "test"
186 str := "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842"
187 //hx := hex.EncodeToString([]byte(str))
188 //fmt.Println(hx)
189 sign, err := privKey.Sign([]byte(str))
190 if err != nil {
191 return
192 }
193
194 fmt.Println(hex.EncodeToString(sign))
195}
19633f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
197026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
198package main
199
200import (
201 "encoding/hex"
202 "fmt"
203
204 "math/big"
205
206 "github.com/cosmos/cosmos-sdk/crypto/hd"
207 "github.com/cosmos/go-bip39"
208 "github.com/tendermint/tendermint/crypto/secp256k1"
209
210 //"github.com/btcsuite/btcd/btcec"
211 "golang.org/x/crypto/cryptobyte"
212 "golang.org/x/crypto/cryptobyte/asn1"
213)
214
215func main() {
216
217 //
218 // Derive private and public key (this part works)
219 //
220 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
221 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
222
223 master, ch := hd.ComputeMastersFromSeed(seed)
224 path := "m/44'/1022'/0'/0/0'"
225 priv, _ := hd.DerivePrivateKeyForPath(master, ch, path)
226 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/1022'/0'/0/0'
227 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 33f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
228
229 var privKey = secp256k1.PrivKey(priv)
230 pubKey := privKey.PubKey()
231 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
232
233 //
234 // Sign (this part needs to be fixed)
235 //
236 data := "test"
237
238 signature, _ := privKey.Sign([]byte(data))
239 fmt.Println(hex.EncodeToString(signature))
240
241 rVal := new(big.Int)
242 rVal.SetBytes(signature[0:32])
243 sVal := new(big.Int)
244 sVal.SetBytes(signature[32:64])
245 var b cryptobyte.Builder
246 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
247 b.AddASN1BigInt(rVal)
248 b.AddASN1BigInt(sVal)
249 })
250 signatureDER, _ := b.Bytes()
251 fmt.Println("Signature, DER: ", hex.EncodeToString(signatureDER))
252
253 /*
254 hash, _ := hex.DecodeString("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08")
255
256 // Sign without hashing
257 privateKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), priv)
258 signature, _ := privateKey.Sign(hash[:])
259
260 // Convert to ASN1/DER
261 rVal := new(big.Int)
262 rVal.SetBytes(signature.R.Bytes())
263 sVal := new(big.Int)
264 sVal.SetBytes(signature.S.Bytes())
265 var b cryptobyte.Builder
266 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
267 b.AddASN1BigInt(rVal)
268 b.AddASN1BigInt(sVal)
269 })
270 signatureDER, _ := b.Bytes()
271 fmt.Println("Signature, DER: ", hex.EncodeToString(signatureDER))
272 */
273}
274Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
275Derivation Path: m/44'/1022'/0'/0/0'
276Private Key: 33f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
277Public Key: 026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
27857624717f71fae8b5917cde0f82dfe6c2e2104183ba01c6a1c9f0a8e66d3303e5035b52876d833522aace232c1d231b3aeeff303cf02d1677a240102365ce71b
279Signature, DER: 3044022057624717f71fae8b5917cde0f82dfe6c2e2104183ba01c6a1c9f0a8e66d3303e02205035b52876d833522aace232c1d231b3aeeff303cf02d1677a240102365ce71b
280return signing_key.sign_digest( # type: ignore
281 digest=bytearray.fromhex(data),
282 sigencode=sigencode_der
283).hex()
284
can be replaced by
1 def test_sign_message(self):
2 """ Tests the ability of the signer to sing message """
3
4 # Loading up the signer object to use for the operation
5 signer: TestSigners = TestSigners.from_mnemonic("blast about old claw current first paste risk involve victory edit current")
6 sample_payload_to_sign = "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842'
7 # print("test".encode("UTF-8").hex())
8 s = signer.sign(sample_payload_to_sign)
9 print(s)
10
11
12from typing import List, Tuple, Dict, Union, Any
13from hdwallet.hdwallet import HDWallet
14from ecdsa.util import sigencode_der
15from ecdsa.curves import SECP256k1
16from ecdsa.keys import SigningKey
17import mnemonic
18import hashlib
19import ecdsa
20
21
22class TestSigners():
23
24 HD_WALLET_PARAMS: Dict[str, Tuple[int, bool]] = {
25 "purpose": (44, True),
26 "coinType": (1022, True),
27 "account": (0, True),
28 "change": (0, False),
29 }
30
31 def __init__(
32 self,
33 seed: Union[bytes, bytearray, str]
34 ) -> None:
35 """ Instantiates a new signer object from the seed phrase
36
37 Args:
38 seed (Union[bytes, bytearray, str]): The seed phrase used to generate the public and
39 private keys.
40 """
41
42 self.seed: Union[bytes, bytearray] = seed if isinstance(seed, (bytes, bytearray)) else bytearray.fromhex(seed)
43
44 @classmethod
45 def from_mnemonic(
46 cls,
47 mnemonic_phrase: Union[str, List[str], Tuple[str]]
48 ) -> 'Signer':
49 """
50 Instantiates a new Signer object from the mnemonic phrase passed.
51
52 Args:
53 mnemonic_phrase (Union[str, :obj:`list` of :obj:`str`, :obj:`tuple` of :obj:`str`):
54 A string, list, or a tuple of the mnemonic phrase. If the argument is passed as an
55 iterable, then it will be joined with a space.
56
57 Returns:
58 Signer: A new signer initalized through the mnemonic phrase.
59 """
60
61 # If the supplied mnemonic phrase is a list then convert it to a string
62 if isinstance(mnemonic_phrase, (list, tuple)):
63 mnemonic_string: str = " ".join(mnemonic_phrase)
64 else:
65 mnemonic_string: str = mnemonic_phrase
66
67 mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
68 (list, tuple)) else mnemonic_phrase
69
70 return cls(mnemonic.Mnemonic.to_seed(mnemonic_string))
71
72 def public_key(
73 self,
74 index: int = 0
75 ) -> str:
76 """
77 Gets the public key for the signer for the specified account index
78
79 Args:
80 index (int): The account index to get the public keys for.
81
82 Returns:
83 str: A string of the public key for the wallet
84 """
85
86 return str(self.hdwallet(index).public_key())
87
88 def private_key(
89 self,
90 index: int = 0
91 ) -> str:
92 """
93 Gets the private key for the signer for the specified account index
94
95 Args:
96 index (int): The account index to get the private keys for.
97
98 Returns:
99 str: A string of the private key for the wallet
100 """
101
102 return str(self.hdwallet(index).private_key())
103
104 def hdwallet(
105 self,
106 index: int = 0
107 ) -> HDWallet:
108 """
109 Creates an HDWallet object suitable for the Radix blockchain with the passed account index.
110
111 Args:
112 index (int): The account index to create the HDWallet object for.
113
114 Returns:
115 HDWallet: An HD wallet object created with the Radix Parameters for a given account
116 index.
117 """
118
119 hdwallet: HDWallet = HDWallet()
120 hdwallet.from_seed(seed=self.seed.hex())
121 for _, values_tuple in self.HD_WALLET_PARAMS.items():
122 value, hardened = values_tuple
123 hdwallet.from_index(value, hardened=hardened)
124 hdwallet.from_index(index, True)
125
126 return hdwallet
127
128 def sign(
129 self,
130 data: str,
131 index: int = 0
132 ) -> str:
133 """
134 Signs the given data using the private keys for the account at the specified account index.
135
136 Arguments:
137 data (str): A string of the data which we wish to sign.
138 index (int): The account index to get the private keys for.
139
140 Returns:
141 str: A string of the signed data
142 """
143
144 signing_key: SigningKey = ecdsa.SigningKey.from_string( # type: ignore
145 string=bytearray.fromhex(self.private_key(index)),
146 curve=SECP256k1,
147 hashfunc=hashlib.sha256
148 )
149
150 return signing_key.sign_digest( # type: ignore
151 digest=bytearray.fromhex(data),
152 sigencode=sigencode_der
153 ).hex()
154package main
155
156import (
157 "encoding/hex"
158 "fmt"
159 "log"
160
161 "github.com/cosmos/cosmos-sdk/crypto/hd"
162 "github.com/cosmos/go-bip39"
163 "github.com/decred/dcrd/bech32"
164 "github.com/tendermint/tendermint/crypto/secp256k1"
165)
166
167func main() {
168
169 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
170 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
171
172 master, ch := hd.ComputeMastersFromSeed(seed)
173 path := "m/44'/1022'/0'/0/0'"
174 priv, err := hd.DerivePrivateKeyForPath(master, ch, path)
175 if err != nil {
176 t.Fatal(err)
177 }
178 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/118'/0'/0/0'
179 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 69668f2378b43009b16b5c6eb5e405d9224ca2a326a65a17919e567105fa4e5a
180
181 var privKey = secp256k1.PrivKey(priv)
182 pubKey := privKey.PubKey()
183 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 03de79435cbc8a799efc24cdce7d3b180fb014d5f19949fb8d61de3f21b9f6c1f8
184
185 //str := "test"
186 str := "75628d14409a5126e6c882d05422c06f5eccaa192c082a9a5695a8e707109842"
187 //hx := hex.EncodeToString([]byte(str))
188 //fmt.Println(hx)
189 sign, err := privKey.Sign([]byte(str))
190 if err != nil {
191 return
192 }
193
194 fmt.Println(hex.EncodeToString(sign))
195}
19633f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
197026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
198package main
199
200import (
201 "encoding/hex"
202 "fmt"
203
204 "math/big"
205
206 "github.com/cosmos/cosmos-sdk/crypto/hd"
207 "github.com/cosmos/go-bip39"
208 "github.com/tendermint/tendermint/crypto/secp256k1"
209
210 //"github.com/btcsuite/btcd/btcec"
211 "golang.org/x/crypto/cryptobyte"
212 "golang.org/x/crypto/cryptobyte/asn1"
213)
214
215func main() {
216
217 //
218 // Derive private and public key (this part works)
219 //
220 seed := bip39.NewSeed("blast about old claw current first paste risk involve victory edit current", "")
221 fmt.Println("Seed: ", hex.EncodeToString(seed)) // Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
222
223 master, ch := hd.ComputeMastersFromSeed(seed)
224 path := "m/44'/1022'/0'/0/0'"
225 priv, _ := hd.DerivePrivateKeyForPath(master, ch, path)
226 fmt.Println("Derivation Path: ", path) // Derivation Path: m/44'/1022'/0'/0/0'
227 fmt.Println("Private Key: ", hex.EncodeToString(priv)) // Private Key: 33f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
228
229 var privKey = secp256k1.PrivKey(priv)
230 pubKey := privKey.PubKey()
231 fmt.Println("Public Key: ", hex.EncodeToString(pubKey.Bytes())) // Public Key: 026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
232
233 //
234 // Sign (this part needs to be fixed)
235 //
236 data := "test"
237
238 signature, _ := privKey.Sign([]byte(data))
239 fmt.Println(hex.EncodeToString(signature))
240
241 rVal := new(big.Int)
242 rVal.SetBytes(signature[0:32])
243 sVal := new(big.Int)
244 sVal.SetBytes(signature[32:64])
245 var b cryptobyte.Builder
246 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
247 b.AddASN1BigInt(rVal)
248 b.AddASN1BigInt(sVal)
249 })
250 signatureDER, _ := b.Bytes()
251 fmt.Println("Signature, DER: ", hex.EncodeToString(signatureDER))
252
253 /*
254 hash, _ := hex.DecodeString("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08")
255
256 // Sign without hashing
257 privateKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), priv)
258 signature, _ := privateKey.Sign(hash[:])
259
260 // Convert to ASN1/DER
261 rVal := new(big.Int)
262 rVal.SetBytes(signature.R.Bytes())
263 sVal := new(big.Int)
264 sVal.SetBytes(signature.S.Bytes())
265 var b cryptobyte.Builder
266 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
267 b.AddASN1BigInt(rVal)
268 b.AddASN1BigInt(sVal)
269 })
270 signatureDER, _ := b.Bytes()
271 fmt.Println("Signature, DER: ", hex.EncodeToString(signatureDER))
272 */
273}
274Seed: dd5ffa7088c0fa4c665085bca7096a61e42ba92e7243a8ad7fbc6975a4aeea1845c6b668ebacd024fd2ca215c6cd510be7a9815528016af3a5e6f47d1cca30dd
275Derivation Path: m/44'/1022'/0'/0/0'
276Private Key: 33f34dad4bc0ce9dc320863509aed43cab33a93a29752779ae0df6dbbea33e56
277Public Key: 026557fe37d5cab1cc8edf474f4baff67dbb2305f1764e42d31b09f83296f5de2b
27857624717f71fae8b5917cde0f82dfe6c2e2104183ba01c6a1c9f0a8e66d3303e5035b52876d833522aace232c1d231b3aeeff303cf02d1677a240102365ce71b
279Signature, DER: 3044022057624717f71fae8b5917cde0f82dfe6c2e2104183ba01c6a1c9f0a8e66d3303e02205035b52876d833522aace232c1d231b3aeeff303cf02d1677a240102365ce71b
280return signing_key.sign_digest( # type: ignore
281 digest=bytearray.fromhex(data),
282 sigencode=sigencode_der
283).hex()
284from ecdsa.util import sigdecode_der
285signature = signing_key.sign_digest( # from Python Code
286 digest=bytearray.fromhex(data),
287 sigencode=sigencode_der
288)
289#signature = bytes.fromhex('3044022057624717f71fae8b5917cde0f82dfe6c2e2104183ba01c6a1c9f0a8e66d3303e02205035b52876d833522aace232c1d231b3aeeff303cf02d1677a240102365ce71b') # from Go code
290verifying_key = signing_key.verifying_key
291verified = verifying_key.verify_digest(signature, digest=bytearray.fromhex(data), sigdecode=sigdecode_der)
292print(verified)
293return signature.hex()
294
The test shows that both, the Python and Go code signatures are successfully verified, proving that the signature generated with the Go code is valid.
Remark 3: The Python code generates a non-deterministic signature, i.e. the signature is different even with identical input data.
In contrast, the Go code generates a deterministic signature, i.e. the signature is the same for identical input data (see here).
If the Go code should also generate a non-deterministic signature, other libraries must be used on the Go side (but this might not actually be necessary, since the non-deterministic and the deterministic variant are established algorithms and generate valid signatures in accordance with the above test).
QUESTION
Flag provided but not defined: -rpc
Asked 2022-Feb-19 at 20:07Am starting off in blockchain development using the book Mastering Blockchain - A deep dive into distributed ledgers, consensus protocols, smart contracts, DApps, cryptocurrencies, Ethereum,
Am using WSL with geth version 1.10.9.
1$geth version
2Geth
3Version: 1.10.9-stable
4Git Commit: eae3b1946a276ac099e0018fc792d9e8c3bfda6d
5Architecture: amd64
6Go Version: go1.17
7Operating System: linux
8GOPATH=
9GOROOT=go
10
Am trying to start geth, but am getting the error that the --rpc flag is not defined.
This is the command I am trying to run:
geth --datadir ~/etherprivate/ --networkid 786 --rpc --rpcapi 'web3,eth,net,debug,personal' --rpccorsdomain '*'
Any help on how I can solve it?
ANSWER
Answered 2021-Oct-11 at 23:20It appears 1.10.9-stable version has a problem and is returning a -rpc error. GETH 1.10.8-stable version works fine when running the geth command with --rpc
QUESTION
ParserError: Source file requires different compiler version
Asked 2022-Feb-08 at 13:18I tried all that you mentioned in the discussion here (in other questions) and at https://github.com/smartcontractkit/full-blockchain-solidity-course-py/discussions/522 , however it is not solving the issue for me, I also noticed that the current compiler version remains (current compiler is 0.6.12+commit.27d51765.Windows.msvc). But when I right click and select Solidty:Compiler information, it shows 0.8.0.
from output:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3
Not sure if that is related to the issue I face. Anyways starting with the problem I see when running brownie compile. I get the error below:
error in terminal:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22
My .sol file is Lottery.sol:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111
I also tried to google some solutions so my settings.json file is a bit different but that didnt help too.
settings.json:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118
In the brownie-config.yaml, I tried all the versions of openzepplin contracts too from old to latest (4.4.0, 4.3.0,4.3.2 etc), but same error.
brownie-config.yaml
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129
I also tried to change the compiler in lottery.sol file with
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129// SPDX-License-Identifier: MIT
130pragma solidity ^0.8.0;
131
Now I get a different error. Completely lost here :(
terminal:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129// SPDX-License-Identifier: MIT
130pragma solidity ^0.8.0;
131INFO: Could not find files for the given pattern(s).
132Brownie v1.17.2 - Python development framework for Ethereum
133
134Compiling contracts...
135 Solc version: 0.8.11
136 Optimizer: Enabled Runs: 200
137 EVM Version: Istanbul
138CompilerError: solc returned the following errors:
139
140ParserError: Source file requires different compiler version (current compiler is 0.8.11+commit.d7f03943.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
141 --> C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol:2:1:
142 |
1432 | pragma solidity ^0.6.0;
144 | ^^^^^^^^^^^^^^^^^^^^^^^
145
146PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
147
I am very new to programing in solidity and this is the first course I am following, I don't want to give up so easily, any help is much appreciated.
ANSWER
Answered 2022-Jan-02 at 03:09i had the same issue. i had this compiler setting:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129// SPDX-License-Identifier: MIT
130pragma solidity ^0.8.0;
131INFO: Could not find files for the given pattern(s).
132Brownie v1.17.2 - Python development framework for Ethereum
133
134Compiling contracts...
135 Solc version: 0.8.11
136 Optimizer: Enabled Runs: 200
137 EVM Version: Istanbul
138CompilerError: solc returned the following errors:
139
140ParserError: Source file requires different compiler version (current compiler is 0.8.11+commit.d7f03943.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
141 --> C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol:2:1:
142 |
1432 | pragma solidity ^0.6.0;
144 | ^^^^^^^^^^^^^^^^^^^^^^^
145
146PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
147pragma solidity >=0.4.22 <0.9.0;
148
Since we are importing from openzeppelin
, I visied github repo and saw that it uses pragma solidity ^0.8.0;
So changed my setting to
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129// SPDX-License-Identifier: MIT
130pragma solidity ^0.8.0;
131INFO: Could not find files for the given pattern(s).
132Brownie v1.17.2 - Python development framework for Ethereum
133
134Compiling contracts...
135 Solc version: 0.8.11
136 Optimizer: Enabled Runs: 200
137 EVM Version: Istanbul
138CompilerError: solc returned the following errors:
139
140ParserError: Source file requires different compiler version (current compiler is 0.8.11+commit.d7f03943.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
141 --> C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol:2:1:
142 |
1432 | pragma solidity ^0.6.0;
144 | ^^^^^^^^^^^^^^^^^^^^^^^
145
146PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
147pragma solidity >=0.4.22 <0.9.0;
148 pragma solidity >=0.4.22 <0.8.0;
149
Community Discussions contain sources that include Stack Exchange Network
Tutorials and Learning Resources in Blockchain
Tutorials and Learning Resources are not available at this moment for Blockchain