I don't know what's the matter with people: they don't learn by understanding, they learn by some other way — by rote or something. Their knowledge is so fragile! (Feynman)
The string to search. It can be CHAR, VARCHAR2, NCHAR, NVARCHAR2, CLOB, or NCLOB.
pattern
The regular expression matching information. It can be a combination of the following:
Value
Description
^
Matches the beginning of a string. If used with a match_parameter of ‘m’, it matches the start of a line anywhere within expression.
$
Matches the end of a string. If used with a match_parameter of ‘m’, it matches the end of a line anywhere within expression.
*
Matches zero or more occurrences.
+
Matches one or more occurrences.
?
Matches zero or one occurrence.
.
Matches any character except NULL.
|
Used like an “OR” to specify more than one alternative.
[ ]
Used to specify a matching list where you are trying to match any one of the characters in the list.
[^ ]
Used to specify a nonmatching list where you are trying to match any character except for the ones in the list.
( )
Used to group expressions as a subexpression.
{m}
Matches m times.
{m,}
Matches at least m times.
{m,n}
Matches at least m times, but no more than n times.
\n
n is a number between 1 and 9. Matches the nth subexpression found within ( ) before encountering \n.
[..]
Matches one collation element that can be more than one character.
[::]
Matches character classes.
[==]
Matches equivalence classes.
\d
Matches a digit character.
\D
Matches a nondigit character.
\w
Matches a word character.
\W
Matches a nonword character.
\s
Matches a whitespace character.
\S
matches a non-whitespace character.
\A
Matches the beginning of a string or matches at the end of a string before a newline character.
\Z
Matches at the end of a string.
*?
Matches the preceding pattern zero or more occurrences.
+?
Matches the preceding pattern one or more occurrences.
??
Matches the preceding pattern zero or one occurrence.
{n}?
Matches the preceding pattern n times.
{n,}?
Matches the preceding pattern at least n times.
{n,m}?
Matches the preceding pattern at least n times, but not more than m times.
start_position
Optional. It is the position in string where the search will start. If omitted, it defaults to 1 which is the first position in the string.
nth_appearance
Optional. It is the nth appearance of pattern in string. If omitted, it defaults to 1 which is the first appearance of pattern in string.
match_parameter
Optional. It allows you to modify the matching behavior for the REGEXP_SUBSTR function. It can be a combination of the following:
Value
Description
‘c’
Perform case-sensitive matching.
‘i’
Perform case-insensitive matching.
‘n’
Allows the period character (.) to match the newline character. By default, the period is a wildcard.
‘m’
expression is assumed to have multiple lines, where ^ is the start of a line and $ is the end of a line, regardless of the position of those characters in expression. By default, expression is assumed to be a single line.
‘x’
Whitespace characters are ignored. By default, whitespace characters are matched like any other character.
subexpression
Optional. This is used when pattern has subexpressions and you wish to indicate which subexpression in pattern is the target. It is an integervalue from 0 to 9 indicating the subexpression to match on in pattern.
Returns
The REGEXP_SUBSTR function returns a string value.
If the REGEXP_SUBSTR function does not find any occurrence of pattern, it will return NULL.
Note
If there are conflicting values provided for match_parameter, the REGEXP_SUBSTR function will use the last value.
If you omit the match_behavior parameter, the REGEXP_SUBSTR function will use the NLS_SORT parameter to determine if it should use a case-sensitive search, it will assume that string is a single line, and assume the period character to match any character (not the newline character).
NOTE: Configuring authentication for SERVER mode.
Enter the email address and password to use for the initial pgAdmin user account:
Email address: admin@itzgeek.local
Password: xxxxxxxxx
Retype password: xxxxxxxxx
pgAdmin 4 - Application Initialisation
======================================
Restart the Apache web service.
systemctl restart httpd
My https configuration file for Apache
For CentOS 7:
<VirtualHost *:80>
ServerName pg.saic.it
Redirect permanent / https://pg.saic.it/pgadmin4/
</VirtualHost>
<VirtualHost *:443>
ServerName pg.saic.it
LoadModule wsgi_module modules/mod_wsgi.so
SSLEngine on
SSLCertificateFile /etc/ssl/certs/pg.saic.it.crt
SSLCertificateKeyFile /etc/ssl/certs/pg.saic.it.key
SSLCACertificateFile /etc/ssl/certs/saic.sslforfree.ca
WSGIDaemonProcess pgadmin processes=1 threads=25
WSGIScriptAlias /pgadmin4 /usr/lib/python2.7/site-packages/pgadmin4-web/pgAdmin4.wsgi
<Directory /usr/lib/python2.7/site-packages/pgadmin4-web/>
WSGIProcessGroup pgadmin
WSGIApplicationGroup %{GLOBAL}
<IfModule mod_authz_core.c>
# Apache 2.4
Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
# Apache 2.2
Order Deny,Allow
Deny from All
Allow from 127.0.0.1
Allow from ::1
</IfModule>
</Directory>
</VirtualHost>
if you have this error in your Apache log file : Fatal Python error: PyEval_AcquireThread: NULL new thread state
is because mod_python have to removed from the modules
After the installation when you do an update the steps are: A, B, C
To update an existing domain with adding a new subdomain
--expand tells Certbot to update an existing certificate with a new certificate that contains all of the old domains and one or more additional new domains. With the --expand option, use the -d option to specify all existing domains and one or more new domains.
1. Verifica l’elenco dei certificati gestiti da Certbot
Esegui il comando seguente per visualizzare tutti i certificati attualmente gestiti da Certbot:
certbot certificates
Troverai una lista dei certificati attivi, con informazioni come il dominio principale, eventuali domini aggiuntivi, e il percorso del file di configurazione.
2. Identifica il certificato da rimuovere
Annota il nome del dominio o il cert name associato al certificato che desideri rimuovere.
3. Elimina il certificato
Per rimuovere il certificato e la sua configurazione dai rinnovi automatici, usa il comando:
certbot delete --cert-name nome-certificato
Sostituisci nome-certificato con il valore del Cert Name trovato nel passo precedente.
Our series of blockchain tutorials has been very popular. The tutorials have been read tens of thousands of times and several hundred people have joined our Telegram community to give us feedback and ask questions.
The most common feedback people give is that our blog posts are useful in making complicated blockchain concepts simple and understandable. However, they are missing Peer-to-Peer functionality.
We’ve done everything from showing you how to code Proof of Work to letting you know how IPFS works. However, in each of our tutorials, we relied on a central server to show you these concepts.
We will now show you how to run a simple blockchain in a truly decentralized, Peer-to-Peer fashion. Let’s get started!
Background
What is Peer-to-Peer (P2P)?
In true Peer-to-Peer architecture, you don’t need a central server to maintain the state of a blockchain. For example, when you send your friend some Bitcoin, the “state” of the Bitcoin blockchain should be updated so your friend’s balance increases and your balance decreases.
There isn’t a central authority like a bank that maintains the state. Instead, all the nodes in the Bitcoin network that wish to maintain a copy of the Bitcoin blockchain update their copies of the blockchain to include your transaction. That way, as long as 51% of the nodes in the network “agree” on the state of the blockchain, it maintains its fidelity. Read more on this consensus concept here.
In this tutorial, we will rework our post, Code your own blockchain in less than 200 lines of Go! so it uses a Peer-to-Peer architecture instead of a central server. We strongly recommend reading it before proceeding. It will help you understand the forthcoming code.
Let’s get coding!
Coding a P2P network is no joke. It has a ton of edge cases and requires a lot of engineering to make it scalable and reliable. Like any good engineer, we will first see what tools are available as a starting point. Let’s stand on the shoulders of giants.
Luckily, there is an excellent P2P library written in Go called go-libp2p. Coincidentally, it is made by the same folks who created IPFS. If you haven’t checked out our IPFS tutorial, take a look here (don’t worry it’s not mandatory for this tutorial).
Warning
As far as we can tell, this go-libp2p library has 2 drawbacks:
Setup is a pain. It uses gx as a package manager that we don’t find very convenient.
It appears to still be under heavy development. When working with the code, you will encounter some minor data races. They have some kinks to iron out.
Don’t worry about #1. We’ll help you through it. #2 is a bigger issue but won’t affect our code. However, if you do notice data races, they are most likely coming from the underlying code of this library. So make sure to open an issue and let them know.
There are very few modern, open source P2P libraries available, particularly in Go. Overall, go-libp2p is quite good and it’s well suited to our objectives.
Setup
The best way to get your code environment set up is to clone this entire library and write your code within it. You can develop outside the environment they provide but it requires knowing how to work with gx. We’ll show you the easy way. Assuming you already have Go installed:
go get -d github.com/libp2p/go-libp2p/...
navigate to the cloned directory from above
make
make deps
This gets you all the packages and dependencies you need from this repo through the gx package manager. Again, we don’t like gx as it breaks a lot of Go convention (besides, why not just stick with go get?) but it’s worth the inconvenience to use this otherwise nice library.
We’re going to develop inside the examples subdirectory. So let’s create a directory under examples called p2p with
mkdir ./examples/p2p
Then navigate to your new p2p folder and create a main.go file. We will be writing all our code in this file.
Your directory tree should look like this:
Open up your main.go file and let’s start writing our code!
Imports
Let’s make our package declaration and list our imports. Most of these imports are packages provided by the go-libp2p library. You’ll learn how to use each of them throughout this tutorial.
The spew package is a simple convenience package to pretty print our blockchain. Make sure to:
go get github.com/davecgh/go-spew/spew
Blockchain stuff
Remember! Read this tutorialbefore proceeding. The following section will be much easier to understand after reading it!
Let’s declare our global variables.
Block is the transaction info we want. We are using BPM (beats per minute, or our pulse rate) as the key data point going in each block. Take your pulse rate and remember that number. Remember, we’re a healthcare company so we’re not going to use boring financial transactions as our block data 😉
Blockchain is our “state”, or the latest blockchain, which is just a slice of Block
We declare a mutex so we can control for and prevent race conditions in our code
Write out the following blockchain-specific functions.
isBlockValid checks to see that the chain of hashes in each block of the blockchain is consistent
calculateHash uses sha256 to hash raw data
generateBlock creates a new block to be added to the blockchain, with the necessary transaction info inside it
P2P Stuff
Host
Now we get to the meat of our tutorial. The first thing we want to do is write the logic that allows a host to be created. When a node runs our Go program, it should act as a host to which other nodes (or peers) can connect. Here’s the code. Don’t stress, we’ll walk you through it 🙂
Our makeBasicHost function takes 3 arguments and returns the host and an error (which is nil if no errors are encountered).
listenPort is the port we specify in our command line flags that other peers connect to
secio is a boolean that turns on and off secure data streams. It’s generally a good idea to use it. It stands for “secure input/output”
randSeed is an optional command line flag that allows us to supply a seed to create a random address for our host. We won’t use this but it’s nice to have.
The function’s first if statement determines whether the seed was supplied and generates keys for our host accordingly. We then generate our public and private keys so our host stays secure. The opts section starts to construct the address to which other peers can connect.
The !secio part bypasses encryption but we’re going to use secio for security so this line doesn’t apply to us for now. It’s fine to have this option though.
We then create the host and finalize the addresses that other peers can connect to. The log.Printf part at the end is the helpful console message we print that tells a new node how to connect to the host we just created.
We then return the fully created host to the caller of the function. We now have our host!
Stream handler
We need to allow our host to deal with incoming data streams. When another node connects to our host and wants to propose a new blockchain to overwrite our own, we need logic to determine whether or not we should accept it.
When we add blocks to our blockchain, we want to broadcast it to our connected peer, so we need logic to do that as well.
Let’s create the skeleton of our handler.
We create a new ReadWriter since we need both read and write and we spin up separate Go routines to deal with the read and write logic.
Read
Let’s create our readData function first.
Our function is an infinite loop since it needs to stay open to incoming blockchains. We parse our incoming blockchain from a peer which is just a string of a JSON blob with ReadString. If it’s not empty (!= “\n”) we Unmarshal the blob first.
Then we check to see if the length of the incoming chain is longer than the blockchain we’re storing ourselves. For our purposes, we are simply going by blockchain length to determine who wins out. If the incoming chain is longer than ours, we’ll accept it as the latest network state (or the latest, “true” blockchain).
We’ll Marshal it back into a JSON format so it’s easier to read then we print it to our console. The fmt.Printf command prints in a different color so it’s easy for us to know it’s a new chain.
Now we’ve accepted our peer’s blockchain, if we add a new block to our blockchain, we need a way to let our connected peer know about it, so they can accept ours. We do that with our writeData function.
Write
We start the function off with a Go routine that broadcasts the latest state of our blockchain every 5 seconds to our peers. They’ll receive it and throw it away if the length is shorter than theirs. They’ll accept it if it’s longer. Either way, all the peers are constantly getting their blockchains updated by the latest state of the network.
We now need a way to create a new block with the pulse rate (BPM) we took earlier. We create a new reader with bufio.NewReader so it can read our stdin (console input). We want to be able to continually add new blocks so we put this in an infinite loop.
We do a little bit of string manipulation to make sure the BPM we type in is an integer and properly formatted to be added as a new block. We go through our standard blockchain functions (see the “Blockchain stuff” section above). Then we Marshal it so it looks pretty, print it to our console to verify with spew.Dump. We then broadcast it to our connected peer with rw.WriteString.
Great! We’ve now finished our blockchain functions and most of our P2P functions. We’ve created our handler, and the read and write logic to deal with incoming and outgoing blockchains. Through these functions we’ve created a way for each peer to continually check the state of their blockchain against each other and collectively, they all get updated to the latest state (longest valid blockchain).
All that’s left now is wiring up our main function.
Main function
Here is our main function. Have a look through it first then we’ll go through it step by step.
We start off by creating a Genesis block, which is our seed block for our blockchain. Again, if you read our previous tutorial this should be review.
We use the go-libp2p library’s logger to handle logging with SetAllLoggers. This is optional.
We then set all our command line flags.
secio we covered previously and allows for secure streams. We’ll make sure to always use this by setting the flag when running our program.
target lets us specify the address of another host we want to connect to, which means we’re acting as a peer to a host if we use this flag.
listenF opens the port we want to allow connections to, which means we’re acting as a host. We can be both a host (receive connections) and a peer (connect to other hosts). This is what makes this system truly P2P!
seed is the optional randomness seeder used to construct our address that other peers can use to connect to us.
We then create a new host with the makeBasicHost function we created earlier. If we’re only acting as a host (i.e. we’re not connecting to other hosts) we specify that with if *target == “” , fire up our handler with the setStreamHandle function we made earlier and that’s the end of our listener code.
If we do want to connect to another host we move onto the else section. We set our handler again, since we’re acting as a host AND a connecting peer.
The next few lines deconstruct the string we supply to target so we can find the host we want to connect to. This is also called Decapsulation.
We end up with the peerID and target address targetAddr of the host we want to connect to and add that record into our “store” so we can keep track of who we’re connected to. We do that with ha.Peerstore().AddAddr
We then create our connection stream to the peer we want to connect to with ha.NewStream. We want to be able to receive and send them streams of data (our blockchain) so just like we did in our handler, we create a ReadWriterand spin up separate Go routines for readData and writeData. We finish off by blocking with an empty select statement so our program doesn’t just finish and quit.
Wahoo!
Guess what? We’re done! I know that was a bit of a handful but considering how complicated P2P engineering is you should proud that you made it to the end! That wasn’t too bad was it?
Now let’s get to what we’re all here for and try this out! We’re going to be using 3 separate terminals to act as individual peers.
Before starting the app, do yourself a favor and go to the root directory of go-libp2p and run make deps again. This makes sure your dependencies are in order. Again, this library uses the annoying gx package manager and we have to do a couple things to make it play nice.
Go back to your working directory.
On your first terminal, go run main.go -l 10000 -secio
Terminal 1
Follow the instructions that say “Now run…”. Open up a 2nd terminal, go to the same directory and go run main.go -l 10001 -d <given address in the instructions> -secio
Terminal 2
You’ll see the first terminal detected the new connection!
Terminal 1
Now following the instructions in the 2nd terminal, open up a 3rd terminal, go to the same working directory and go run main.go -l 10002 -d <given address in the instructions> -secio
Terminal 3
Check out the 2nd terminal, which detected the connection from the 3rd terminal.
Terminal 2
Now let’s start inputting our BPM data. Type in “70” in our 1st terminal, give it a few seconds and watch what happens in each terminal.
Terminal 1Terminal 2Terminal 3
What just happened here? It’s really cool so let’s think it through.
Terminal 1 added a new block to its blockchain
It then broadcast it to Terminal 2
Terminal 2 compared it against its own blockchain, which only contained its genesis block. It saw Terminal 1 had a longer chain so it replaced its own chain with Terminal 1’s chain. Then it broadcast the new chain to Terminal 3.
Terminal 3 compared the new chain against its own and replaced it.
All 3 terminals updated their blockchains to the latest state with no central authority! This is the power of Peer-to-Peer.
Let’s test it again but this time allow Terminal 2 to add a block. Type in “80” into Terminal 2.
Terminal 2Terminal 1Terminal 3
Awesome! As expected, this time Terminal 2 added a new block and broadcast it to the rest of the network. Each of the peers ran its own internal checks and updated their blockchains to the latest blockchain of the network!
Next Steps
Take a breather and enjoy your handy work. You just coded up a simple but fully functioning P2P blockchain in just a few hundred lines of code. This is no joke. P2P programming is very complicated, which is why you don’t see many simple tutorials out there on how to create your own P2P network.
There are some improvements and caveats to take away. Challenge yourself and try to tackle one or more of these:
As mentioned, the go-libp2p library is not perfect. We were careful to ensure our own code has minimal (if any) data races but while we were testing this library we noticed they had some data races in their code. It didn’t affect the results we were expecting to see but be extra cautious if you’re using this external library in production. Let them know about bugs you find as their library is a work in progress.
Try incorporating consensus mechanisms to this tutorial. We just did a simple check to see which blockchain was the longest, but you could incorporate either our Proof of Work or Proof of Stake tutorials to have a more robust check.
Add persistence to the code. Right now, for simplicity, we shut down all the nodes if you kill one of them. You can leave all other nodes running even if one closes. If one node dies, it should be able to relay the info in its Peer Store to its connected nodes so they can connect to each other.
This code hasn’t been tested with hundreds of nodes. Try writing a shell script to scale many nodes and see how performance is affected. If you notice any bugs, make sure to file an issue or submit a pull request in our Github repo!
Look into node discovery. How do new nodes find existing nodes? Here’s a good place to start.
That’s all for now!
Where will your P2P journey go from here? Between this and our other tutorials, you have almost all the building blocks to create your own blockchain from scratch. That’s serious stuff!
Make sure to let us know what you think by joining our Telegramchat. This is the best place to get help with your code or just geek out with us on blockchain topics! We have a very vibrant community that would love to hear from you. Ask us anything!
Here are the links to our other tutorials. Read them all!
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.AcceptRejectRead More
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are as essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.