注意

官方文档:Running a Chainlink Node | Chainlink Documentation

  1. 本教程和官方教程的区别在于,本教程基于自己搭建的Geth私有链而非Goerli测试网
  2. 建议先在本地创建账户,再创建json文件,然后去metamask添加import account,最后再在启动私链的命令中添加–unlock参数解锁账户,实现交易的打包。这一步,目的是为在Remix上部署LinkToken合约做准备。
  3. 在metamask上添加创建的账户是为后续在Remix上部署合约做准备
  4. 在Remix上部署LinkToken合约的目的是为后续给预言机节点转账做准备

用Geth搭建私有链

下载Geth

1
2
3
4
apt-get install software-properties-common
add-apt-repository -y ppa:ethereum/ethereum
apt-get update
apt-get install ethereum

随后创建如下的文件目录

1
2
3
4
/myChain
├── chainlink
└── localChain
├── node1

输入如下命令创建账户

1
sudo geth --datadir ./ account new

可以通过两种方式配置创世区块:

  • 直接配置genesis.json文件
  • 使用puppeth配置创世区块

0xedd96278959aA8B27DdC14FD70ACb31f7e7beC2F

0xCDA9035668b149d18905349Fa8779073e433820C

如果要直接配置genesis.json文件,可参考如下写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"config": {
"chainId": 15,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0,
"eip150Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00",
"alloc": {
"18aCF602A4C1f4915709bA09A0bFd83A58656CA4": { "balance": "300000000000000000000" },
"8c304567E5d337cB60301a998e430F056EF9F622": { "balance": "400000000000000000000" }
}
}

初始化。注意每次修改JSON文件后都必须初始化

1
geth init --datadir data testchain.json

在~/myChain/localChain/node1下启动私链

1
geth --datadir data --gcmode "archive" --syncmode=full --networkid 4190 --http --http.addr 0.0.0.0 --http.port 6789 --http.corsdomain "*" --ws --port 30305 --allow-insecure-unlock --unlock edd96278959aA8B27DdC14FD70ACb31f7e7beC2F --keystore ./keystore console

私链启动以后,就去Metamask添加网络。

Metamask具体可以看这篇:https://blog.csdn.net/llslinliansheng/article/details/123596009

私链开启挖矿

1
2
miner.setEtherbase("edd96278959aa8b27ddc14fd70acb31f7e7bec2f")
miner.start()

搭建Chainlink预言机

由于LinkToken.sol的Solidity代码需要在GitHub拉取,可以通过在主页按T键搜索LinkToken.sol文件,找到文件所在目录,并拉取其V0.4的所有文件。同时要修改import部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
pragma solidity ^0.4.11;

import "https://github.com/smartcontractkit/chainlink/contracts/src/v0.4/ERC677Token.sol";
import { StandardToken as linkStandardToken } from "https://github.com/smartcontractkit/chainlink/contracts/src/v0.4/vendor/StandardToken.sol";


contract LinkToken is linkStandardToken, ERC677Token {

uint public constant totalSupply = 10**27;
string public constant name = "ChainLink Token";
uint8 public constant decimals = 18;
string public constant symbol = "LINK";

function LinkToken()
public
{
balances[msg.sender] = totalSupply;
}

/**
* @dev transfer token to a specified address with additional data if the recipient is a contract.
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
* @param _data The extra data to be passed to the receiving contract.
*/
function transferAndCall(address _to, uint _value, bytes _data)
public
validRecipient(_to)
returns (bool success)
{
return super.transferAndCall(_to, _value, _data);
}

/**
* @dev transfer token to a specified address.
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
*/
function transfer(address _to, uint _value)
public
validRecipient(_to)
returns (bool success)
{
return super.transfer(_to, _value);
}

/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* @param _spender The address which will spend the funds.
* @param _value The amount of tokens to be spent.
*/
function approve(address _spender, uint256 _value)
public
validRecipient(_spender)
returns (bool)
{
return super.approve(_spender, _value);
}

/**
* @dev Transfer tokens from one address to another
* @param _from address The address which you want to send tokens from
* @param _to address The address which you want to transfer to
* @param _value uint256 the amount of tokens to be transferred
*/
function transferFrom(address _from, address _to, uint256 _value)
public
validRecipient(_to)
returns (bool)
{
return super.transferFrom(_from, _to, _value);
}


// MODIFIERS

modifier validRecipient(address _recipient) {
require(_recipient != address(0) && _recipient != address(this));
_;
}

}

随后使用Remix部署合约,然而私链终端需要对交易进行打包,解锁账户,开始挖矿。

安装PostgreSQL和docker,这里不细说。PostgreSQL的安装过程具体可以看这篇文章:技术|如何在 Ubuntu 上安装和配置 PostgreSQL (linux.cn)

我使用的PostgreSQL版本和docker版本如下:

1
2
3
4
5
6
7
8
9
10
11
12
keikei@ubuntu:~$ psql --version
psql (PostgreSQL) 12.14 (Ubuntu 12.14-0ubuntu0.20.04.1)
keikei@ubuntu:~$ docker version
Client: Docker Engine - Community
Version: 23.0.1
API version: 1.42
Go version: go1.19.5
Git commit: a5ee5b1
Built: Thu Feb 9 19:46:56 2023
OS/Arch: linux/amd64
Context: default
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/version": dial unix /var/run/docker.sock: connect: permission denied

随后在~/myChain/chainlink/.chainlink下创建.env文件

1
2
3
4
5
6
7
8
9
10
ROOT=/chainlink
LOG_LEVEL=debug
ETH_CHAIN_ID=4190
CHAINLINK_TLS_PORT=0
LINK_CONTRACT_ADDRESS=0x2C8ed9723635a66597Ee5f94E626453A3528fE26
SECURE_COOKIES=false
ALLOW_ORIGINS=*
ETH_URL=ws://127.0.0.1:8546
DATABASE_URL=postgresql://postgres:Likeqi5201314000@localhost:5432/chainlink?sslmode=disable
DATABASE_TIMEOUT=0

随后启动预言机

1
docker run --net host -u=root  -p 6688:6688 -v ~/.chainlink:/chainlink -it --env-file=.env smartcontract/chainlink:1.11.0 local n

在本地浏览器输入127.0.0.1:6688,打开Chainlink Operator

至此,Chainlink分布式预言机节点已经搭建完毕。