Skip to content

Instantly share code, notes, and snippets.

Avatar

Michael Graczyk mgraczyk

View GitHub Profile
View marcel_vos_rct_maze_mdp.py
import numpy as np
from matplotlib import pyplot as plt
def make_Av(N):
a = 1 - 0.5 * 0.75
b = 0.5 * 0.25
A = np.zeros((2 * N + 2, 2 * N + 2))
View init_once_async_example.py
import asyncio
num_times = 0
async def one_time_setup():
global num_times
num_times += 1
print("doing setup")
await asyncio.sleep(1)
View perlin10.go
func (n *Node) IsAccepted(tx *Transaction) bool {
mutex.RLock()
defer mutex.RUnlock()
committed := false
for _, parent := range tx.Body.GetParents() {
parent := n.Transactions[parent]
committed = committed && n.IsAccepted(parent)
}
set := n.Conflicts[tx.Body.Utxo]
// [OT] safe early commitment.
View perlin9.go
// ... update the preference for ancestors
// [OT] This only loops over parents, not ancestors
for _, parentId := range tx.Body.Parents {
mutex.RLock()
parent := n.Transactions[parentId]
conflicts := n.Conflicts[parent.Body.Utxo]
mutex.RUnlock()
parentScore, presentScore := n.Confidence(parent), n.Confidence(conflicts.Preferred)
if parentScore > presentScore {
conflicts.Preferred = parent
View perlin8.go
func QueryEvents(n *Node, rpc RPC) {
// [OT] Line 2 with modified condition
for id, tx := range n.Unqueried() {
// [OT] Check that the transactions parents are known
// In a real implementation, undigestible txns
// would eventually need to be pruned.
if !n.IsDigestable(tx) {
continue
}
// [OT] Lines 4-5
View perlin7.go
func (n *Node) IsStronglyPreferred(tx *Transaction) bool {
mutex.RLock()
defer mutex.RUnlock()
stronglyPreferred := true
parents := // ... make map of parent ids
for len(parents) != 0 {
for parentId := range parents {
// [OT] stronglyPreferred could be memoized here for efficiency
// This is a downside of using protocol buffers for state.
// Additional in-memory state can't be stored naturally because
View perlin6.go
func (n *Node) OnReceiveTx(tx *Transaction) bool {
// ... Verify tx
// [OT] Take a global read lock.
mutex.Lock()
defer mutex.Unlock()
// [OT] Line 9
if _, received := n.Transactions[tx.Id]; !received {
// [OT] Line 10
if set, exists := n.Conflicts[tx.Body.Utxo]; exists {
set.Transactions[tx.Id] = tx // [OT] Line 13
View perlin5.go
case *messages.QueryRequest:
response := &messages.QueryResponse{}
if msg.Transaction != nil && msg.Transaction.Verify() {
stronglyPreferred := state.node.OnQueryTx(msg.Transaction)
response.Transaction = msg.Transaction.Id
response.StronglyPreferred = stronglyPreferred
ctx.Respond(response)
}
// [OT] Always respond with empty? Does this overwrite?
ctx.Respond(response)
View perlin4.go
// Searches for suitable parent transactions for a new transaction.
func (n *Node) SelectParents() []string {
// [OT] The lock could be held for less time with BFS
mutex.RLock()
defer mutex.RUnlock()
var eligibleParents []*Transaction
// [OT] Search every historical transaction.
for _, tx := range n.Transactions {
if n.IsStronglyPreferred(tx) {
// [OT] Figure 19, line 2
View perlin3.go
// [OT] This case corresponds to onGenerateTx in the paper.
case *messages.ApiReceiveTransaction:
// [OT] small race, should be `utxo := atomic.Add...() - 1`
// already being fixed by Perlin
utxo := atomic.LoadUint64(&messages.LastUTXO)
atomic.AddUint64(&messages.LastUTXO, 1)
body := messages.CreateTx(utxo, store.GetKeys().PublicKeyHex(), state.node.SelectParents(), msg.Data)
state.node.OnReceiveTx(body.Sign(store.GetKeys()))
You can’t perform that action at this time.