Skip to content

Commit

Permalink
fix(nft): cr proposal and cr proposal review remove payload signature
Browse files Browse the repository at this point in the history
  • Loading branch information
Houshoupei84 committed Aug 7, 2023
1 parent 0809d05 commit 18123de
Show file tree
Hide file tree
Showing 6 changed files with 325 additions and 110 deletions.
41 changes: 32 additions & 9 deletions core/transaction/crcproposalreviewtransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"bytes"
"errors"
"fmt"
"github.com/elastos/Elastos.ELA/core/contract"

"github.com/elastos/Elastos.ELA/blockchain"
"github.com/elastos/Elastos.ELA/common"
Expand Down Expand Up @@ -59,6 +60,25 @@ func (t *CRCProposalReviewTransaction) SpecialContextCheck() (result elaerr.ELAE
if !ok {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("invalid payload")), true
}
//todo compatible with old tx
programDID, err1 := getDIDFromCode(t.Programs()[0].Code)
if err1 != nil {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("can not create did from program code")), true
}
if !programDID.IsEqual(crcProposalReview.DID) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("program code not match with payload DID")), true
}
switch t.payloadVersion {
case payload.CRCProposalReviewVersion, payload.CRCProposalReviewVersion01:
if !contract.IsStandard(t.Programs()[0].Code) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("CRCProposalReviewVersion or CRCProposalReviewVersion01 match standard code")), true
}
case payload.CRCProposalReviewMultiSignVersion:
if !contract.IsMultiSig(t.Programs()[0].Code) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("CRCProposalReviewMultiSignVersion match multi code")), true
}
}

// Check if the proposal exist.
proposalState := t.parameters.BlockChain.GetCRCommittee().GetProposal(crcProposalReview.ProposalHash)
if proposalState == nil {
Expand Down Expand Up @@ -98,16 +118,19 @@ func (t *CRCProposalReviewTransaction) SpecialContextCheck() (result elaerr.ELAE
}

// check signature.
signedBuf := new(bytes.Buffer)
err := crcProposalReview.SerializeUnsigned(signedBuf, t.PayloadVersion())
if err != nil {
return elaerr.Simple(elaerr.ErrTxPayload, err), true
}
err = blockchain.CheckCRTransactionSignature(crcProposalReview.Signature, crMember.Info.Code,
signedBuf.Bytes())
if err != nil {
return elaerr.Simple(elaerr.ErrTxPayload, err), true
if t.PayloadVersion() < payload.CRCProposalReviewMultiSignVersion {
signedBuf := new(bytes.Buffer)
err := crcProposalReview.SerializeUnsigned(signedBuf, t.PayloadVersion())
if err != nil {
return elaerr.Simple(elaerr.ErrTxPayload, err), true
}
err = blockchain.CheckCRTransactionSignature(crcProposalReview.Signature, crMember.Info.Code,
signedBuf.Bytes())
if err != nil {
return elaerr.Simple(elaerr.ErrTxPayload, err), true
}
}

return nil, false
}

Expand Down
58 changes: 45 additions & 13 deletions core/transaction/crcproposaltransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,34 @@ func (t *CRCProposalTransaction) SpecialContextCheck() (result elaerr.ELAError,
if t.parameters.BlockChain.GetCRCommittee().IsProposalFull(proposal.CRCouncilMemberDID) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("proposal is full")), true
}
//todo compatible with old tx
programDID, err1 := getDIDFromCode(t.Programs()[0].Code)
if err1 != nil {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("can not create did from program code")), true
}
if !programDID.IsEqual(proposal.CRCouncilMemberDID) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("program code not match with payload CRCouncilCommitteeDID")), true
}
switch t.payloadVersion {
case payload.CRCProposalVersion, payload.CRCProposalVersion01:
if !contract.IsStandard(t.Programs()[0].Code) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("CRCProposalVersion or CRCProposalVersion01 match standard code")), true
}
case payload.CRCProposalMultiSignVersion:
if !contract.IsMultiSig(t.Programs()[0].Code) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("CRCProposalMultiSignVersion match multi code")), true
}
}

if len(proposal.OwnerKey) != 0 && len(proposal.OwnerKey) != 33 {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("OwnerKey must standard publickey")), true
}
if len(proposal.NewOwnerKey) != 0 && len(proposal.NewOwnerKey) != 33 {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("NewOwnerKey must standard publickey")), true
}
if len(proposal.SecretaryGeneralPublicKey) != 0 && len(proposal.SecretaryGeneralPublicKey) != 33 {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("SecretaryGeneralPublicKey must standard publickey")), true
}
// Check draft hash of proposal.
if t.parameters.BlockChain.GetCRCommittee().ExistDraft(proposal.DraftHash) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("duplicated draft proposal hash")), true
Expand Down Expand Up @@ -301,17 +329,18 @@ func (t *CRCProposalTransaction) checkOwnerAndCRCouncilMemberSign(proposal *payl
signedBuf.Bytes()); err != nil {
return errors.New("owner signature check failed")
}

