fix: send tx with 2 seeds

This commit is contained in:
Anh Minh 2025-10-15 08:00:31 +07:00
parent 0cc226c52a
commit 552a9e9d9b
2 changed files with 171 additions and 24 deletions

View File

@ -17,6 +17,7 @@ var (
PublicKeyStart = []byte{234, 230, 92}
MagicDyckForPoint = []uint64{0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1}
MagicDyckForT8 = []uint64{0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}
MagicDyckForSeed = []uint64{0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}
Tip5Zero = [5]uint64{1730770831742798981, 2676322185709933211, 8329210750824781744, 16756092452590401876, 3547445316740171466}
Tip5One = [5]uint64{6727110957294540849, 15606243244732609007, 11887284596344881785, 10646863421881571398, 8146872807338919620}
Tip5ZeroZero = [5]uint64{4372149332062030091, 17876920912185183887, 13348798570422431948, 8872865212694716527, 3385176510443841516}

View File

@ -174,6 +174,29 @@ func HashSeed(seed *nockchain.NockchainSeed) ([5]uint64, error) {
return crypto.Tip5RehashTenCell(sourceHash, seedHash), nil
}
func HashSeedVarLen(seed *nockchain.NockchainSeed) ([5]uint64, error) {
belts := []crypto.Belt{{Value: 0}}
belts = append(belts, crypto.Belt{Value: seed.Recipient.KeysRequired})
for _, pk := range seed.Recipient.Pubkeys {
pkPoint, err := crypto.CheetaPointFromBytes(base58.Decode(pk))
if err != nil {
return [5]uint64{}, err
}
belts = append(belts, pkPoint.X[:]...)
belts = append(belts, pkPoint.Y[:]...)
}
belts = append(belts, []crypto.Belt{{Value: 1}, {Value: 0}, {Value: 0}, {Value: 0}, {Value: seed.Gift}}...)
parentHash := crypto.Base58ToTip5Hash(seed.ParentHash)
for _, i := range parentHash {
belts = append(belts, crypto.Belt{Value: i})
}
size := len(belts)
belts = append([]crypto.Belt{{Value: uint64(size)}}, belts...)
for _, i := range crypto.MagicDyckForSeed {
belts = append(belts, crypto.Belt{Value: i})
}
return crypto.Tip5HashBelts(belts), nil
}
func HashNonce(pkPoint crypto.CheetahPoint, message [5]uint64) ([]crypto.Belt, [5]uint64) {
belts := []crypto.Belt{}
for _, belt := range pkPoint.X {
@ -203,21 +226,83 @@ func HashSpend(spend *nockchain.NockchainSpend) ([5]uint64, error) {
return [5]uint64{}, err
}
seedsCount := len(spend.Seeds)
finalSeedHash, err := HashSeedWithoutSource(spend.Seeds[seedsCount-1])
var finalSeedHash [5]uint64
if seedsCount == 1 {
seedHash, err := HashSeedWithoutSource(spend.Seeds[0])
if err != nil {
return [5]uint64{}, err
}
if err != nil {
return [5]uint64{}, err
}
finalSeedHash = crypto.Tip5RehashTenCell(finalSeedHash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(seedHash, crypto.Tip5ZeroZero)
} else {
seed1Hash, err := HashSeedWithoutSource(spend.Seeds[0])
if err != nil {
return [5]uint64{}, err
}
seed1HashVarLen, err := HashSeedVarLen(spend.Seeds[0])
if err != nil {
return [5]uint64{}, err
}
seed1DoubleHash := crypto.Tip5RehashTenCell(seed1HashVarLen, seed1HashVarLen)
seed2Hash, err := HashSeedWithoutSource(spend.Seeds[1])
if err != nil {
return [5]uint64{}, err
}
seed2HashVarLen, err := HashSeedVarLen(spend.Seeds[1])
if err != nil {
return [5]uint64{}, err
}
seed2DoubleHash := crypto.Tip5RehashTenCell(seed2HashVarLen, seed2HashVarLen)
seedHash1BigInt := new(big.Int).SetBytes(base58.Decode(crypto.Tip5HashToBase58(seed1HashVarLen)))
seed1DoubleHashBigInt := new(big.Int).SetBytes(base58.Decode(crypto.Tip5HashToBase58(seed1DoubleHash)))
seedHash2BigInt := new(big.Int).SetBytes(base58.Decode(crypto.Tip5HashToBase58(seed2HashVarLen)))
seed2DoubleHashBigInt := new(big.Int).SetBytes(base58.Decode(crypto.Tip5HashToBase58(seed2DoubleHash)))
if seedHash1BigInt.Cmp(seedHash2BigInt) == -1 {
// seed 1 < seed 2
if seed1DoubleHashBigInt.Cmp(seed2DoubleHashBigInt) == -1 {
// seed1
// / \
// ~ seed2
// / \
// ~ ~
finalSeedHash = crypto.Tip5RehashTenCell(seed2Hash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(crypto.Tip5Zero, finalSeedHash)
finalSeedHash = crypto.Tip5RehashTenCell(seed1Hash, finalSeedHash)
} else {
// seed2
// / \
// seed1 ~
// / \
// ~ ~
finalSeedHash = crypto.Tip5RehashTenCell(seed1Hash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(finalSeedHash, crypto.Tip5Zero)
finalSeedHash = crypto.Tip5RehashTenCell(seed2Hash, finalSeedHash)
}
} else {
// seed 1 > seed 2
if seed1DoubleHashBigInt.Cmp(seed2DoubleHashBigInt) == -1 {
// seed1
// / \
// seed2 ~
// / \
// ~ ~
finalSeedHash = crypto.Tip5RehashTenCell(seed2Hash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(finalSeedHash, crypto.Tip5Zero)
finalSeedHash = crypto.Tip5RehashTenCell(seed1Hash, finalSeedHash)
} else {
// seed2
// / \
// ~ seed1
// / \
// ~ ~
finalSeedHash = crypto.Tip5RehashTenCell(seed1Hash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(crypto.Tip5Zero, finalSeedHash)
finalSeedHash = crypto.Tip5RehashTenCell(seed2Hash, finalSeedHash)
if seedsCount != 1 {
finalSeedHash = crypto.Tip5RehashTenCell(crypto.Tip5Zero, finalSeedHash)
for i := 1; i < seedsCount; i++ {
seedHash, err := HashSeedWithoutSource(spend.Seeds[seedsCount-1-i])
if err != nil {
return [5]uint64{}, err
}
finalSeedHash = crypto.Tip5RehashTenCell(seedHash, finalSeedHash)
}
}
feeHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: spend.Fee}})
@ -228,22 +313,83 @@ func HashSpend(spend *nockchain.NockchainSpend) ([5]uint64, error) {
func HashMsg(spend *nockchain.NockchainSpend) ([5]uint64, error) {
seedsCount := len(spend.Seeds)
finalSeedHash, err := HashSeed(spend.Seeds[seedsCount-1])
var finalSeedHash [5]uint64
if seedsCount == 1 {
seedHash, err := HashSeed(spend.Seeds[0])
if err != nil {
return [5]uint64{}, err
}
if err != nil {
return [5]uint64{}, err
}
finalSeedHash = crypto.Tip5RehashTenCell(finalSeedHash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(seedHash, crypto.Tip5ZeroZero)
} else {
seed1HashVarLen, err := HashSeedVarLen(spend.Seeds[0])
if err != nil {
return [5]uint64{}, err
}
seed1Hash, err := HashSeed(spend.Seeds[0])
if err != nil {
return [5]uint64{}, err
}
seed1DoubleHash := crypto.Tip5RehashTenCell(seed1HashVarLen, seed1HashVarLen)
seed2HashVarLen, err := HashSeedVarLen(spend.Seeds[1])
if err != nil {
return [5]uint64{}, err
}
seed2Hash, err := HashSeed(spend.Seeds[1])
if err != nil {
return [5]uint64{}, err
}
seed2DoubleHash := crypto.Tip5RehashTenCell(seed2HashVarLen, seed2HashVarLen)
if seedsCount != 1 {
finalSeedHash = crypto.Tip5RehashTenCell(crypto.Tip5Zero, finalSeedHash)
seedHash1BigInt := new(big.Int).SetBytes(base58.Decode(crypto.Tip5HashToBase58(seed1HashVarLen)))
seed1DoubleHashBigInt := new(big.Int).SetBytes(base58.Decode(crypto.Tip5HashToBase58(seed1DoubleHash)))
seedHash2BigInt := new(big.Int).SetBytes(base58.Decode(crypto.Tip5HashToBase58(seed2HashVarLen)))
seed2DoubleHashBigInt := new(big.Int).SetBytes(base58.Decode(crypto.Tip5HashToBase58(seed2DoubleHash)))
if seedHash1BigInt.Cmp(seedHash2BigInt) == -1 {
// seed 1 < seed 2
if seed1DoubleHashBigInt.Cmp(seed2DoubleHashBigInt) == -1 {
// seed1
// / \
// ~ seed2
// / \
// ~ ~
finalSeedHash = crypto.Tip5RehashTenCell(seed2Hash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(crypto.Tip5Zero, finalSeedHash)
finalSeedHash = crypto.Tip5RehashTenCell(seed1Hash, finalSeedHash)
} else {
// seed2
// / \
// seed1 ~
// / \
// ~ ~
finalSeedHash = crypto.Tip5RehashTenCell(seed1Hash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(finalSeedHash, crypto.Tip5Zero)
finalSeedHash = crypto.Tip5RehashTenCell(seed2Hash, finalSeedHash)
}
} else {
// seed 1 > seed 2
if seed1DoubleHashBigInt.Cmp(seed2DoubleHashBigInt) == -1 {
// seed1
// / \
// seed2 ~
// / \
// ~ ~
finalSeedHash = crypto.Tip5RehashTenCell(seed2Hash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(finalSeedHash, crypto.Tip5Zero)
finalSeedHash = crypto.Tip5RehashTenCell(seed1Hash, finalSeedHash)
} else {
// seed2
// / \
// ~ seed1
// / \
// ~ ~
finalSeedHash = crypto.Tip5RehashTenCell(seed1Hash, crypto.Tip5ZeroZero)
finalSeedHash = crypto.Tip5RehashTenCell(crypto.Tip5Zero, finalSeedHash)
finalSeedHash = crypto.Tip5RehashTenCell(seed2Hash, finalSeedHash)
for i := 1; i < seedsCount; i++ {
seedHash, err := HashSeed(spend.Seeds[seedsCount-1-i])
if err != nil {
return [5]uint64{}, err
}
finalSeedHash = crypto.Tip5RehashTenCell(seedHash, finalSeedHash)
}
}
feeHash := crypto.Tip5HashBelts([]crypto.Belt{{Value: 1}, {Value: spend.Fee}})