Skip to content

Instantly share code, notes, and snippets.

@namnc
Created March 24, 2024 01:55
Show Gist options
  • Save namnc/1351994aacb25054ee4696c52ad0802e to your computer and use it in GitHub Desktop.
Save namnc/1351994aacb25054ee4696c52ad0802e to your computer and use it in GitHub Desktop.
Fun proj during EthTaipei 2024 for linking circom-2-arithc and MP-SPDZ
import json
f = open('circ.json')
# f = open('nn_circuit_small.json')
data = json.load(f)
class AGate:
def __init__(self, id, type, lhs, rhs, out):
self.id = id
self.type = type
self.lhs = lhs
self.rhs = rhs
self.out = out
class ANode:
def __init__(self, id, signals, names, is_const, const_value):
self.id = id
self.signals = signals
self.names = names
self.is_const = is_const
self.const_value = const_value
anodes = {}
anode_consts = {}
anode_inputs = {}
anode_outputs = {}
for node in data['nodes']:
node_id = node['id']
node_signals = node['signals']
node_names = node['names']
node_is_const = node['is_const']
node_const_value = node['const_value']
anode = ANode(node_id, node_signals, node_names, node_is_const, node_const_value)
anodes[node_id] = anode
for node_name in node_names:
if "0." in node_name:
anode_inputs[node_id] = node_name[2:]
anode_outputs[node_id] = node_name[2:]
if node_is_const:
anode_consts[node_id] = node_const_value
agates = {}
for gate in data['gates']:
gate_id = gate['id']
gate_type = gate['gate_type']
glh_input = gate['lh_input']
grh_input = gate['rh_input']
goutput = gate['output']
agate = AGate(gate_id, gate_type, glh_input, grh_input, goutput)
agates[gate_id] = agate
for gid in agates:
gate = agates[gid]
lhs = gate.lhs
rhs = gate.rhs
out = gate.out
anode_outputs.pop(lhs, None)
anode_outputs.pop(rhs, None)
anode_inputs.pop(out, None)
if anode_consts.get(lhs) is not None:
lhs = "("+str(anode_consts[lhs])+")"
if anode_consts.get(rhs) is not None:
rhs = "("+str(anode_consts[rhs])+")"
# if gate.type == 'AAdd':
# print(""+str(out)+" = "+str(lhs)+" + "+str(rhs))
# elif gate.type == 'ASub':
# print(""+str(out)+" = "+str(lhs)+" - "+str(rhs))
# elif gate.type == 'AMul':
# print(""+str(out)+" = "+str(lhs)+" * "+str(rhs))
# elif gate.type == 'ALt':
# print(""+str(out)+" = "+str(lhs)+" < "+str(rhs))
# print(anode_inputs)
# print(anode_outputs)
f.close()
class TNode:
def __init__(self, rid, type, lnode, rnode):
self.iid = 0
self.rid = rid
self.lnode = lnode
self.rnode = rnode
self.type = type
self.is_root = True
self.is_leaf = True
self.is_visited = False
def visit_dfs(self, id):
if self.is_visited:
return id
self.is_visited = True
if self.lnode is not None:
id = self.lnode.visit_dfs(id)
if self.rnode is not None:
id = self.rnode.visit_dfs(id)
self.iid = id
return id+1
def visit_root(self):
if self.is_visited:
return
self.is_visited = True
id = 0
print(id)
id = self.lnode.visit_dfs(id)
id = self.rnode.visit_dfs(id)
self.iid = id
print(id)
def fill_iid_dfs2(self, id):
if self.is_visited:
return id
self.is_visited = True
if (self.lnode is None) and (self.rnode is None):
return id
if self.lnode is not None:
id = self.lnode.fill_iid_dfs2(id)
if self.rnode is not None:
id = self.rnode.fill_iid_dfs2(id)
self.iid = id
return id + 1
def visit_dfs2(self, id):
if self.is_visited:
return id
self.is_visited = True
if self.lnode is not None:
id = self.lnode.visit_dfs2(id)
if self.rnode is not None:
id = self.rnode.visit_dfs2(id)
if (self.lnode is None) and (self.rnode is None):
self.iid = id
return id + 1
return id
def visit_root2(self, tt):
if self.is_visited:
return id
self.is_visited = True
id = 0
print(id)
id = self.lnode.visit_dfs2(id)
id = self.rnode.visit_dfs2(id)
tt.reset_visit()
id = self.fill_iid_dfs2(id)
print(id)
return id
def print_dfs(self, f):
if self.is_visited:
return
self.is_visited = True
if self.lnode is not None:
id = self.lnode.print_dfs(f)
if self.rnode is not None:
id = self.rnode.print_dfs(f)
if (self.lnode is None) & (self.rnode is None):
return
f.write("2 1 " + str(self.lnode.iid) + " " + str(self.rnode.iid) + " " + str(self.iid) + " " + str(self.type) + "\n")
def print_root(self, f):
if self.is_visited:
return
self.is_visited = True
self.lnode.print_dfs(f)
self.rnode.print_dfs(f)
f.write("2 1 " + str(self.lnode.iid) + " " + str(self.rnode.iid) + " " + str(self.iid) + " " + str(self.type) + "\n")
class TTree:
def __init__(self):
self.roots = None
self.tnodes = {}
self.leaves = {}
self.gcount = 0
self.wcount = 0
def insert_node(self, gate):
gid = gate.id
gtype = gate.type
gout = gate.out
glhs = gate.lhs
grhs = gate.rhs
tnode = TNode(gout, gtype, None, None)
self.tnodes[gout] = tnode
if (self.tnodes.get(glhs) is None):
lnode = TNode(glhs, None, None, None)
self.tnodes[glhs] = lnode
if (self.tnodes.get(grhs) is None):
rnode = TNode(grhs, None, None, None)
self.tnodes[grhs] = rnode
def reset_visit(self):
for nid in self.tnodes:
tnode = self.tnodes[nid]
tnode.is_visited = False
def build_tree(self, gates):
for gid in gates:
gate = gates[gid]
self.insert_node(gate)
for gid in gates:
gate = gates[gid]
gout = gate.out
tnode = self.tnodes[gout]
glhs = gate.lhs
grhs = gate.rhs
lnode = self.tnodes[glhs]
rnode = self.tnodes[grhs]
lnode.is_root = False
rnode.is_root = False
tnode.is_leaf = False
tnode.lnode = lnode
tnode.rnode = rnode
self.gcount += 1
for tnid in self.tnodes:
tnode = self.tnodes[tnid]
if tnode.is_root:
self.roots = tnode
elif tnode.is_leaf:
self.leaves[tnode.rid] = tnode
self.wcount = self.roots.visit_root2(self)
def print_tree(self, f):
self.roots.print_root(f)
def leaves_ordered(self):
ls = {}
for lid in self.leaves:
leaf = self.leaves[lid]
ls[leaf.iid] = leaf
return ls
tt = TTree()
tt.build_tree(agates)
f = open("circ.txt", "w")
f.write(str(tt.gcount))
f.write(" ")
f.write(str((tt.wcount)))
f.write("\n")
f.write(str(len(tt.leaves)))
f.write(" ")
for i in range(0, len(tt.leaves)):
f.write("1 ")
f.write("\n")
f.write("1")
f.write(" ")
for i in range(0, 1):
f.write("1 ")
f.write("\n")
f.write("\n")
tt.reset_visit()
tt.print_tree(f)
# ls = tt.leaves_ordered()
f.close()
# f = open("circ.conf", "w")
# for lid in ls:
# leaf = ls[lid]
# f.write(str(lid) + " " + anode_inputs[leaf.rid] + "\n")
# f.close()
# from ast import literal_eval
# fi = open('inputs.json')
# datai = json.load(fi)
# mapi = {}
# for aid in anode_inputs:
# aname = anode_inputs.get(aid)
# sep = aname.find("[")
# access = "datai['"+aname[:sep]+"']"+aname[sep:]
# mapi[aname] = eval(access)
# for aid in anode_outputs:
# aname = anode_outputs.get(aid)
# sep = aname.find("[")
# access = "datai['"+aname[:sep]+"']"+aname[sep:]
# mapi[aname] = eval(access)
# print(mapi)
# # Closing file
# fi.close()
{
"vars": {
"2274727901": null,
"256027254": null,
"707860729": null,
"2573828220": null,
"0": 0,
"10": 10,
"3418096790": null,
"1716273923": null,
"950363519": null,
"3408241754": null,
"11305347": null,
"2871116428": null,
"4076123877": null,
"3251828585": null,
"2151764623": null,
"3686905244": null,
"1127324556": null,
"140409081": null,
"782492029": null,
"1206250264": null,
"2539431855": null,
"482585862": null
},
"nodes": [
{
"id": 3398201401,
"signals": [
10
],
"names": [
"CALL_DeScale.isf"
],
"is_const": true,
"const_value": 10
},
{
"id": 570082499,
"signals": [
1716273923,
2573828220
],
"names": [
"0.in",
"CALL_DeScale.in"
],
"is_const": false,
"const_value": 0
},
{
"id": 318995186,
"signals": [
707860729
],
"names": [
"CALL_Switcher.random_4281045258"
],
"is_const": false,
"const_value": 0
},
{
"id": 4060015081,
"signals": [
11305347,
3418096790
],
"names": [
"CALL_Switcher.random_2102410497",
"CALL_Switcher.aux"
],
"is_const": false,
"const_value": 0
},
{
"id": 1867749162,
"signals": [
2871116428,
482585862
],
"names": [
"CALL_Switcher.random_3986217929",
"CALL_Switcher.outL"
],
"is_const": false,
"const_value": 0
},
{
"id": 2902071736,
"signals": [
4076123877,
3251828585
],
"names": [
"CALL_Switcher.random_2117015335",
"CALL_Switcher.outR"
],
"is_const": false,
"const_value": 0
},
{
"id": 995677393,
"signals": [
1206250264,
2539431855,
3686905244
],
"names": [
"CALL_Sign.random_238866503",
"CALL_Sign.sign",
"CALL_Switcher.sel"
],
"is_const": false,
"const_value": 0
},
{
"id": 2732172177,
"signals": [
2274727901,
950363519,
782492029,
1127324556
],
"names": [
"CALL_DeScale.random_4088491867",
"CALL_DeScale.out",
"CALL_Sign.in",
"CALL_Switcher.L"
],
"is_const": false,
"const_value": 0
},
{
"id": 116951668,
"signals": [
0,
3408241754
],
"names": [
"CALL_Sign.random_126383539",
"CALL_Switcher.R"
],
"is_const": true,
"const_value": 0
},
{
"id": 946705336,
"signals": [
140409081
],
"names": [
"0.random_4263890812"
],
"is_const": false,
"const_value": 0
},
{
"id": 2111524539,
"signals": [
256027254,
2151764623
],
"names": [
"0.random_4024064508",
"0.out"
],
"is_const": false,
"const_value": 0
}
],
"gates": [
{
"id": 0,
"gate_type": "AMul",
"lh_input": 570082499,
"rh_input": 3398201401,
"output": 2732172177
},
{
"id": 1,
"gate_type": "ALt",
"lh_input": 2732172177,
"rh_input": 116951668,
"output": 995677393
},
{
"id": 2,
"gate_type": "ASub",
"lh_input": 116951668,
"rh_input": 2732172177,
"output": 318995186
},
{
"id": 3,
"gate_type": "AMul",
"lh_input": 318995186,
"rh_input": 995677393,
"output": 4060015081
},
{
"id": 4,
"gate_type": "AAdd",
"lh_input": 4060015081,
"rh_input": 2732172177,
"output": 1867749162
},
{
"id": 5,
"gate_type": "ASub",
"lh_input": 116951668,
"rh_input": 4060015081,
"output": 2902071736
},
{
"id": 6,
"gate_type": "AAdd",
"lh_input": 2902071736,
"rh_input": 116951668,
"output": 946705336
},
{
"id": 7,
"gate_type": "AAdd",
"lh_input": 1867749162,
"rh_input": 946705336,
"output": 2111524539
}
]
}
8 11
3 1 1 1
1 1
2 1 1 2 3 AMul
2 1 0 3 4 ASub
2 1 3 0 5 ALt
2 1 4 5 6 AMul
2 1 6 3 7 AAdd
2 1 0 6 8 ASub
2 1 8 0 9 AAdd
2 1 7 9 10 AAdd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment