0% found this document useful (0 votes)
54 views

blockchain 52

Uploaded by

rajand2510
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
54 views

blockchain 52

Uploaded by

rajand2510
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 34

Block Chain Technology (CT703D-N) 21BECE30052

Practical – 1
Aim: 1. Understanding Block using
 https://tools.superdatascience.com/Blockchain/block.
 The block in the block chain plays an important role during transaction of bitcoins,
storing information related user.

OUTPUT:
Block Chain Technology (CT703D-N) 21BECE30052

Aim:2. Understanding Block chain using


https://tools.superdatascience.com/Blockchain/Blockchain

 Block chain is a system of recording information in a way that makes


it difficult or impossible to change, hack, or cheat the system.. Each
block in the chain contains a number of transactions, and every time
a new transaction occurs on the block chain, arecord of that
transaction is added to every participant's ledger.

OUTPUT:
Block Chain Technology (CT703D-N) 21BECE30052

Aim:3.Understanding Distributed block chain using.

https://tools.superdatascience.com/Blockchain/Blockchain

 A distributed ledger is a database that is consensually shared and synchronized across


multiple sites, institutions, or geographies, accessible by multiple people. Underlying
distributed ledgers is the same technology that is used by blockchain, which is the
technology that is used by bitcoin.

OUTPUT:
Block Chain Technology (CT703D-N) 21BECE30052

Aim:4.Understanding Tokens using.


https://tools.superdatascience.com/Blockchain/Blockchain

 TOKENS are digital assets defined by a project or smart contract and built on a
specific block chain.

OUTPUT:
Block Chain Technology (CT703D-N) 21BECE30052

Aim:5.Understanding Coin base using.


https://tools.superdatascience.com/Blockchain/Blockchain

 Coin base is an easy way for those who are new to cryptocurrency to get started. Its
easy-to-use interface lets people buy and sell crypto in just a few clicks. While not
every type of cryptocurrency is supported, you will find many of the most popular
coins there.

OUTPUT:
Block Chain Technology (CT703D-N) 21BECE30052

Practical – 2
Using JavaScript
Aim: 1. Creating a block chain using Javascript.

const SHA256 = require('crypto-js/sha256');

class Block {
constructor(index, timestamp, data, previousHash = '') {
this.index = index;
this.timestamp = timestamp;
this.data = data;
this.previousHash = previousHash;
this.hash = this.calculateHash();
}

calculateHash() {
return SHA256(this.index + this.previousHash + this.timestamp +
JSON.stringify(this.data)).toString();
}
}

class Blockchain {
constructor() {
this.chain = [this.createGenesisBlock()];
}

createGenesisBlock() {
return new Block(0, "01/01/2020", "Genesis Block", "0");
}

getLatestBlock() {
Block Chain Technology (CT703D-N) 21BECE30052

return this.chain[this.chain.length - 1];


}
addBlock(newBlock) {
newBlock.previousHash = this.getLatestBlock().hash;
newBlock.hash = newBlock.calculateHash();
this.chain.push(newBlock);
}
isChainValid() {
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];

if (currentBlock.hash !== currentBlock.calculateHash()) {


return false;
}

if (currentBlock.previousHash !== previousBlock.hash) {


return false;
}
}
return true;
}
}

let myCoin = new Blockchain();


myCoin.addBlock(new Block(1, "10/07/2024", { amount: 4 }));
myCoin.addBlock(new Block(2, "12/07/2024", { amount: 10 }));
myCoin.addBlock(new Block(3, "13/07/2024", { amount: 5 }));

console.log(JSON.stringify(myCoin, null, 4));


Block Chain Technology (CT703D-N) 21BECE30052

console.log('Blockchain valid? ' + myCoin.isChainValid());


OUTPUT:

Aim :2. Implementing Proof-Of-Work using Javascript


Block Chain Technology (CT703D-N) 21BECE30052

const SHA256 = require('crypto-js/sha256');

class Block {
constructor(index, timestamp, data, previousHash = '') {
this.index = index;
this.timestamp = timestamp;
this.data = data;
this.previousHash = previousHash;
this.hash = this.calculateHash();
this.nonce = 0;
}

calculateHash() {
return SHA256(this.index + this.previousHash + this.timestamp +
JSON.stringify(this.data) + this.nonce).toString();
}

mineBlock(difficulty) {
while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) {
this.nonce++;
this.hash = this.calculateHash();
}
console.log("Block mined: " + this.hash);
}
}

class Blockchain {
constructor() {
this.chain = [this.createGenesisBlock()];
this.difficulty = 2;
}
Block Chain Technology (CT703D-N) 21BECE30052

createGenesisBlock() {
return new Block(0, "01/01/2020", "Genesis Block", "0");
}

getLatestBlock() {
return this.chain[this.chain.length - 1];
}

addBlock(newBlock) {
newBlock.previousHash = this.getLatestBlock().hash;
newBlock.mineBlock(this.difficulty);
this.chain.push(newBlock);
}

isChainValid() {
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];

if (currentBlock.hash !== currentBlock.calculateHash()) {


return false;
}

if (currentBlock.previousHash !== previousBlock.hash) {


return false;
}
}
return true;
}
Block Chain Technology (CT703D-N) 21BECE30052

let myCoin = new Blockchain();


console.log("Mining block 1...");
myCoin.addBlock(new Block(1, "15/07/2024", { amount: 4 }));

console.log("Mining block 2...");


myCoin.addBlock(new Block(2, "17/07/2024", { amount: 10 }));

console.log(JSON.stringify(myCoin, null, 4));


console.log('Blockchain valid? ' + myCoin.isChainValid());
OUTPUT:

Aim: 3. Miner Rewards and Transaction using Javascript.


Block Chain Technology (CT703D-N) 21BECE30052

const SHA256 = require('crypto-js/sha256');

class Transaction {
constructor(fromAddress, toAddress, amount) {
this.fromAddress = fromAddress;
this.toAddress = toAddress;
this.amount = amount;
}
}

class Block {
constructor(timestamp, transactions, previousHash = '') {
this.timestamp = timestamp;
this.transactions = transactions;
this.previousHash = previousHash;
this.hash = this.calculateHash();
this.nonce = 0;
}

calculateHash() {
return SHA256(this.previousHash + this.timestamp + JSON.stringify(this.transactions)
+ this.nonce).toString();
}
mineBlock(difficulty) {
while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) {
this.nonce++;
this.hash = this.calculateHash();
}
console.log("Block mined: " + this.hash);
}
}
Block Chain Technology (CT703D-N) 21BECE30052

class Blockchain {
constructor() {
this.chain = [this.createGenesisBlock()];
this.difficulty = 2;
this.pendingTransactions = [];
this.miningReward = 200;
}
createGenesisBlock() {
return new Block("10/01/2024", [], "0");
}
getLatestBlock() {
return this.chain[this.chain.length - 1];
}
minePendingTransactions(miningRewardAddress) {
const rewardTx = new Transaction(null, miningRewardAddress, this.miningReward);
this.pendingTransactions.push(rewardTx);

let block = new Block(Date.now(), this.pendingTransactions,


this.getLatestBlock().hash);
block.mineBlock(this.difficulty);
console.log("Block successfully mined!");
this.chain.push(block);
this.pendingTransactions = [];
}
createTransaction(transaction) {
this.pendingTransactions.push(transaction);
}
getBalanceOfAddress(address) {
let balance = 0;
for (const block of this.chain) {
Block Chain Technology (CT703D-N) 21BECE30052

for (const trans of block.transactions) {


if (trans.fromAddress === address) {
balance -= trans.amount;
}
if (trans.toAddress === address) {
balance += trans.amount;
}
}
}
return balance;
}
isChainValid() {
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];
if (currentBlock.hash !== currentBlock.calculateHash()) {
return false;
}
if (currentBlock.previousHash !== previousBlock.hash) {
return false;
}
}
return true;
}
}
let myCoin = new Blockchain();
myCoin.createTransaction(new Transaction('address1', 'address2', 200));
myCoin.createTransaction(new Transaction('address2', 'address1', 50));
console.log("Starting the miner...");
myCoin.minePendingTransactions('miner-address');
Block Chain Technology (CT703D-N) 21BECE30052

console.log("Balance of miner is", myCoin.getBalanceOfAddress('miner-address'));


console.log("Starting the miner again...");
myCoin.minePendingTransactions('miner-address');

console.log("Balance of miner is", myCoin.getBalanceOfAddress('miner-address'));

OUTPUT:

Aim :4. Signing Transactions using Javascript.


Block Chain Technology (CT703D-N) 21BECE30052

const SHA256 = require('crypto-js/sha256');


const EC = require('elliptic').ec;
const ec = new EC('secp256k1');

class KeyPair {
constructor() {
this.key = ec.genKeyPair();
}

getPublic() {
return this.key.getPublic('hex');
}

getPrivate() {
return this.key.getPrivate('hex');
}
}

class Transaction {
constructor(fromAddress, toAddress, amount) {
this.fromAddress = fromAddress;
this.toAddress = toAddress;
this.amount = amount;
this.signature = null;
}

calculateHash() {
return SHA256(this.fromAddress + this.toAddress + this.amount).toString();
}
Block Chain Technology (CT703D-N) 21BECE30052

signTransaction(signingKey) {
if (signingKey.getPublic('hex') !== this.fromAddress) {
throw new Error('You cannot sign transactions for other wallets!');
}

const hashTx = this.calculateHash();


const sig = signingKey.sign(hashTx, 'base64');
this.signature = sig.toDER('hex');
}

isValid() {
if (this.fromAddress === null) return true;

if (!this.signature || this.signature.length === 0) {


throw new Error('No signature in this transaction');
}

const publicKey = ec.keyFromPublic(this.fromAddress, 'hex');


return publicKey.verify(this.calculateHash(), this.signature);
}
}

class Block {
constructor(timestamp, transactions, previousHash = '') {
this.timestamp = timestamp;
this.transactions = transactions;
this.previousHash = previousHash;
this.hash = this.calculateHash();
this.nonce = 0;
}
Block Chain Technology (CT703D-N) 21BECE30052

calculateHash() {
return SHA256(this.previousHash + this.timestamp + JSON.stringify(this.transactions)
+ this.nonce).toString();
}
mineBlock(difficulty) {
while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) {
this.nonce++;
this.hash = this.calculateHash();
}
console.log("Block mined: " + this.hash);
}
hasValidTransactions() {
for (const tx of this.transactions) {
if (!tx.isValid()) {
return false;
}
}
return true;
}
}
class Blockchain {
constructor() {
this.chain = [this.createGenesisBlock()];
this.difficulty = 2;
this.pendingTransactions = [];
this.miningReward = 200;
}

createGenesisBlock() {
return new Block("10/01/2024", [], "0");
}
Block Chain Technology (CT703D-N) 21BECE30052

getLatestBlock() {
return this.chain[this.chain.length - 1];
}
minePendingTransactions(miningRewardAddress) {
const rewardTx = new Transaction(null, miningRewardAddress, this.miningReward);
this.pendingTransactions.push(rewardTx);

let block = new Block(Date.now(), this.pendingTransactions,


this.getLatestBlock().hash);
block.mineBlock(this.difficulty);
console.log("Block successfully mined!");
this.chain.push(block);
this.pendingTransactions = [];
}
addTransaction(transaction) {
if (!transaction.fromAddress || !transaction.toAddress) {
throw new Error('Transaction must include from and to address');

if (!transaction.isValid()) {
throw new Error('Cannot add invalid transaction to chain');
}
this.pendingTransactions.push(transaction);
}
getBalanceOfAddress(address) {
let balance = 0;
for (const block of this.chain) {
for (const trans of block.transactions) {
if (trans.fromAddress === address) {
balance -= trans.amount;
}
Block Chain Technology (CT703D-N) 21BECE30052

if (trans.toAddress === address) {


balance += trans.amount;
}
}
}
return balance;

isChainValid() {
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];

if (!currentBlock.hasValidTransactions()) {
return false;
}

if (currentBlock.hash !== currentBlock.calculateHash()) {


return false;
}

if (currentBlock.previousHash !== previousBlock.hash) {


return false;
}
}
return true;
}
}
// Testing the implementation
const myKey = ec.genKeyPair();
const myWalletAddress = myKey.getPublic('hex');
Block Chain Technology (CT703D-N) 21BECE30052

let myCoin = new Blockchain();


const tx1 = new Transaction(myWalletAddress, 'address2', 10);
tx1.signTransaction(myKey);
myCoin.addTransaction(tx1);

console.log("Starting the miner...");


myCoin.minePendingTransactions(myWalletAddress);

console.log("Balance of my wallet is", myCoin.getBalanceOfAddress(myWalletAddress));


OUTPUT:

Aim :5. Angular Frontend using Javascript.


Block Chain Technology (CT703D-N) 21BECE30052

const crypto = require('crypto');


const EC = require('elliptic').ec;
const ec = new EC('secp256k1');
const debug = require('debug')('savjeecoin:blockchain');
class Transaction {
constructor(fromAddress, toAddress, amount) {
this.fromAddress = fromAddress;
this.toAddress = toAddress;
this.amount = amount;
this.timestamp = Date.now();
}
calculateHash() {
return crypto.createHash('sha256').update(this.fromAddress + this.toAddress + this.amount
+ this.timestamp).digest('hex');
}
signTransaction(signingKey) {
if (signingKey.getPublic('hex') !== this.fromAddress) {
throw new Error('You cannot sign transactions for other wallets!');
}
const hashTx = this.calculateHash();
const sig = signingKey.sign(hashTx, 'base64');
this.signature = sig.toDER('hex');
}
isValid() {
if (this.fromAddress === null) return true;
if (!this.signature || this.signature.length === 0) {
throw new Error('No signature in this transaction');
}
const publicKey = ec.keyFromPublic(this.fromAddress, 'hex');
return publicKey.verify(this.calculateHash(), this.signature);
}
}
Block Chain Technology (CT703D-N) 21BECE30052

class Block {
constructor(timestamp, transactions, previousHash = '') {
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"savjeecoin-frontend": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {
"@schematics/angular:component": {
"styleext": "scss"
}
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/savjeecoin-frontend",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
Block Chain Technology (CT703D-N) 21BECE30052

],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
Block Chain Technology (CT703D-N) 21BECE30052

"options": {
"browserTarget": "savjeecoin-frontend:build"
},
"configurations": {
"production": {
"browserTarget": "savjeecoin-frontend:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "savjeecoin-frontend:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.scss"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
}
},
Block Chain Technology (CT703D-N) 21BECE30052

"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"savjeecoin-frontend-e2e": {
"root": "e2e/",
"projectType": "application",
"prefix": "",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "savjeecoin-frontend:serve"
},
"configurations": {
"production": {
"devServerTarget": "savjeecoin-frontend:serve:production"
}
}
},
"lint": {
Block Chain Technology (CT703D-N) 21BECE30052

"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "savjeecoin-frontend"
}

Practical – 3
Block Chain Technology (CT703D-N) 21BECE30052

Aim: 1. Introduction to Geth.


 Geth is an implementation of an Ethereum node in the Go programming
language
 In simpler terms, Geth is a program which serves as a node for the Ethereum
blockchain, and via which a user can mine Ether and create software which
runs on the EVM – the Ethereum Virtual Machine.
 This software can be things like crypto tokens, decentralized apps, and more.
 After startup, Geth will connect to the existing live blockchain or create its
own, depending on provided settings. Left at the default values, Geth will
connect to the live Ethereum blockchain (the Mainnet) which we use daily.
 Simply by running Geth, you're already participating in making the Ethereum
network better and stronger. Geth also serves as a console for inputting certain
commands and executing specific functions.

Aim 2. Creation of private Block chain.


Block Chain Technology (CT703D-N) 21BECE30052

Step 1 — Environment Setup


 First, you need to install Geth which is a command-line interface (CLI) tool
that communicates with the Ethereum network and acts as the link between
your computer and the rest of the Ethereum nodes.
Step 2 — Configure the Genesis file
 To run a private network, you need to provide geth with some basic
information required to create the initial block. Every blockchain starts with
a Genesis Block, the very first block in the chain. To create our private
blockchain, we will create a genesis block with a custom genesis file. Then, ask
Geth to use that genesis file to create our own genesis block.
Custom Genesis file
{
"nonce": "0x0000000000000042",
"timestamp": "0x0",
"parentHash":
"0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x00",
"gasLimit": "0x8000000",
"difficulty": "0x400",
"mixhash":
"0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x3333333333333333333333333333333333333333",
"alloc": {},
"config": {"chainId": 987, "homesteadBlock": 0, "eip155Block": 0,
"eip158Block": 0}
}
Explanation on the config file;
• chainId: A unique identifier of the new private blockchain
• homesteadBlock: Homestead is the first production release of Ethereum and
since the developers are already using this version the value of this parameter can
Block Chain Technology (CT703D-N) 21BECE30052

be left as ‘0’.
Block Chain Technology (CT703D-N)
• eip155Block/eip158Block: EIP stands for “Ethereum Improvement
Proposals”, these were implemented to release Homestead. In a private
blockchain development, hard forks aren’t needed, hence the parameter value
should be left as ‘0’.
• difficulty: Controls the complexity of the mining puzzle and a lower value
enables quicker mining.
• gasLimit: Establishes an upper limit for executing smart contracts.
• alloc: Allows allocation of Ether to a specific address.
 Paste the above code in the genesis.json file and save it in a folder on your
computer.
 Next, open the terminal and run the following code snippet. This will instruct
Geth to use genesis.json file to be the first block of your custom blockchain.
 We also specify a data directory where our private chain data will be stored.
 Choose a location on your computer (separate folder from the public Ethereum
chain folder, if you have one) and Geth will create the data directory for you.
geth --rpc --rpcport "8085" --datadir
/path_to_your_data_directory/TestChain init
/path_to_folder/genesis.json
Once you run this snippet, you can see the following terminal result

Step 3 — Create a Private Network


 Next, we will start our private network to mine new blocks to our private chain. Run
the following code snippet on your terminal. The parameter “networkid” is a unique
id to identify our private blockchain network.
 The main Ethereum network has “1” as the networkid. Give any random number
except “1” to create our unique network.
geth --rpc --rpcport "8085" --datadir
Block Chain Technology (CT703D-N) 21BECE30052

/path_to_your_data_directory/TestChain --networkid 123 –nodiscover


Now your private network will go live. After running the above snippet, the terminal gives
the following result.
3. Creation of Account.
 Open another terminal window and run the following snippet to open Geth console.

geth attach /path_to_your_data_directory/TestChain/geth.ipc You will get a JavaScript


console like the following.

 Now create a new account by typing


personal.newAccount() and give a password.
Simple!
 Please remember the account address and password
because it will be needed very often.
 Check the balance of theaccount by
typing
eth.getBalance(“ENTER_ACCOUNT_ADDRESS_HERE”)

Here’s what I got:

There are two ways to get ether to your account. You can mine
blocks and get rewarded with ether or someone sends you
some ether to your account.

Since you are alone in your private network at this point, the
only way isto mine some blocks and get rewarded.

Mining in the main Ethereum network is hard and need more

computational power. However, mining blocks in a private


Block Chain Technology (CT703D-N) 21BECE30052

network is easy since we specified a low difficulty level in the

genesis.json file.

To mine ether to your account, simply type miner.start() in the Geth


console. After 10–15 seconds, check the balance again. To
stop mining,
run miner.stop()

After that your account is created and lots of ether


are there in your account but they all are fake
ethers.

 To add or to mine a new node, run the commands as shown in


above Step 2 to Step 4 in a new terminal.

Important Note:

1. You must use the same genesis.json file to initiate


thenode.

2. You must use a different data directory

folder to the newnode. 3. Make sure to use

the same networkid for the new node.

4. You need to give a port number because the default port is


already used by the first node.

1.geth --rpc --rpcport "8085" --datadir

/path_to_your_data_directory/TestChain

2.init /path_to_folder/genesis.json2. geth

--rpc --rpcport "8085" --datadir


Block Chain Technology (CT703D-N) 21BECE30052

/path_to_your_data_directory/TestChain2 --

networkid 123 --nodiscover --port 30306

 In the console of the second node, run

admin.nodeInfo.enode You should get something

similar to this.

 Note:
 [::] will be parsed as localhost (127.0.0.1). If your
nodes are on a local network check each individual host
machine and find your IP with ifconfig
 If your peers are not on the local network, you need to

know your external IP address (use a service) to

construct the enode URL.

 Copy this value and in the console of the first noderun,


 admin.addPeer("enode://

f2da64f49c30a0038bba3391f40805d531510c473ec2bcc7

c201631ba003c6f16fa09e03308e48f87d21c0fed1e4e0bc

53428047f6dcf34da344d3f 5bb69373b@[::]:30306?

discport=0")

 This will return true if successful, but that doesn’t mean

the node was added successfully. To confirm run

admin.peers and you should see the details of the node

you just added.


Block Chain Technology (CT703D-N) 21BECE30052

 If you start mining on the first node by running


miner.start(), you will see the block number increase
on the second node.
 Congratulations! You just built your first
private Ethereum blockchain, mined some
ether and added more peers to the network!

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy