mirror of
https://github.com/logos-blockchain/logos-blockchain-pocs.git
synced 2026-05-01 23:23:12 +00:00
Addvances in the verifier script of 09/24/24
This commit is contained in:
parent
788a57a6e7
commit
0635a277d7
@ -28,7 +28,6 @@ thiserror.workspace = true
|
||||
tracing.workspace = true
|
||||
rayon = { version = "1.10.0", optional = true }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
light-poseidon = {path = "../../../../../save/rust/snarks/light-poseidon/light-poseidon"}
|
||||
crypto-bigint = "0.5.5"
|
||||
ark-serialize = "0.4.0"
|
||||
serde_json = "1.0.116"
|
||||
|
||||
@ -118,7 +118,7 @@ pub fn verify<MC: MerkleChannel>(
|
||||
let composition_oods_eval = extract_composition_eval(sampled_oods_values).map_err(|_| {
|
||||
VerificationError::InvalidStructure("Unexpected sampled_values structure".to_string())
|
||||
})?;
|
||||
|
||||
println!("composition_oods_eval = {:?}",composition_oods_eval);
|
||||
if composition_oods_eval
|
||||
// Compute
|
||||
!= components.eval_composition_polynomial_at_point(
|
||||
|
||||
@ -400,6 +400,7 @@ mod tests {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::core::vcs::poseidon_bls_merkle::PoseidonBLSMerkleChannel;
|
||||
use crate::core::ColumnVec;
|
||||
use crate::core::fields::qm31::QM31;
|
||||
use crate::examples::wide_fibonacci::{generate_trace, FibInput, WideFibonacciComponent};
|
||||
|
||||
const FIB_SEQUENCE_LENGTH: usize = 100;
|
||||
@ -604,6 +605,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
_ = pretty_save_poseidon_bls_proof(&proof);
|
||||
println!(" 0 1 0 0 = {:?}",QM31::from_u32_unchecked(0,1,0,0));
|
||||
|
||||
// Verify.
|
||||
let verifier_channel = &mut PoseidonBLSChannel::default();
|
||||
|
||||
@ -174,7 +174,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 128,
|
||||
"id": "67a09953",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@ -195,7 +195,33 @@
|
||||
" remainder = cur % shift\n",
|
||||
" cur = quotient\n",
|
||||
" u32s.append(M31(remainder))\n",
|
||||
" return u32s"
|
||||
" return u32s\n",
|
||||
"\n",
|
||||
"def draw_random_bytes(digest, n_sent):\n",
|
||||
" shift = 1 << 8\n",
|
||||
" cur = int(draw_felt252(digest, n_sent))\n",
|
||||
" byte = []\n",
|
||||
" for i in range(31):\n",
|
||||
" quotient = cur // shift\n",
|
||||
" remainder = cur % shift\n",
|
||||
" cur = quotient\n",
|
||||
" byte.append(remainder)\n",
|
||||
" return byte\n",
|
||||
"\n",
|
||||
"def hash_node(has_children, left, right, column_values):\n",
|
||||
" n_column_blocks = ceil(len(column_values) / 8.0);\n",
|
||||
" values = []\n",
|
||||
" if has_children:\n",
|
||||
" values.append(left)\n",
|
||||
" values.append(right)\n",
|
||||
" padding_length = 8 * n_column_blocks - len(column_values)\n",
|
||||
" padded_values = column_values + [F(0) for i in range(padding_length)]\n",
|
||||
" for i in range(int(len(padded_values) / 8)):\n",
|
||||
" word = F(0)\n",
|
||||
" for j in range(8):\n",
|
||||
" word = word * F(2**31) + F(padded_values[i*8+j])\n",
|
||||
" values.append(word)\n",
|
||||
" return poseidon_hash_many_bls(values)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -296,7 +322,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"execution_count": 312,
|
||||
"id": "d9371b02",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@ -326,83 +352,169 @@
|
||||
"point = oods_point\n",
|
||||
"mask_values = proof[\"sampled_values_0\"] + proof[\"sampled_values_1\"]\n",
|
||||
"\n",
|
||||
"accumulator = random_coeff\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Evaluate random point on the vanishing polynomial of the coset\n",
|
||||
"evaluation = point.x\n",
|
||||
"for i in range(5):\n",
|
||||
" evaluation = CirclePoint.double_x(evaluation)\n",
|
||||
"evaluation_inverse = evaluation ** (-1)"
|
||||
"evaluation_inverse = evaluation ** (-1)\n",
|
||||
"\n",
|
||||
"# Compute evaluation using the mask values\n",
|
||||
"accumulator = QM31(0)\n",
|
||||
"a = QM31([mask_values[0][:2],mask_values[0][2:4]])\n",
|
||||
"b = QM31([mask_values[1][:2],mask_values[1][2:4]])\n",
|
||||
"for i in range(len(proof[\"sampled_values_0\"])-2):\n",
|
||||
" c = QM31([mask_values[2+i][:2],mask_values[2+i][2:4]])\n",
|
||||
" accumulator = (c - (a**2 + b**2))*evaluation_inverse + accumulator * random_coeff\n",
|
||||
" a = b\n",
|
||||
" b = c\n",
|
||||
"\n",
|
||||
"expected_value = QM31([proof[\"sampled_values_1\"][0][:2],proof[\"sampled_values_1\"][0][2:4]]) + QM31([proof[\"sampled_values_1\"][1][:2],proof[\"sampled_values_1\"][1][2:4]]) * QM31([[0,1],[0,0]]) + QM31([proof[\"sampled_values_1\"][2][:2],proof[\"sampled_values_1\"][2][2:4]]) * QM31([[0,0],[1,0]]) + QM31([proof[\"sampled_values_1\"][3][:2],proof[\"sampled_values_1\"][3][2:4]]) * QM31([[0,0],[0,1]])\n",
|
||||
"\n",
|
||||
"assert(expected_value == accumulator)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"####FRI part\n",
|
||||
"# Fiat-Shamir\n",
|
||||
"shift = F(1 << 31)\n",
|
||||
"res = [digest]\n",
|
||||
"for i in range(len(mask_values) / 2):\n",
|
||||
" cur = F(0)\n",
|
||||
" for j in range(2):\n",
|
||||
" for k in range(4):\n",
|
||||
" cur = cur * shift + F(mask_values[2*i+j][k])\n",
|
||||
" res.append(cur)\n",
|
||||
"digest = poseidon_hash_many_bls(res)\n",
|
||||
"random_coeff = QM31([draw_base_felts(digest,0)[:2],draw_base_felts(digest,0)[2:4]])\n",
|
||||
"\n",
|
||||
"# Verify commitment stage\n",
|
||||
"circle_poly_alpha = QM31([draw_base_felts(digest,1)[:2],draw_base_felts(digest,1)[2:4]])\n",
|
||||
"folding_alpha = []\n",
|
||||
"for i in range(6):\n",
|
||||
" digest = poseidon_hash_bls(digest,proof[\"inner_commitment_\"+str(i)])\n",
|
||||
" folding_alpha.append(QM31([draw_base_felts(digest,0)[:2],draw_base_felts(digest,0)[2:4]]))\n",
|
||||
"last_layer_poly = QM31([proof[\"coeffs\"][:2],proof[\"coeffs\"][2:4]])\n",
|
||||
"\n",
|
||||
"#Check proof of work\n",
|
||||
"res = [digest]\n",
|
||||
"cur = F(0)\n",
|
||||
"for i in range(4):\n",
|
||||
" cur = cur * shift + F(proof[\"coeffs\"][i])\n",
|
||||
"res.append(cur)\n",
|
||||
"digest = poseidon_hash_many_bls(res)\n",
|
||||
"digest = poseidon_hash_bls(digest, proof[\"proof of work\"])\n",
|
||||
"# The first 5 bits following the first 1 must be 0 for proof of work\n",
|
||||
"for i in range(5):\n",
|
||||
" assert(bin(digest)[3+i] == '0')\n",
|
||||
"\n",
|
||||
"# Compute openings positions\n",
|
||||
"querries = []\n",
|
||||
"max_querry = (1<<8)-1\n",
|
||||
"random_bytes = draw_random_bytes(digest,0)\n",
|
||||
"# The number of required querries is 3 so we need 3*8 bytes wich is enough with the 31 bytes of random_bytes\n",
|
||||
"for i in range(3):\n",
|
||||
" querry_bits = int().from_bytes(random_bytes[i*4:i*4+4],byteorder=\"little\")\n",
|
||||
" querries.append(querry_bits & max_querry)\n",
|
||||
"positions = []\n",
|
||||
"# For each collumn\n",
|
||||
"for i in range(2):\n",
|
||||
" # For each querry\n",
|
||||
" for j in range(3):\n",
|
||||
" positions.append(querries[j] >> (1+i))\n",
|
||||
"positions_sav = positions.copy()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#Verify decommitments (this part must be simplified repeting duplicated inputs)\n",
|
||||
"# First tree\n",
|
||||
"nodes = {}\n",
|
||||
"for i in range(6):\n",
|
||||
" leaf = []\n",
|
||||
" for j in range(100):\n",
|
||||
" leaf.append(M31(proof[\"queried_values_0\"][j][i]))\n",
|
||||
" nodes[\"level_0_node_\"+str(positions[i//2] // 2 * 2 + i % 2) ] = hash_node(false,0,0,leaf)\n",
|
||||
"counter = 0\n",
|
||||
"for level in range(7):\n",
|
||||
" for i in range(3):\n",
|
||||
" if \"level_\"+str(level)+\"_node_\"+str(positions[len(positions)-3] * 2) in nodes:\n",
|
||||
" lhs = nodes[\"level_\"+str(level)+\"_node_\"+str(positions[len(positions)-3] * 2)]\n",
|
||||
" else:\n",
|
||||
" lhs = F(proof[\"decommitment_0\"][counter])\n",
|
||||
" counter += 1\n",
|
||||
" if \"level_\"+str(level)+\"_node_\"+str(positions[len(positions) - 3] * 2 + 1) in nodes:\n",
|
||||
" rhs = nodes[\"level_\"+str(level)+\"_node_\"+str(positions[len(positions) - 3] * 2 + 1)]\n",
|
||||
" else:\n",
|
||||
" rhs = F(proof[\"decommitment_0\"][counter])\n",
|
||||
" counter += 1\n",
|
||||
" nodes[\"level_\"+str(level+1)+\"_node_\"+str(positions[len(positions)-3])] = hash_node(true,lhs,rhs,[])\n",
|
||||
" positions.append(positions[len(positions)-3] // 2)\n",
|
||||
"assert(nodes[\"level_7_node_0\"] == F(proof[\"commitments\"][0]))\n",
|
||||
"\n",
|
||||
"#Second tree\n",
|
||||
"positions = positions_sav\n",
|
||||
"for i in range(len(positions)):\n",
|
||||
" positions[i] = positions[i] * 2\n",
|
||||
"nodes = {}\n",
|
||||
"for i in range(6):\n",
|
||||
" leaf = []\n",
|
||||
" for j in range(4):\n",
|
||||
" leaf.append(M31(proof[\"queried_values_1\"][j][i]))\n",
|
||||
" nodes[\"level_0_node_\"+str(positions[i//2] // 2 * 2 + i % 2) ] = hash_node(false,0,0,leaf)\n",
|
||||
"counter = 0\n",
|
||||
"for level in range(8):\n",
|
||||
" for i in range(3):\n",
|
||||
" if \"level_\"+str(level)+\"_node_\"+str(positions[len(positions)-3] * 2) in nodes:\n",
|
||||
" lhs = nodes[\"level_\"+str(level)+\"_node_\"+str(positions[len(positions)-3] * 2)]\n",
|
||||
" else:\n",
|
||||
" lhs = F(proof[\"decommitment_1\"][counter])\n",
|
||||
" counter += 1\n",
|
||||
" if \"level_\"+str(level)+\"_node_\"+str(positions[len(positions) - 3] * 2 + 1) in nodes:\n",
|
||||
" rhs = nodes[\"level_\"+str(level)+\"_node_\"+str(positions[len(positions) - 3] * 2 + 1)]\n",
|
||||
" else:\n",
|
||||
" rhs = F(proof[\"decommitment_1\"][counter])\n",
|
||||
" counter += 1\n",
|
||||
" nodes[\"level_\"+str(level+1)+\"_node_\"+str(positions[len(positions)-3])] = hash_node(true,lhs,rhs,[])\n",
|
||||
" if level == 0:\n",
|
||||
" nodes[\"level_1_node_\"+str(positions[len(positions)-3] + 1)] = hash_node(true,nodes[\"level_0_node_\"+str((positions[len(positions)-3] + 1)* 2)],nodes[\"level_0_node_\"+str((positions[len(positions)-3] + 1)* 2 + 1)],[])\n",
|
||||
" positions.append(positions[len(positions)-3] // 2)\n",
|
||||
"assert(nodes[\"level_8_node_0\"] == F(proof[\"commitments\"][1]))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Check querries answer\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "3adb682e",
|
||||
"id": "56e4c016",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"id": "59b44767",
|
||||
"execution_count": null,
|
||||
"id": "6b89599c",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(1001989877*i + 1100649138)*u + 462165474*i + 673026348"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"evaluation_inverse"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"id": "7790a0f9",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "AttributeError",
|
||||
"evalue": "'PolynomialQuotientRing_field_with_category.element_class' object has no attribute 'double'",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)",
|
||||
"\u001b[1;32m/tmp/ipykernel_10017/940279797.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0ma\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mQM31\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mInteger\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mInteger\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mb\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mQM31\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mInteger\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2129160320\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1109509513\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mInteger\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m787887008\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1676461964\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0ma\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdouble\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdouble\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
|
||||
"\u001b[1;32m/usr/lib/python3/dist-packages/sage/structure/element.pyx\u001b[0m in \u001b[0;36msage.structure.element.Element.__getattr__ (build/cythonized/sage/structure/element.c:4827)\u001b[1;34m()\u001b[0m\n\u001b[0;32m 492\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;34m'LeftZeroSemigroup_with_category.element_class'\u001b[0m \u001b[0mobject\u001b[0m \u001b[0mhas\u001b[0m \u001b[0mno\u001b[0m \u001b[0mattribute\u001b[0m \u001b[1;34m'blah_blah'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 493\u001b[0m \"\"\"\n\u001b[1;32m--> 494\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetattr_from_category\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mname\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 495\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 496\u001b[0m \u001b[0mcdef\u001b[0m \u001b[0mgetattr_from_category\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mname\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[1;32m/usr/lib/python3/dist-packages/sage/structure/element.pyx\u001b[0m in \u001b[0;36msage.structure.element.Element.getattr_from_category (build/cythonized/sage/structure/element.c:4939)\u001b[1;34m()\u001b[0m\n\u001b[0;32m 505\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 506\u001b[0m \u001b[0mcls\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mP\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_abstract_element_class\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 507\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mgetattr_from_other_class\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcls\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mname\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 508\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 509\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__dir__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[1;32m/usr/lib/python3/dist-packages/sage/cpython/getattr.pyx\u001b[0m in \u001b[0;36msage.cpython.getattr.getattr_from_other_class (build/cythonized/sage/cpython/getattr.c:2636)\u001b[1;34m()\u001b[0m\n\u001b[0;32m 354\u001b[0m \u001b[0mdummy_error_message\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcls\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 355\u001b[0m \u001b[0mdummy_error_message\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mname\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mname\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 356\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdummy_error_message\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 357\u001b[0m \u001b[0mcdef\u001b[0m \u001b[0mPyObject\u001b[0m\u001b[1;33m*\u001b[0m \u001b[0mattr\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0minstance_getattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mname\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 358\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mattr\u001b[0m \u001b[1;32mis\u001b[0m \u001b[0mNULL\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[1;31mAttributeError\u001b[0m: 'PolynomialQuotientRing_field_with_category.element_class' object has no attribute 'double'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"a = QM31([[1,0],[0,0]])\n",
|
||||
"b = QM31([[2129160320,1109509513],[787887008,1676461964]])\n",
|
||||
"a.double() + b.double()\n"
|
||||
]
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "5f95a975",
|
||||
"id": "e486cb3a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"[[\"1\",\"0\",\"0\",\"0\"],\n",
|
||||
"\t\t[\"2129160320\",\"1109509513\",\"787887008\",\"1676461964\"],\n",
|
||||
"\t\t[\"262908602\",\"915488457\",\"1893945291\",\"1774327476\"]"
|
||||
]
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "85dd52b3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
Loading…
x
Reference in New Issue
Block a user