Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Greybeard
momiji-node-mainnet
Commits
f813ab6b
Commit
f813ab6b
authored
9 months ago
by
John Doe
Browse files
Options
Download
Email Patches
Plain Diff
🟣
parent
671a85fd
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
238 additions
and
175 deletions
+238
-175
.env.example
.env.example
+7
-3
.gitignore
.gitignore
+1
-0
.gitmodules
.gitmodules
+3
-0
Dockerfile
Dockerfile
+7
-3
README.md
README.md
+1
-1
momiji-helpers/utils/peering.ts
momiji-helpers/utils/peering.ts
+64
-148
momiji-helpers/utils/types.ts
momiji-helpers/utils/types.ts
+1
-0
package.json
package.json
+6
-6
src/index.ts
src/index.ts
+42
-1
src/modules/momiji.ts
src/modules/momiji.ts
+106
-13
No files found.
.env.example
View file @
f813ab6b
# Private key used for publishing
# RPC that supports eth_getLogs
RPC_URL=
RPC_URL=https://rpc.mevblocker.io/
# Private key
# If private key is filled, it will be used for both deposits and publishing -- be careful if you are doing both
# If private key is filled, it will be used for both deposits and publishing -- be careful if you are doing both
PRIVATE_KEY=
PRIVATE_KEY=
THREADS=0 # Use all available threads
THREADS=0 # Use all available threads
...
@@ -23,4 +24,7 @@ RELAYS=
...
@@ -23,4 +24,7 @@ RELAYS=
# Nostr Relay APIs ("Seed" nodes) -- expects an array returned
# Nostr Relay APIs ("Seed" nodes) -- expects an array returned
MAX_RELAYS=8
MAX_RELAYS=8
SEEDS=https://api.nostr.watch/v1/online
SEEDS=https://api.nostr.watch/v1/online
\ No newline at end of file
# Your public ip in case you are using a tunneling service
PUBLIC_IP=
\ No newline at end of file
This diff is collapsed.
Click to expand it.
.gitignore
View file @
f813ab6b
...
@@ -24,3 +24,4 @@ yarn-error.log*
...
@@ -24,3 +24,4 @@ yarn-error.log*
# Ignore OS generated files
# Ignore OS generated files
.DS_Store
.DS_Store
Thumbs.db
Thumbs.db
package-lock.json
\ No newline at end of file
This diff is collapsed.
Click to expand it.
.gitmodules
0 → 100644
View file @
f813ab6b
[submodule "momiji-helpers"]
path = momiji-helpers
url = http://open.offshift.io/greybeard/momiji-helpers.git
This diff is collapsed.
Click to expand it.
Dockerfile
View file @
f813ab6b
FROM
node:20.
0
FROM
node:20.
2
RUN
mkdir
/code
&&
mkdir
/code/node
RUN
mkdir
/code
&&
mkdir
/code/node
WORKDIR
/code/node
WORKDIR
/code/node
RUN
wget https://github.com/noir-lang/noir/releases/download/v0.28.0/nargo-x86_64-unknown-linux-gnu.tar.gz
RUN
wget https://github.com/noir-lang/noir/releases/download/v0.28.0/nargo-x86_64-unknown-linux-gnu.tar.gz
...
@@ -9,5 +9,9 @@ COPY . .
...
@@ -9,5 +9,9 @@ COPY . .
RUN
npm
install
RUN
npm
install
RUN
cd
./momiji-helpers/
&&
npm
install
RUN
cd
./momiji-helpers/
&&
npm
install
WORKDIR
/code/node
WORKDIR
/code/node
RUN
apt update
&&
apt
install
-y
tor libc++-dev
ENTRYPOINT
[ "npm", "start"]
RUN
echo
"HiddenServiceDir /var/lib/tor/hidden_service/"
>>
/etc/tor/torrc
RUN
echo
"HiddenServicePort 80 127.0.0.1:5150"
>>
/etc/tor/torrc
RUN
service tor start
RUN
update-rc.d tor
enable
ENTRYPOINT
[ "npm", "start" ]
This diff is collapsed.
Click to expand it.
README.md
View file @
f813ab6b
...
@@ -24,7 +24,7 @@ sudo docker build -t xftnode .
...
@@ -24,7 +24,7 @@ sudo docker build -t xftnode .
for running
for running
```
sh
```
sh
sudo
docker run
-it
xftnode
sudo
docker run
-p
5150:5150
-it
xftnode
```
```
### npm usage
### npm usage
-
Install noirup, the Nargo package manager
-
Install noirup, the Nargo package manager
...
...
This diff is collapsed.
Click to expand it.
momiji-helpers/utils/peering.ts
View file @
f813ab6b
// @ts-ignore
// @ts-ignore
import
*
as
types
from
'
./types
'
;
import
*
as
types
from
'
./types
'
;
import
{
TransactionBuilder
}
from
"
./transactionBuilder
"
;
import
{
TransactionBuilder
}
from
"
./transactionBuilder
"
;
import
{
createLibp2p
}
from
'
libp2p
'
// import { createLibp2p } from 'libp2p'
import
{
webSockets
}
from
'
@libp2p/websockets
'
// import * as filters from '@libp2p/websockets/filters'
import
*
as
filters
from
'
@libp2p/websockets/filters
'
import
{
finalizeEvent
,
verifyEvent
,
setNostrWasm
,
VerifiedEvent
,
Event
}
from
'
nostr-tools/wasm
'
import
{
finalizeEvent
,
verifyEvent
,
setNostrWasm
,
VerifiedEvent
,
Event
}
from
'
nostr-tools/wasm
'
import
{
SimplePool
}
from
'
nostr-tools/pool
'
import
{
SimplePool
}
from
'
nostr-tools/pool
'
import
{
gossipsub
}
from
'
@chainsafe/libp2p-gossipsub
'
//
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
import
{
noise
}
from
'
@chainsafe/libp2p-noise
'
//
import { noise } from '@chainsafe/libp2p-noise'
import
{
yamux
}
from
'
@chainsafe/libp2p-yamux
'
//
import { yamux } from '@chainsafe/libp2p-yamux'
import
{
mplex
}
from
'
@libp2p/mplex
'
//
import { mplex } from '@libp2p/mplex'
import
{
identify
}
from
"
@libp2p/identify
"
//
import { identify } from "@libp2p/identify"
import
{
dcutr
}
from
"
@libp2p/dcutr
"
//
import { dcutr } from "@libp2p/dcutr"
import
{
getPublicKey
}
from
'
nostr-tools/pure
'
;
import
{
getPublicKey
}
from
'
nostr-tools/pure
'
;
import
{
initNostrWasm
}
from
'
nostr-wasm
'
import
{
initNostrWasm
}
from
'
nostr-wasm
'
import
{
multiaddr
}
from
'
@multiformats/multiaddr
'
//
import { multiaddr } from '@multiformats/multiaddr'
import
{
useWebSocketImplementation
}
from
'
nostr-tools/pool
'
import
{
useWebSocketImplementation
}
from
'
nostr-tools/pool
'
import
{
pubsubPeerDiscovery
}
from
'
@libp2p/pubsub-peer-discovery
'
import
WebSocket
from
'
ws
'
import
WebSocket
from
'
ws
'
import
{
Block
}
from
'
ethers
'
;
if
(
typeof
global
===
"
object
"
)
useWebSocketImplementation
(
WebSocket
);
if
(
typeof
global
===
"
object
"
)
useWebSocketImplementation
(
WebSocket
);
export
class
Peering
extends
TransactionBuilder
{
export
class
Peering
extends
TransactionBuilder
{
p2p
:
any
|
undefined
;
//
p2p: any | undefined;
pool
:
SimplePool
=
new
SimplePool
();
pool
:
SimplePool
=
new
SimplePool
();
relays
:
string
[];
relays
:
string
[];
seeds
:
string
[];
seeds
:
string
[];
rebroadcast
:
any
|
undefined
;
rebroadcast
:
any
|
undefined
;
callback
:
Function
;
//
callback: Function;
constructor
(
_config
:
types
.
GlobalConfig
)
{
constructor
(
_config
:
types
.
GlobalConfig
)
{
super
(
_config
);
super
(
_config
);
if
(
!
this
.
config
.
gossip
)
throw
new
Error
(
"
Gossip config not found
"
);
//
if (!this.config.gossip) throw new Error("Gossip config not found");
this
.
pool
=
new
SimplePool
();
this
.
pool
=
new
SimplePool
();
this
.
relays
=
this
.
config
.
gossip
!
.
relays
;
this
.
relays
=
this
.
config
.
gossip
!
.
relays
;
this
.
seeds
=
this
.
config
.
gossip
!
.
seeds
;
this
.
seeds
=
this
.
config
.
gossip
!
.
seeds
;
this
.
callback
=
()
=>
true
;
//
this.callback = () => true;
}
}
postEvent
=
async
(
_sk
:
Uint8Array
,
_timestamp
:
number
)
=>
Promise
.
any
(
this
.
pool
.
publish
(
this
.
relays
,
finalizeEvent
({
postEvent
=
async
(
_sk
:
Uint8Array
,
_timestamp
:
number
,
ips
:
string
)
=>
Promise
.
any
(
this
.
pool
.
publish
(
this
.
relays
,
finalizeEvent
({
kind
:
1
,
kind
:
1
,
created_at
:
_timestamp
,
created_at
:
_timestamp
,
tags
:
[],
tags
:
[],
content
:
this
.
p2p
.
getMultiaddrs
().
map
((
addr
:
any
)
=>
multiaddr
(
addr
).
toString
()).
join
(
'
,
'
)
content
:
ips
},
_sk
)))
},
_sk
)))
postTransaction
=
async
(
_tx
:
types
.
Transaction
)
=>
{
const
hexString
=
(
await
this
.
contracts
.
state
.
getAddress
()).
slice
(
2
).
padStart
(
64
,
'
0
'
);
const
matches
=
hexString
.
match
(
/.
{1,2}
/g
);
const
skUint8Array
=
matches
?
new
Uint8Array
(
matches
.
map
(
byte
=>
parseInt
(
byte
,
16
)))
:
new
Uint8Array
();
const
_pk
:
string
=
getPublicKey
(
skUint8Array
);
if
(
this
.
p2p
.
services
.
pubsub
.
getSubscribers
(
_pk
).
length
>
0
)
{
// postTransaction = async (_tx: types.Transaction) => {
await
this
.
p2p
.
services
.
pubsub
.
publish
(
_pk
,
new
TextEncoder
().
encode
(
JSON
.
stringify
(
_tx
)))
// const hexString = (await this.contracts.state.getAddress()).slice(2).padStart(64, '0');
}
else
{
// const matches = hexString.match(/.{1,2}/g);
setTimeout
(
async
()
=>
await
this
.
postTransaction
(
_tx
),
10
_000
);
// const skUint8Array = matches ? new Uint8Array(matches.map(byte => parseInt(byte, 16))) : new Uint8Array();
}
// const _pk: string = getPublicKey(skUint8Array);
};
// if (this.p2p.services.pubsub.getSubscribers(_pk).length > 0) {
// await this.p2p.services.pubsub.publish(_pk, new TextEncoder().encode(JSON.stringify(_tx)))
// } else {
// setTimeout(async () => await this.postTransaction(_tx), 10_000);
// }
// };
initializePeering
=
async
(
callback
?:
Function
):
Promise
<
void
>
=>
{
initializePeering
=
async
(
callback
?:
Function
):
Promise
<
void
>
=>
{
await
this
.
initializeTransactionBuilder
();
await
this
.
initializeTransactionBuilder
();
const
hexString
=
(
await
this
.
contracts
.
state
.
getAddress
()).
slice
(
2
)
.
padStart
(
64
,
'
0
'
);
const
hexString
=
"
6835ccbeddc1c1c91fed2116099592a309f98d0df34d8dc72e770df83cc3b065
"
.
padStart
(
64
,
'
0
'
);
const
matches
=
hexString
.
match
(
/.
{1,2}
/g
);
const
matches
=
hexString
.
match
(
/.
{1,2}
/g
);
const
skUint8Array
=
matches
?
new
Uint8Array
(
matches
.
map
(
byte
=>
parseInt
(
byte
,
16
)))
:
new
Uint8Array
()
;
const
skUint8Array
=
matches
?
new
Uint8Array
(
matches
.
map
(
byte
=>
parseInt
(
byte
,
16
)))
:
new
Uint8Array
()
let
_pk
=
getPublicKey
(
skUint8Array
);
let
_pk
=
getPublicKey
(
skUint8Array
);
await
this
.
fetchRelays
();
await
this
.
fetchRelays
();
await
initNostrWasm
().
then
(
setNostrWasm
);
await
initNostrWasm
().
then
(
setNostrWasm
);
const
latestBlock
=
await
this
.
config
.
provider
.
getBlock
(
"
latest
"
);
const
latestBlock
=
await
this
.
config
.
provider
.
getBlock
(
"
latest
"
);
let
ip
:
string
let
multiAddrs
:
string
[]
=
[];
if
(
this
.
config
.
ip
==
""
)
{
let
ips
:
string
[]
=
[]
this
.
p2p
=
await
createLibp2p
({
let
ipServices
=
[
"
https://api.ipify.org
"
,
"
https://icanhazip.com
"
,
"
https://ifconfig.me/ip
"
,
"
https://checkip.amazonaws.com/
"
]
addresses
:
{
for
(
let
i
=
0
;
i
<
ipServices
.
length
;
i
++
)
{
listen
:
(
typeof
global
===
"
object
"
)
?
[
'
/ip4/0.0.0.0/tcp/5150/ws
'
]
:
[]
let
res
=
await
fetch
(
ipServices
[
i
])
},
ips
.
push
((
await
res
.
text
()).
trim
())
transports
:
[
webSockets
({
filter
:
filters
.
all
})],
connectionEncryption
:
[
noise
()],
streamMuxers
:
[
yamux
(),
mplex
()],
services
:
{
pubsub
:
gossipsub
(),
identify
:
identify
(),
dcutr
:
dcutr
()
},
connectionGater
:
{
denyDialMultiaddr
:
()
=>
{
return
false
}
},
peerDiscovery
:
[
pubsubPeerDiscovery
({
interval
:
10
_000
})
]
});
await
this
.
p2p
.
start
()
this
.
p2p
.
services
.
pubsub
.
subscribe
(
_pk
)
await
this
.
p2p
.
services
.
pubsub
.
start
()
this
.
p2p
.
addEventListener
(
'
connection:open
'
,
async
(
event
:
CustomEvent
)
=>
{
console
.
log
(
"
peering.ts - connection open
"
,
event
.
detail
.
id
.
toString
())
})
this
.
p2p
.
addEventListener
(
'
connection:close
'
,
()
=>
{
console
.
log
(
"
peering.ts - connection closed
"
)
})
this
.
p2p
.
addEventListener
(
"
peer:connect
"
,
async
(
event
:
CustomEvent
)
=>
{
console
.
log
(
"
peering.ts - peer connect
"
)
})
this
.
p2p
.
addEventListener
(
"
peer:discovery
"
,
(
event
:
CustomEvent
)
=>
{
console
.
log
(
"
peering.ts - peer discovered:
"
,
event
.
detail
.
id
.
toString
())
})
if
(
typeof
global
===
"
object
"
)
{
try
{
this
.
pool
.
subscribeMany
(
this
.
relays
.
slice
(
0
,
this
.
config
.
gossip
!
.
maxRelays
),
[
{
kinds
:
[
1
],
authors
:
[
_pk
],
since
:
latestBlock
!
.
timestamp
},
],
{
onevent
:
async
(
event
)
=>
event
.
content
.
split
(
'
,
'
)
.
filter
(
addr
=>
{
try
{
multiaddr
(
addr
);
return
true
;
}
catch
(
error
)
{
return
false
;
}
})
.
forEach
(
async
(
addr
)
=>
this
.
addPeer
(
addr
)),
oneose
:
async
()
=>
true
,
onclose
:
async
()
=>
true
,
}
)
}
catch
(
error
)
{
}
}
}
else
{
let
last
=
ips
[
0
]
try
{
for
(
let
i
=
0
;
i
<
ips
.
length
;
i
++
)
{
const
events
:
Event
[]
=
await
this
.
pool
.
querySync
(
this
.
relays
.
slice
(
0
,
this
.
config
.
gossip
!
.
maxRelays
),
if
(
last
===
ips
[
i
])
{
{
last
=
ips
[
i
]
kinds
:
[
1
],
}
else
{
authors
:
[
_pk
],
console
.
log
(
"
Please set your public ip in the config file
"
)
since
:
latestBlock
!
.
timestamp
-
(
typeof
global
===
'
object
'
?
0
:
86400
)
return
}
}
)
console
.
log
(
"
peering.ts - nostr events
"
,
events
)
multiAddrs
=
events
.
map
(
event
=>
event
.
content
.
split
(
"
,
"
))
.
flat
(
1
)
.
filter
(
addr
=>
{
try
{
multiaddr
(
addr
);
return
true
;
}
catch
(
error
)
{
return
false
;
}
})
for
(
let
addr
in
multiAddrs
)
await
this
.
addPeer
(
multiAddrs
[
addr
]);
}
catch
(
error
)
{
console
.
log
(
"
error, peering.ts - initializePeering(), pool.querySync()
"
,
error
)
}
}
ip
=
last
}
else
{
ip
=
this
.
config
.
ip
as
string
}
}
if
(
typeof
global
===
'
object
'
)
{
if
(
typeof
global
===
'
object
'
)
{
this
.
rebroadcast
=
setInterval
(
async
()
=>
await
this
.
postEvent
(
skUint8Array
,
latestBlock
!
.
timestamp
),
60
*
60
*
1000
);
this
.
rebroadcast
=
setInterval
(
async
()
=>
{
await
this
.
postEvent
(
skUint8Array
,
latestBlock
!
.
timestamp
);
await
this
.
postEvent
(
skUint8Array
,
latestBlock
!
.
timestamp
,
ip
)
this
.
p2p
.
services
.
pubsub
.
addEventListener
(
'
message
'
,
(
message
:
CustomEvent
)
=>
{
},
60
*
60
*
1000
);
if
(
!
(
message
.
detail
.
topic
==
_pk
)
||
!
callback
)
return
;
callback
(
JSON
.
parse
(
new
TextDecoder
().
decode
(
message
.
detail
.
data
)));
})
await
this
.
postEvent
(
skUint8Array
,
latestBlock
!
.
timestamp
,
ip
);
}
}
}
}
addPeer
=
async
(
peerMultiaddr
:
string
):
Promise
<
void
>
=>
{
queryEvents
=
async
(
latestBlock
:
number
)
=>
{
if
(
!
this
.
p2p
)
{
const
hexString
=
"
6835ccbeddc1c1c91fed2116099592a309f98d0df34d8dc72e770df83cc3b065
"
.
padStart
(
64
,
'
0
'
);
throw
new
Error
(
'
P2P is not initialized
'
);
const
matches
=
hexString
.
match
(
/.
{1,2}
/g
);
}
const
skUint8Array
=
matches
?
new
Uint8Array
(
matches
.
map
(
byte
=>
parseInt
(
byte
,
16
)))
:
new
Uint8Array
()
try
{
let
_pk
=
getPublicKey
(
skUint8Array
);
await
this
.
p2p
.
dial
(
multiaddr
(
peerMultiaddr
));
let
event
=
await
this
.
pool
.
querySync
(
this
.
relays
,
{
console
.
log
(
`Successfully connected to peer:
${
peerMultiaddr
}
`
);
kinds
:
[
1
],
}
catch
(
error
)
{
authors
:
[
_pk
],
}
since
:
latestBlock
-
(
typeof
global
===
'
object
'
?
0
:
86400
)
};
})
}
fetchRelays
=
async
(
refresh
:
boolean
=
false
):
Promise
<
string
[]
>
=>
{
fetchRelays
=
async
(
refresh
:
boolean
=
false
):
Promise
<
string
[]
>
=>
{
if
(
this
.
seeds
.
length
==
0
||
refresh
)
return
this
.
relays
;
if
(
this
.
seeds
.
length
==
0
||
refresh
)
return
this
.
relays
;
for
(
const
seed
of
this
.
seeds
)
{
for
(
const
seed
of
this
.
seeds
)
{
...
...
This diff is collapsed.
Click to expand it.
momiji-helpers/utils/types.ts
View file @
f813ab6b
...
@@ -88,6 +88,7 @@ export type GlobalConfig = {
...
@@ -88,6 +88,7 @@ export type GlobalConfig = {
withdrawal
?:
string
,
withdrawal
?:
string
,
verbose
?:
boolean
,
verbose
?:
boolean
,
threads
?:
number
,
threads
?:
number
,
ip
?:
string
,
provider
:
Provider
provider
:
Provider
}
}
...
...
This diff is collapsed.
Click to expand it.
package.json
View file @
f813ab6b
...
@@ -17,27 +17,27 @@
...
@@ -17,27 +17,27 @@
"devDependencies"
:
{
"devDependencies"
:
{
"
@types/node
"
:
"
^20.10.4
"
,
"
@types/node
"
:
"
^20.10.4
"
,
"
@types/validator
"
:
"
^13.11.7
"
,
"
@types/validator
"
:
"
^13.11.7
"
,
"
@types/ws
"
:
"
^8.5.12
"
,
"
dotenv
"
:
"
^16.4.5
"
,
"
dotenv
"
:
"
^16.4.5
"
,
"
hardhat
"
:
"
^2.22.3
"
,
"
hardhat
"
:
"
^2.22.3
"
,
"
nodemon
"
:
"
^3.0.2
"
,
"
nodemon
"
:
"
^3.0.2
"
,
"
ts-node
"
:
"
^10.9.2
"
,
"
ts-node
"
:
"
^10.9.2
"
,
"
typescript
"
:
"
^5.3.2
"
"
typescript
"
:
"
^5.3.2
"
,
"
ws
"
:
"
^8.18.0
"
},
},
"dependencies"
:
{
"dependencies"
:
{
"
@chainlink/contracts
"
:
"
^0.8.0
"
,
"
@chainlink/contracts
"
:
"
^0.8.0
"
,
"
@libp2p/bootstrap
"
:
"
^10.1.0
"
,
"
@libp2p/identify
"
:
"
^2.1.2
"
,
"
@noir-lang/noir_js
"
:
"
^0.28.0
"
,
"
@noir-lang/noir_js
"
:
"
^0.28.0
"
,
"
@nomicfoundation/hardhat-toolbox
"
:
"
^5.0.0
"
,
"
@nomicfoundation/hardhat-toolbox
"
:
"
^5.0.0
"
,
"
@openzeppelin/contracts
"
:
"
^5.0.2
"
,
"
@openzeppelin/contracts
"
:
"
^5.0.2
"
,
"
@openzeppelin/contracts-upgradeable
"
:
"
^5.0.2
"
,
"
@openzeppelin/contracts-upgradeable
"
:
"
^5.0.2
"
,
"
@openzeppelin/hardhat-upgrades
"
:
"
^3.2.0
"
,
"
@openzeppelin/hardhat-upgrades
"
:
"
^3.2.0
"
,
"
@types/
pubsub-js
"
:
"
^1.8.6
"
,
"
@types/
express
"
:
"
^4.17.21
"
,
"
@uniswap/v3-periphery
"
:
"
^1.4.4
"
,
"
@uniswap/v3-periphery
"
:
"
^1.4.4
"
,
"
cors
"
:
"
^2.8.5
"
,
"
ethers
"
:
"
^6.13.0
"
,
"
ethers
"
:
"
^6.13.0
"
,
"
fonstr
"
:
"
^0.0.11
"
,
"
express
"
:
"
^4.19.2
"
,
"
indexeddbshim
"
:
"
^15.0.0
"
,
"
indexeddbshim
"
:
"
^15.0.0
"
,
"
memorelay
"
:
"
^2.0.4
"
,
"
reflect-metadata
"
:
"
^0.1.14
"
,
"
reflect-metadata
"
:
"
^0.1.14
"
,
"
sequelize
"
:
"
^6.35.1
"
,
"
sequelize
"
:
"
^6.35.1
"
,
"
sequelize-typescript
"
:
"
^2.1.6
"
"
sequelize-typescript
"
:
"
^2.1.6
"
...
...
This diff is collapsed.
Click to expand it.
src/index.ts
View file @
f813ab6b
...
@@ -2,6 +2,7 @@ import { Publisher } from "./modules/momiji";
...
@@ -2,6 +2,7 @@ import { Publisher } from "./modules/momiji";
import
*
as
types
from
"
../momiji-helpers/utils/types
"
;
import
*
as
types
from
"
../momiji-helpers/utils/types
"
;
import
{
ethers
}
from
"
ethers
"
;
import
{
ethers
}
from
"
ethers
"
;
import
'
dotenv/config
'
;
import
'
dotenv/config
'
;
import
{
WebSocketServer
}
from
"
ws
"
;
const
main
=
async
()
=>
{
const
main
=
async
()
=>
{
let
_globalConfig
:
types
.
GlobalConfig
=
{
let
_globalConfig
:
types
.
GlobalConfig
=
{
...
@@ -18,10 +19,50 @@ const main = async () => {
...
@@ -18,10 +19,50 @@ const main = async () => {
verbose
:
(
process
.
env
.
VERBOSE
)
?
(
process
.
env
.
VERBOSE
.
toLowerCase
()
===
"
true
"
)
:
false
,
verbose
:
(
process
.
env
.
VERBOSE
)
?
(
process
.
env
.
VERBOSE
.
toLowerCase
()
===
"
true
"
)
:
false
,
profit
:
(
process
.
env
.
PROFIT
)
?
parseInt
(
process
.
env
.
PROFIT
)
:
0
profit
:
(
process
.
env
.
PROFIT
)
?
parseInt
(
process
.
env
.
PROFIT
)
:
0
};
};
let
publisher
=
new
Publisher
(
_globalConfig
);
let
publisher
=
new
Publisher
(
_globalConfig
);
await
publisher
.
initializePublisher
();
await
publisher
.
initializePublisher
();
const
wss
=
new
WebSocketServer
({
host
:
'
0.0.0.0
'
,
port
:
5150
});
wss
.
on
(
'
connection
'
,
function
connection
(
ws
)
{
ws
.
on
(
'
error
'
,
console
.
error
);
ws
.
on
(
'
message
'
,
async
function
message
(
data
)
{
if
(
publisher
.
queue
.
length
>=
14
){
ws
.
send
(
'
{status:"error", msg:"Prover queue is full"}
'
)
return
}
const
valid
=
await
publisher
.
newTransactionReceivedMultiple
(
JSON
.
parse
(
data
.
toString
()));
if
(
valid
){
ws
.
send
(
'
{status:"ok", msg:"Proof added to queue"}
'
);
}
else
{
ws
.
send
(
'
{status:"error", msg:"Invalid proof"}
'
);
}
});
});
let
queuing
=
false
const
wenQueue
=
async
()
=>
{
if
(
!
queuing
&&
publisher
.
queue
.
length
>
0
)
{
queuing
=
true
;
await
publisher
.
proveMultiple
()
queuing
=
false
;
}
}
let
publishing
=
false
const
wenPublish
=
async
()
=>
{
if
(
!
publishing
&&
!
queuing
&&
publisher
.
batch
.
length
>
0
)
{
publishing
=
true
await
publisher
.
publishSingle
()
publishing
=
false
}
}
setInterval
(
wenQueue
,
1
e4
)
setInterval
(
wenPublish
,
1
e5
)
}
}
console
.
log
(
`💫 Starting publisher...`
)
console
.
log
(
`💫 Starting publisher...`
)
...
...
This diff is collapsed.
Click to expand it.
src/modules/momiji.ts
View file @
f813ab6b
...
@@ -4,19 +4,22 @@ import { keccak_tx } from '../../momiji-helpers/circuits/helpers/codegen/keccak_
...
@@ -4,19 +4,22 @@ import { keccak_tx } from '../../momiji-helpers/circuits/helpers/codegen/keccak_
import
{
tx_as_hash
}
from
'
../../momiji-helpers/circuits/helpers/codegen/tx_as_hash
'
;
import
{
tx_as_hash
}
from
'
../../momiji-helpers/circuits/helpers/codegen/tx_as_hash
'
;
export
class
Publisher
extends
BatchBuilder
{
export
class
Publisher
extends
BatchBuilder
{
private
publishTimeout
:
NodeJS
.
Timeout
;
//
private publishTimeout: NodeJS.Timeout;
private
signer
:
types
.
EthersSigner
|
undefined
;
private
signer
:
types
.
EthersSigner
|
undefined
;
private
mempool
:
types
.
Mempool
=
{};
private
mempool
:
types
.
Mempool
=
{};
private
provingQueue
:
Promise
<
types
.
RecursionInputs
[]
>
=
Promise
.
resolve
([]);
private
provingQueue
:
Promise
<
types
.
RecursionInputs
[]
>
=
Promise
.
resolve
([]);
p
rivate
batch
:
types
.
RecursionInputs
[]
=
[];
p
ublic
batch
:
types
.
RecursionInputs
[]
=
[];
private
confirmed
:
types
.
Confirmed
=
{};
private
confirmed
:
types
.
Confirmed
=
{};
private
publishing
:
boolean
=
false
;
private
publishing
:
boolean
=
false
;
private
proving
:
boolean
=
false
;
private
proving
:
boolean
=
false
;
private
sweeping
:
boolean
=
false
;
private
sweeping
:
boolean
=
false
;
public
queue
:
types
.
Transaction
[]
=
[];
public
accumulator
:
string
=
types
.
ZERO_VALUE
;
private
contractPublish
:
types
.
ContractPublish
=
{}
as
types
.
ContractPublish
;
constructor
(
config
:
types
.
GlobalConfig
)
{
constructor
(
config
:
types
.
GlobalConfig
)
{
super
(
config
);
super
(
config
);
this
.
publishTimeout
=
setInterval
(
this
.
publish
,
60
*
1000
);
//
this.publishTimeout = setInterval(this.publish, 60 * 1000);
this
.
mempool
=
{};
this
.
mempool
=
{};
this
.
confirmed
=
{};
this
.
confirmed
=
{};
}
}
...
@@ -60,12 +63,46 @@ export class Publisher extends BatchBuilder {
...
@@ -60,12 +63,46 @@ export class Publisher extends BatchBuilder {
}
}
let
txid
=
await
keccak_tx
(
tx
.
public_inputs
);
let
txid
=
await
keccak_tx
(
tx
.
public_inputs
);
let
_verified
=
await
this
.
addToMempool
(
tx
,
txid
)
let
_verified
=
await
this
.
addToMempool
(
tx
,
txid
)
if
(
_verified
)
this
.
queueToProve
(
tx
)
if
(
_verified
)
this
.
queueToProve
(
tx
)
else
console
.
log
(
`🔴 Transaction rejected -- failed to verify:
${
txid
}
`
);
else
console
.
log
(
`🔴 Transaction rejected -- failed to verify:
${
txid
}
`
);
}
}
async
newTransactionReceivedSingle
(
tx
:
types
.
Transaction
):
Promise
<
void
>
{
let
txid
=
await
keccak_tx
(
tx
.
public_inputs
);
let
_verified
=
await
this
.
addToMempool
(
tx
,
txid
)
if
(
_verified
)
{
await
this
.
proveSingle
(
tx
);
}
else
console
.
log
(
`🔴 Transaction rejected -- failed to verify:
${
txid
}
`
);
}
async
newTransactionReceivedMultiple
(
tx
:
types
.
Transaction
):
Promise
<
boolean
>
{
let
txid
=
await
keccak_tx
(
tx
.
public_inputs
);
let
_verified
=
await
this
.
addToMempool
(
tx
,
txid
)
if
(
_verified
)
{
this
.
queue
.
push
(
tx
)
return
true
}
else
{
console
.
log
(
`🔴 Transaction rejected -- failed to verify:
${
txid
}
`
);
return
false
};
}
async
proveMultiple
():
Promise
<
void
>
{
for
(
let
i
=
0
;
i
<
this
.
queue
.
length
;
i
++
)
{
if
(
this
.
batch
.
length
>=
15
)
{
console
.
log
(
`⚠️ Batch is full. Cannot prove additional transactions.`
)
this
.
queue
=
this
.
queue
.
slice
(
i
)
return
}
this
.
batch
=
await
this
.
proveSingle
(
this
.
queue
[
i
])
}
this
.
queue
=
[]
return
}
async
setupListeners
():
Promise
<
void
>
{
async
setupListeners
():
Promise
<
void
>
{
if
(
!
this
.
contracts
)
await
this
.
initializePublisher
();
if
(
!
this
.
contracts
)
await
this
.
initializePublisher
();
if
(
!
this
.
contracts
)
return
;
if
(
!
this
.
contracts
)
return
;
...
@@ -104,7 +141,8 @@ export class Publisher extends BatchBuilder {
...
@@ -104,7 +141,8 @@ export class Publisher extends BatchBuilder {
this
.
contracts
.
state
.
on
(
this
.
contracts
.
state
.
filters
.
BatchPublish
(
undefined
,
undefined
,
undefined
,
undefined
,
undefined
),
async
(
event
:
any
)
=>
{
this
.
contracts
.
state
.
on
(
this
.
contracts
.
state
.
filters
.
BatchPublish
(
undefined
,
undefined
,
undefined
,
undefined
,
undefined
),
async
(
event
:
any
)
=>
{
console
.
log
(
`🎯 Batch published:
${
event
}
.`
);
console
.
log
(
`🎯 Batch published:
${
event
}
.`
);
this
.
provingQueue
=
Promise
.
resolve
([]);
// this.provingQueue = Promise.resolve([]);
this
.
queue
=
[]
this
.
batch
=
[];
this
.
batch
=
[];
this
.
printRoot
();
this
.
printRoot
();
return
;
return
;
...
@@ -131,7 +169,7 @@ export class Publisher extends BatchBuilder {
...
@@ -131,7 +169,7 @@ export class Publisher extends BatchBuilder {
const
withdrawals
:
types
.
WithdrawalSwap
[]
=
await
this
.
_generateWithdrawals
([{
const
withdrawals
:
types
.
WithdrawalSwap
[]
=
await
this
.
_generateWithdrawals
([{
amount
:
(
new
types
.
NoirFr
(
withdrawalAmount
)).
toString
(),
amount
:
(
new
types
.
NoirFr
(
withdrawalAmount
)).
toString
(),
recipient
:
types
.
toFixedHex
(
1
,
true
),
recipient
:
types
.
toFixedHex
(
1
,
true
),
swap_percentage
:
100
swap_percentage
:
100
}],
1
)
}],
1
)
const
proverTx
:
types
.
Transaction
=
await
this
.
_generateTransactionProof
(
utxo_commitments
,
utxo_encrypted
,
withdrawals
);
const
proverTx
:
types
.
Transaction
=
await
this
.
_generateTransactionProof
(
utxo_commitments
,
utxo_encrypted
,
withdrawals
);
return
proverTx
;
return
proverTx
;
...
@@ -149,7 +187,13 @@ export class Publisher extends BatchBuilder {
...
@@ -149,7 +187,13 @@ export class Publisher extends BatchBuilder {
})
})
const
withdrawalAmount
:
bigint
=
utxo_commitments
.
map
(
utxo
=>
BigInt
(
utxo
.
amount
)).
reduce
((
prev
,
curr
)
=>
prev
+
curr
)
const
withdrawalAmount
:
bigint
=
utxo_commitments
.
map
(
utxo
=>
BigInt
(
utxo
.
amount
)).
reduce
((
prev
,
curr
)
=>
prev
+
curr
)
const
withdrawalAmountEther
:
bigint
=
await
this
.
_getEtherFromXFT
(
withdrawalAmount
)
const
withdrawalAmountEther
:
bigint
=
await
this
.
_getEtherFromXFT
(
withdrawalAmount
)
const
gasEstimate
:
bigint
=
await
this
.
contracts
.
state
.
publish
.
estimateGas
(
contractPublish
.
proof
,
contractPublish
.
batch
)
let
gasEstimate
:
bigint
try
{
gasEstimate
=
await
this
.
contracts
.
state
.
publish
.
estimateGas
(
contractPublish
.
proof
,
contractPublish
.
batch
)
}
catch
{
this
.
batch
.
pop
()
return
false
}
const
maxFeePerGas
:
bigint
=
await
this
.
config
.
provider
.
getFeeData
().
then
(
feeData
=>
feeData
.
maxFeePerGas
as
bigint
)
const
maxFeePerGas
:
bigint
=
await
this
.
config
.
provider
.
getFeeData
().
then
(
feeData
=>
feeData
.
maxFeePerGas
as
bigint
)
const
maxFeePerGasAdjusted
:
bigint
=
(
this
.
config
.
profit
)
?
maxFeePerGas
+
BigInt
(
this
.
config
.
profit
*
1
e9
)
:
maxFeePerGas
const
maxFeePerGasAdjusted
:
bigint
=
(
this
.
config
.
profit
)
?
maxFeePerGas
+
BigInt
(
this
.
config
.
profit
*
1
e9
)
:
maxFeePerGas
const
txFeeEstimate
:
bigint
=
gasEstimate
*
maxFeePerGasAdjusted
const
txFeeEstimate
:
bigint
=
gasEstimate
*
maxFeePerGasAdjusted
...
@@ -189,6 +233,15 @@ export class Publisher extends BatchBuilder {
...
@@ -189,6 +233,15 @@ export class Publisher extends BatchBuilder {
})
})
}
}
async
proveSingle
(
tx
:
types
.
Transaction
):
Promise
<
types
.
RecursionInputs
[]
>
{
this
.
proving
=
true
;
console
.
log
(
`⏳ Proving
${
await
keccak_tx
(
tx
.
public_inputs
)}
.`
)
const
proof
=
await
this
.
rollupTransaction
(
this
.
batch
,
tx
);
console
.
log
(
`✔️ Proved
${
await
keccak_tx
(
tx
.
public_inputs
)}
.`
)
this
.
proving
=
false
return
proof
}
publish
=
async
()
=>
{
publish
=
async
()
=>
{
if
(
this
.
publishing
)
return
;
if
(
this
.
publishing
)
return
;
...
@@ -196,10 +249,9 @@ export class Publisher extends BatchBuilder {
...
@@ -196,10 +249,9 @@ export class Publisher extends BatchBuilder {
if
(
this
.
sweeping
)
return
;
if
(
this
.
sweeping
)
return
;
if
(
this
.
batch
.
length
===
0
)
return
;
if
(
this
.
batch
.
length
===
0
)
return
;
await
this
.
provingQueue
;
// await this.provingQueue;
const
contractPublish
:
types
.
ContractPublish
=
await
this
.
preparePublish
(
this
.
batch
)
// const contractPublish: types.ContractPublish = await this.preparePublish(this.batch)
// if (!(await this.publishReady(this.batch, contractPublish))) return;
if
(
!
(
await
this
.
publishReady
(
this
.
batch
,
contractPublish
)))
return
;
console
.
log
(
`🧹 Sweeping prover fees...`
)
console
.
log
(
`🧹 Sweeping prover fees...`
)
this
.
sweeping
=
true
this
.
sweeping
=
true
...
@@ -213,7 +265,7 @@ export class Publisher extends BatchBuilder {
...
@@ -213,7 +265,7 @@ export class Publisher extends BatchBuilder {
console
.
log
(
`🗞️ Publishing batch...`
)
console
.
log
(
`🗞️ Publishing batch...`
)
const
contractPublishProver
:
types
.
ContractPublish
=
await
this
.
preparePublish
(
this
.
batch
)
const
contractPublishProver
:
types
.
ContractPublish
=
await
this
.
preparePublish
(
this
.
batch
)
clearInterval
(
this
.
publishTimeout
);
//
clearInterval(this.publishTimeout);
await
this
.
contracts
.
state
.
publish
(
contractPublishProver
.
proof
,
contractPublishProver
.
batch
)
await
this
.
contracts
.
state
.
publish
(
contractPublishProver
.
proof
,
contractPublishProver
.
batch
)
.
then
((
tx
:
any
)
=>
console
.
log
(
`📡 Batch published:
${
tx
.
hash
}
.`
),
(
error
:
any
)
=>
console
.
log
(
error
.
message
));
.
then
((
tx
:
any
)
=>
console
.
log
(
`📡 Batch published:
${
tx
.
hash
}
.`
),
(
error
:
any
)
=>
console
.
log
(
error
.
message
));
...
@@ -221,7 +273,48 @@ export class Publisher extends BatchBuilder {
...
@@ -221,7 +273,48 @@ export class Publisher extends BatchBuilder {
this
.
provingQueue
=
Promise
.
resolve
([]);
this
.
provingQueue
=
Promise
.
resolve
([]);
this
.
batch
=
[];
this
.
batch
=
[];
this
.
publishTimeout
=
setInterval
(
this
.
publish
,
60
*
1000
);
// this.publishTimeout = setInterval(this.publish, 60 * 1000);
this
.
publishing
=
false
;
return
;
}
async
publishSingle
()
{
if
(
this
.
publishing
)
return
;
if
(
this
.
proving
)
return
;
if
(
this
.
batch
.
length
===
0
)
return
;
// If the accumulator has changed since the last pass
// ie. a new transaction has been added to the batch
if
(
this
.
accumulator
!==
this
.
batch
[
this
.
batch
.
length
-
1
].
accumulator
)
{
console
.
log
(
`📝 Preparing batch publish`
)
this
.
proving
=
true
this
.
contractPublish
=
await
this
.
preparePublish
(
this
.
batch
)
this
.
accumulator
=
this
.
batch
[
this
.
batch
.
length
-
1
].
accumulator
this
.
proving
=
false
return
;
}
if
(
!
(
await
this
.
publishReady
(
this
.
batch
,
this
.
contractPublish
)))
return
;
this
.
publishing
=
true
console
.
log
(
`🧹 Sweeping prover fees...`
)
const
transactions
:
types
.
Transaction
[]
=
this
.
batch
.
filter
(
tx
=>
tx
.
transaction
!==
undefined
).
map
(
tx
=>
tx
.
transaction
as
types
.
Transaction
)
const
proverTx
:
types
.
Transaction
=
await
this
.
sweepProfit
(
transactions
)
const
proverBatch
:
types
.
RecursionInputs
[]
=
await
this
.
proveSingle
(
proverTx
)
const
contractPublishProver
:
types
.
ContractPublish
=
await
this
.
preparePublish
(
proverBatch
)
console
.
log
(
`🗞️ Publishing batch...`
)
await
this
.
contracts
.
state
.
publish
(
contractPublishProver
.
proof
,
contractPublishProver
.
batch
)
.
then
((
tx
:
any
)
=>
console
.
log
(
`📡 Batch published:
${
tx
.
hash
}
.`
),
(
error
:
any
)
=>
console
.
log
(
error
.
message
));
this
.
queue
=
[];
this
.
batch
=
[];
this
.
accumulator
=
types
.
ZERO_VALUE
;
this
.
contractPublish
=
{}
as
types
.
ContractPublish
if
(
Object
.
keys
(
this
.
mempool
).
length
>=
1000
)
this
.
mempool
=
{}
if
(
Object
.
keys
(
this
.
confirmed
).
length
>=
1000
)
this
.
confirmed
=
{}
this
.
publishing
=
false
;
this
.
publishing
=
false
;
return
;
return
;
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment