“The world computer” – rețea descentralizată de noduri care pot executa secvențe de cod și salva rezultatele intr-o baza de date (blockchain).
Ethereum oferă posibilitatea dezvoltării de aplicații descentralizate, oferă disponibilitate 100% (24/7) transparenta, securitate, poate fi auditat codul de orice entitate și este neutru din punct de vedere politic, guvernamental sau emotional.
Componentele Ethereum:
O rețea de noduri (softuri care rulează pe computer fizice sau virtuale in cloud), nodurile sunt interconectate și au scopul de a transmite (propaga) tranzacții în rețea. Anumite noduri au “dreptul” (își câștigă dreptul găsind soluții brute force la niste probleme matematice) de a scrie informație în baza de date (blockchain). Găsirea soluțiilor se face printr-un algoritm de consens numit “proof of work”. Acest algoritm totodată rasplateste pe cei care găsesc soluțiile cu ether tokens.
Tranzactii - sunt de 2 tipuri, un tip muta (transfera) ether tokens dintr-un cont în altul și alt tip de tranzacție sunt reprezentate de lansari(deploy)/executii de smart contracts.
EVM (Ethereum Virtual Machine) - o masina virtuala care are rolul de a executa deterministic pe baza unor reguli definite de protocolul Ethereum secvențe de cod numite smart contracts.
Instalare portofel MetaMask
Portofelul MetaMask este unul dedicat Ethereum si poate fi instalat ca o extensie de Chrome (sau orice browser compatibil). MetaMask este mai mult decat un wallet obisnuit dar mai multe pe tema aceasta mai tarziu in curs.
Pentru a instala MetaMask trebuie sa navigati la https://metamask.io/.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract PI {
// unique document id
uint256 hCount;
// doc owner address => doc id => document info
mapping(address => mapping(uint256 => PIData)) public documents;
// count documents per address ... doc owner address => number of documents
mapping(address => uint256) documentsCount;
mapping(string => address) fileHashes;
// doc owner address => doc id => buyer address => amount
mapping(address => mapping(uint256 => mapping(address => uint256))) public pendingTransfers;
struct PIData {
// document unique id
uint256 id;
address ownerAddress;
string name;
string fileHash;
uint time;
}
constructor() {
hCount = 1;
}
// document functions add/verify/get documents from blockchain
function AddDocument(string calldata _name, string calldata _fileHash) public {
require(fileHashes[_fileHash] == address(0x0));
documents[msg.sender][documentsCount[msg.sender]] =
PIData(hCount, msg.sender, _name, _fileHash, block.timestamp);
documentsCount[msg.sender] ++;
hCount++;
fileHashes[_fileHash] = msg.sender;
}
function OwnerDocumentCount(address _ownerAddress) public view returns (uint256) {
return documentsCount[_ownerAddress];
}
function VerifyDocumentId(address _ownerAddress, uint256 _id) public view returns (uint, bool, string memory) {
for (uint i = 0; i < documentsCount[_ownerAddress]; i++) {
if (documents[_ownerAddress][i].id == _id)
return (documents[_ownerAddress][i].time, true, documents[_ownerAddress][i].fileHash);
}
return (0, false, "not found");
}
function Verify(address _ownerAddress, string memory _fileHash) public view returns (uint256) {
for (uint i = 0; i < documentsCount[_ownerAddress]; i++) {
if (compareStrings(documents[_ownerAddress][i].fileHash, _fileHash))
return (documents[_ownerAddress][i].id);
}
return (0);
}
// transaction functions
function RequestTransfer(uint256 _docId, address _ownerAddress) public payable {
for (uint i = 0; i < documentsCount[_ownerAddress]; i++) {
if (documents[_ownerAddress][i].id == _docId) {
require(pendingTransfers[_ownerAddress][_docId][msg.sender] == 0);
pendingTransfers[_ownerAddress][_docId][msg.sender] += msg.value;
}
}
}
function CancelTransfer(uint256 _docId, address _ownerAddress) public {
require(pendingTransfers[_ownerAddress][_docId][msg.sender] > 0);
payable(msg.sender).transfer(pendingTransfers[_ownerAddress][_docId][msg.sender]);
pendingTransfers[_ownerAddress][_docId][msg.sender] = 0;
}
function CompleteTransfer(uint256 _docId, address _buyerAddress) public {
require(pendingTransfers[msg.sender][_docId][_buyerAddress] > 0);
for (uint i = 0; i < documentsCount[msg.sender]; i++) {
if (documents[msg.sender][i].id == _docId) {
require(documents[msg.sender][i].id > 0);
PIData storage pid = documents[msg.sender][i];
documents[_buyerAddress][documentsCount[_buyerAddress]] =
PIData(_docId, _buyerAddress, pid.name, pid.fileHash, pid.time);
documentsCount[_buyerAddress] ++;
DestroyDocument(msg.sender, _docId, _buyerAddress);
break;
}
}
payable(msg.sender).transfer(pendingTransfers[msg.sender][_docId][_buyerAddress]);
pendingTransfers[msg.sender][_docId][_buyerAddress] = 0;
}
function DestroyDocument(address _adr, uint256 _id, address _buyerAddress) private {
for (uint i = 0; i < documentsCount[_adr]; i++) {
if (documents[_adr][i].id == _id)
{
documents[_adr][i].id = 0;
documents[_adr][i].ownerAddress = _buyerAddress;
documents[_adr][i].name = "information transfered";
documents[_adr][i].fileHash = "N/A";
documents[_adr][i].time = block.timestamp;
break;
}
}
}
// helper functions
function compareStrings (string memory a, string memory b) private pure returns (bool) {
return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
}
}
Andreas M. Antonopoulos Mastering Bitcoin: Programming the Open Blockchain. O'Reilly Media.
Andreas M. Antonopoulos; Gavin Wood Ph. D.. Mastering Ethereum. O'Reilly Media.
https://blockchainlab.com/pdf/Ethereum_white_paper-a_next_generation_smart_contract_and_decentralized_application_platform-vitalik-buterin.pdf
https://www.taurushq.com/articles/20201127_ETH2_0/20201127_Ethereum_2.0_Introduction.pdf
https://docs.soliditylang.org/en/v0.8.7/
https://ethereum.org/en/eth2/beacon-chain/