// Check signature of CR Council Member.
if err = common.WriteVarBytes(signedBuf, proposal.Signature); err != nil {
return errors.New("failed to write proposal owner signature")
}
if err = proposal.CRCouncilMemberDID.Serialize(signedBuf); err != nil {
return errors.New("failed to write CR Council Member's DID")
}
if err = blockchain.CheckCRTransactionSignature(proposal.CRCouncilMemberSignature, crMemberCode,
signedBuf.Bytes()); err != nil {
return errors.New("failed to check CR Council Member signature")
if PayloadVersion < payload.CRCProposalMultiSignVersion {
// Check signature of CR Council Member.
if err = common.WriteVarBytes(signedBuf, proposal.Signature); err != nil {
return errors.New("failed to write proposal owner signature")
}
if err = proposal.CRCouncilMemberDID.Serialize(signedBuf); err != nil {
return errors.New("failed to write CR Council Member's DID")
}
if err = blockchain.CheckCRTransactionSignature(proposal.CRCouncilMemberSignature, crMemberCode,
signedBuf.Bytes()); err != nil {
return errors.New("failed to check CR Council Member signature")
}
}
return nil
}
Expand Down Expand Up @@ -346,9 +375,12 @@ func (t *CRCProposalTransaction) checkChangeSecretaryGeneralProposalTx(params *T
if crMember == nil {
return errors.New("CR Council Member should be one of the CR members")
}
if err := checkProposalCRCouncilMemberSign(crcProposal, crMember.Info.Code, signedBuf); err != nil {
return errors.New("CR Council Member signature check failed")
if PayloadVersion < payload.CRCProposalMultiSignVersion {
if err := checkProposalCRCouncilMemberSign(crcProposal, crMember.Info.Code, signedBuf); err != nil {
return errors.New("CR Council Member signature check failed")
}
}

return nil
}

Expand Down
191 changes: 153 additions & 38 deletions core/transaction/crcproposaltransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (s *txValidatorTestSuite) TestCheckSecretaryGeneralProposalTransaction() {
s.Chain.GetCRCommittee().NeedAppropriation = false

//owner not elected cr
txn := s.getSecretaryGeneralCRCProposalTx(ownerPublicKeyStr1, ownerPrivateKeyStr1, crPublicKeyStr, crPrivateKeyStr,
txn := s.getSecretaryGeneralCRCProposalTx2(ownerPublicKeyStr1, ownerPrivateKeyStr1, crPublicKeyStr, crPrivateKeyStr,
secretaryPublicKeyStr, secretaryPrivateKeyStr)

//CRCouncilMember not elected cr
Expand Down Expand Up @@ -170,6 +170,68 @@ func (s *txValidatorTestSuite) getSecretaryGeneralCRCProposalTx(ownerPublicKeySt
return txn
}

func (s *txValidatorTestSuite) getSecretaryGeneralCRCProposalTx2(ownerPublicKeyStr, ownerPrivateKeyStr,
crPublicKeyStr, crPrivateKeyStr, secretaryPublicKeyStr, secretaryPrivateKeyStr string) interfaces.Transaction {

ownerPublicKey, _ := common.HexStringToBytes(ownerPublicKeyStr)
ownerPrivateKey, _ := common.HexStringToBytes(ownerPrivateKeyStr)

secretaryPublicKey, _ := common.HexStringToBytes(secretaryPublicKeyStr)
secretaryGeneralDID, _ := blockchain.GetDiDFromPublicKey(secretaryPublicKey)
secretaryGeneralPrivateKey, _ := common.HexStringToBytes(secretaryPrivateKeyStr)

//crPrivateKey, _ := common.HexStringToBytes(crPrivateKeyStr)
//crCode := getCodeByPubKeyStr(crPublicKeyStr)
ownerCode := getCodeByPubKeyStr(ownerPublicKeyStr)
draftData := randomBytes(10)
txn := functions.CreateTransaction(
common2.TxVersion09,
common2.CRCProposal,
0,
nil,
[]*common2.Attribute{},
[]*common2.Input{},
[]*common2.Output{},
0,
[]*program.Program{},
)
recipient := *randomUint168()
recipient[0] = uint8(contract.PrefixStandard)
//crDID, _ := blockchain.GetDIDFromCode(crCode)
ownerDID, _ := blockchain.GetDIDFromCode(ownerCode)
crcProposalPayload := &payload.CRCProposal{
ProposalType: payload.SecretaryGeneral,
CategoryData: "111",
OwnerKey: ownerPublicKey,
DraftHash: common.Hash(draftData),
SecretaryGeneralPublicKey: secretaryPublicKey,
SecretaryGeneralDID: *secretaryGeneralDID,
CRCouncilMemberDID: *ownerDID,
//NewOwnerKey: randomBytes(33),
}

signBuf := new(bytes.Buffer)
crcProposalPayload.SerializeUnsigned(signBuf, payload.CRCProposalVersion)
sig, _ := crypto.Sign(ownerPrivateKey, signBuf.Bytes())
crcProposalPayload.Signature = sig

secretaryGeneralSig, _ := crypto.Sign(secretaryGeneralPrivateKey, signBuf.Bytes())
crcProposalPayload.SecretaryGeneraSignature = secretaryGeneralSig

common.WriteVarBytes(signBuf, sig)
common.WriteVarBytes(signBuf, secretaryGeneralSig)
crcProposalPayload.CRCouncilMemberDID.Serialize(signBuf)
crSig, _ := crypto.Sign(ownerPrivateKey, signBuf.Bytes())
crcProposalPayload.CRCouncilMemberSignature = crSig

txn.SetPayload(crcProposalPayload)
txn.SetPrograms([]*program.Program{{
Code: getCodeByPubKeyStr(ownerPublicKeyStr),
Parameter: nil,
}})
return txn
}

func (s *txValidatorTestSuite) TestCheckCRCProposalRegisterSideChainTransaction() {
publicKeyStr1 := "02f981e4dae4983a5d284d01609ad735e3242c5672bb2c7bb0018cc36f9ab0c4a5"
privateKeyStr1 := "15e0947580575a9b6729570bed6360a890f84a07dc837922fe92275feec837d4"
Expand Down Expand Up @@ -211,38 +273,38 @@ func (s *txValidatorTestSuite) TestCheckCRCProposalRegisterSideChainTransaction(
s.EqualError(err, "transaction validate error: payload content invalid:GenesisHash can not be empty")
}

{
txn := s.getCRCRegisterSideChainProposalTx(publicKeyStr2, privateKeyStr2, publicKeyStr1, privateKeyStr1)
payload, _ := txn.Payload().(*payload.CRCProposal)
payload.SideChainName = ""
txn = CreateTransactionByType(txn, s.Chain)
txn.SetParameters(&TransactionParameters{
Transaction: txn,
BlockHeight: tenureHeight,
TimeStamp: s.Chain.BestChain.Timestamp,
Config: s.Chain.GetParams(),
BlockChain: s.Chain,
ProposalsUsedAmount: 0,
})
err, _ := txn.SpecialContextCheck()
s.EqualError(err, "transaction validate error: payload content invalid:SideChainName can not be empty")
}

{
s.Chain.GetCRCommittee().GetProposalManager().RegisteredSideChainNames = []string{"NEO"}
txn := s.getCRCRegisterSideChainProposalTx(publicKeyStr2, privateKeyStr2, publicKeyStr1, privateKeyStr1)
txn = CreateTransactionByType(txn, s.Chain)
txn.SetParameters(&TransactionParameters{
Transaction: txn,
BlockHeight: tenureHeight,
TimeStamp: s.Chain.BestChain.Timestamp,
Config: s.Chain.GetParams(),
BlockChain: s.Chain,
ProposalsUsedAmount: 0,
})
err, _ := txn.SpecialContextCheck()
s.EqualError(err, "transaction validate error: payload content invalid:SideChainName already registered")
}
//{
// txn := s.getCRCRegisterSideChainProposalTx(publicKeyStr2, privateKeyStr2, publicKeyStr1, privateKeyStr1)
// payload, _ := txn.Payload().(*payload.CRCProposal)
// payload.SideChainName = ""
// txn = CreateTransactionByType(txn, s.Chain)
// txn.SetParameters(&TransactionParameters{
// Transaction: txn,
// BlockHeight: tenureHeight,
// TimeStamp: s.Chain.BestChain.Timestamp,
// Config: s.Chain.GetParams(),
// BlockChain: s.Chain,
// ProposalsUsedAmount: 0,
// })
// err, _ := txn.SpecialContextCheck()
// s.EqualError(err, "transaction validate error: payload content invalid:SideChainName can not be empty")
//}
//
//{
// s.Chain.GetCRCommittee().GetProposalManager().RegisteredSideChainNames = []string{"NEO"}
// txn := s.getCRCRegisterSideChainProposalTx(publicKeyStr2, privateKeyStr2, publicKeyStr1, privateKeyStr1)
// txn = CreateTransactionByType(txn, s.Chain)
// txn.SetParameters(&TransactionParameters{
// Transaction: txn,
// BlockHeight: tenureHeight,
// TimeStamp: s.Chain.BestChain.Timestamp,
// Config: s.Chain.GetParams(),
// BlockChain: s.Chain,
// ProposalsUsedAmount: 0,
// })
// err, _ := txn.SpecialContextCheck()
// s.EqualError(err, "transaction validate error: payload content invalid:SideChainName already registered")
//}

}

Expand Down Expand Up @@ -294,7 +356,7 @@ func (s *txValidatorTestSuite) getCRCRegisterSideChainProposalTx(publicKeyStr, p

txn.SetPayload(crcProposalPayload)
txn.SetPrograms([]*program.Program{{
Code: getCodeByPubKeyStr(publicKeyStr),
Code: getCodeByPubKeyStr(crPublicKeyStr),
Parameter: nil,
}})
return txn
Expand Down Expand Up @@ -685,6 +747,59 @@ func (s *txValidatorTestSuite) getCRCProposalTx(publicKeyStr, privateKeyStr,
crSig, _ := crypto.Sign(privateKey2, signBuf.Bytes())
crcProposalPayload.CRCouncilMemberSignature = crSig

txn.SetPayload(crcProposalPayload)
txn.SetPrograms([]*program.Program{{
Code: code2,
Parameter: nil,
}})
return txn
}

func (s *txValidatorTestSuite) getCRCProposalTx2(publicKeyStr, privateKeyStr,
crPublicKeyStr, crPrivateKeyStr string) interfaces.Transaction {

publicKey1, _ := common.HexStringToBytes(publicKeyStr)
privateKey1, _ := common.HexStringToBytes(privateKeyStr)

//privateKey2, _ := common.HexStringToBytes(crPrivateKeyStr)
code2 := getCodeByPubKeyStr(publicKeyStr)

draftData := randomBytes(10)

txn := functions.CreateTransaction(
common2.TxVersion09,
common2.CRCProposal,
0,
nil,
[]*common2.Attribute{},
[]*common2.Input{},
[]*common2.Output{},
0,
[]*program.Program{},
)

recipient := *randomUint168()
recipient[0] = uint8(contract.PrefixStandard)
did2, _ := blockchain.GetDIDFromCode(code2)
crcProposalPayload := &payload.CRCProposal{
ProposalType: payload.Normal,
OwnerKey: publicKey1,
CRCouncilMemberDID: *did2,
DraftHash: common.Hash(draftData),
Budgets: createBudgets(3),
Recipient: recipient,
}

signBuf := new(bytes.Buffer)
crcProposalPayload.SerializeUnsigned(signBuf, payload.CRCProposalVersion)
sig, _ := crypto.Sign(privateKey1, signBuf.Bytes())
crcProposalPayload.Signature = sig

common.WriteVarBytes(signBuf, sig)
crcProposalPayload.CRCouncilMemberDID.Serialize(signBuf)
crSig, _ := crypto.Sign(privateKey1, signBuf.Bytes())
crcProposalPayload.CRCouncilMemberSignature = crSig

txn.SetPayload(crcProposalPayload)
txn.SetPrograms([]*program.Program{{
Code: getCodeByPubKeyStr(publicKeyStr),
Expand Down Expand Up @@ -736,7 +851,7 @@ func (s *txValidatorTestSuite) getCRChangeProposalOwnerProposalTx(publicKeyStr,

txn.SetPayload(crcProposalPayload)
txn.SetPrograms([]*program.Program{{
Code: getCodeByPubKeyStr(publicKeyStr),
Code: getCodeByPubKeyStr(crPublicKeyStr),
Parameter: nil,
}})
return txn
Expand Down Expand Up @@ -829,7 +944,7 @@ func (s *txValidatorTestSuite) getCRCCloseProposalTxWithHash(publicKeyStr, priva

txn.SetPayload(crcProposalPayload)
txn.SetPrograms([]*program.Program{{
Code: getCodeByPubKeyStr(publicKeyStr),
Code: getCodeByPubKeyStr(crPublicKeyStr),
Parameter: nil,
}})
return txn
Expand Down Expand Up @@ -880,7 +995,7 @@ func (s *txValidatorTestSuite) getCRCCloseProposalTx(publicKeyStr, privateKeyStr

txn.SetPayload(crcProposalPayload)
txn.SetPrograms([]*program.Program{{
Code: getCodeByPubKeyStr(publicKeyStr),
Code: getCodeByPubKeyStr(crPublicKeyStr),
Parameter: nil,
}})
return txn
Expand Down Expand Up @@ -931,7 +1046,7 @@ func (s *txValidatorTestSuite) getCRCReservedCustomIDProposalTx(publicKeyStr, pr

txn.SetPayload(crcProposalPayload)
txn.SetPrograms([]*program.Program{{
Code: getCodeByPubKeyStr(publicKeyStr),
Code: getCodeByPubKeyStr(crPublicKeyStr),
Parameter: nil,
}})
return txn
Expand Down
Loading

0 comments on commit 18123de

Please sign in to comment.